Refactor CellSetExplicit to remove NumIndices.

See #408 for details.
This commit is contained in:
Allison Vacanti 2019-08-30 13:04:17 -04:00
parent b2daec0e35
commit 3886b7dfb8
36 changed files with 1019 additions and 1112 deletions

@ -646,11 +646,11 @@ class BenchmarkFilters
} }
} }
template <typename T1, typename T2, typename T3, typename T4> template <typename T1, typename T2, typename T3>
VTKM_CONT void operator()(const vtkm::cont::CellSetExplicit<T1, T2, T3, T4>& cellSet) const VTKM_CONT void operator()(const vtkm::cont::CellSetExplicit<T1, T2, T3>& cellSet) const
{ {
{ // Why does CastAndCall insist on making the cellset const? { // Why does CastAndCall insist on making the cellset const?
using CellSetT = vtkm::cont::CellSetExplicit<T1, T2, T3, T4>; using CellSetT = vtkm::cont::CellSetExplicit<T1, T2, T3>;
CellSetT& mcellSet = const_cast<CellSetT&>(cellSet); CellSetT& mcellSet = const_cast<CellSetT&>(cellSet);
mcellSet.ResetConnectivity(vtkm::TopologyElementTagPoint{}, mcellSet.ResetConnectivity(vtkm::TopologyElementTagPoint{},
vtkm::TopologyElementTagCell{}); vtkm::TopologyElementTagCell{});

@ -0,0 +1,70 @@
# `CellSetExplicit` Refactoring
The `CellSetExplicit` class has been refactored to remove the `NumIndices`
array. This information is now derived from the `Offsets` array, which has
been changed to contain `[numCells + 1]` entries.
```
Old Layout:
-----------
NumIndices: [ 2, 4, 3, 3, 2 ]
IndexOffset: [ 0, 2, 6, 9, 12 ]
Connectivity: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
New Layout:
-----------
Offsets: [ 0, 2, 6, 9, 12, 14 ]
Connectivity: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
```
This will reduce the memory overhead of the cellset by roughly `[numCells * 4]`
bytes.
The `IndexOffset` array / typedefs / methods have been renamed to `Offsets` for
brevity and consistency (similar members were plural, e.g. `Shapes`).
The `NumIndices` array can be recovered from the `Offsets` array by using an
`ArrayHandleDecorator`. This is done automatically by the
`CellSetExplicit::GetNumIndicesArray` method.
The `CellSetExplicit::Fill` signature has changed to remove `numIndices` as a
parameter and to require the `offsets` array as a non-optional argument. To
assist in porting old code, an `offsets` array can be generated from
`numIndices` using the new `vtkm::cont::ConvertNumIndicesToOffsets` methods,
defined in `CellSetExplicit.h`.
```
vtkm::Id numPoints = ...;
auto cellShapes = ...;
auto numIndices = ...;
auto connectivity = ...;
vtkm::cont::CellSetExplicit<> cellSet = ...;
// Old:
cellSet.Fill(numPoints, cellShapes, numIndices, connectivity);
// New:
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
cellSet.Fill(numPoints, cellShapes, connectivity, offsets);
```
Since the `offsets` array now contains an additional offset at the end, it
cannot be used directly with `ArrayHandleGroupVecVariable` with the cellset's
`connectivity` array to create an array handle containing cell definitions.
This now requires an `ArrayHandleView` to trim the last value off of the array:
```
vtkm::cont::CellSetExplicit<> cellSet = ...;
auto offsets = cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{});
auto conn = cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{});
// Old:
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
// New:
const vtkm::Id numCells = offsets.GetNumberOfValues - 1;
auto offsetsTrim = vtkm::cont::make_ArrayHandleView(offsets, 0, numCells);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
```

@ -29,7 +29,7 @@ template <vtkm::IdComponent>
class CellSetStructured; class CellSetStructured;
template <typename T> template <typename T>
class CellSetSingleType; class CellSetSingleType;
template <typename T, typename S, typename U, typename V> template <typename T, typename S, typename U>
class CellSetExplicit; class CellSetExplicit;
template <typename T, typename S> template <typename T, typename S>
class CellSetPermutation; class CellSetPermutation;
@ -88,10 +88,8 @@ void CastAndCall(const vtkm::cont::CellSetSingleType<ConnectivityStorageTag>& ce
/// A specialization of CastAndCall for basic CellSetExplicit types, /// A specialization of CastAndCall for basic CellSetExplicit types,
/// Since the type is already known no deduction is needed. /// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms /// This specialization is used to simplify numerous worklet algorithms
template <typename T, typename S, typename U, typename V, typename Functor, typename... Args> template <typename T, typename S, typename U, typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetExplicit<T, S, U, V>& cellset, void CastAndCall(const vtkm::cont::CellSetExplicit<T, S, U>& cellset, Functor&& f, Args&&... args)
Functor&& f,
Args&&... args)
{ {
f(cellset, std::forward<Args>(args)...); f(cellset, std::forward<Args>(args)...);
} }

@ -19,7 +19,6 @@ namespace cont
template class VTKM_CONT_EXPORT CellSetExplicit<>; // default template class VTKM_CONT_EXPORT CellSetExplicit<>; // default
template class VTKM_CONT_EXPORT template class VTKM_CONT_EXPORT
CellSetExplicit<typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag, CellSetExplicit<typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>; typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>;
} }

@ -12,8 +12,11 @@
#include <vtkm/CellShape.h> #include <vtkm/CellShape.h>
#include <vtkm/TopologyElementTag.h> #include <vtkm/TopologyElementTag.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleConstant.h> #include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h> #include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleDecorator.h>
#include <vtkm/cont/CellSet.h> #include <vtkm/cont/CellSet.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h> #include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/exec/ConnectivityExplicit.h> #include <vtkm/exec/ConnectivityExplicit.h>
@ -34,14 +37,35 @@ struct CellSetExplicitConnectivityChooser
using ConnectivityType = vtkm::cont::internal::ConnectivityExplicitInternals<>; using ConnectivityType = vtkm::cont::internal::ConnectivityExplicitInternals<>;
}; };
// Used with ArrayHandleDecorator to recover the NumIndices array from the
// offsets.
struct NumIndicesDecorator
{
template <typename OffsetsPortal>
struct Functor
{
OffsetsPortal Offsets;
VTKM_EXEC_CONT
vtkm::IdComponent operator()(vtkm::Id cellId) const
{
return static_cast<vtkm::IdComponent>(this->Offsets.Get(cellId + 1) -
this->Offsets.Get(cellId));
}
};
template <typename OffsetsPortal>
static VTKM_CONT Functor<typename std::decay<OffsetsPortal>::type> CreateFunctor(
OffsetsPortal&& portal)
{
return { std::forward<OffsetsPortal>(portal) };
}
};
} // namespace detail } // namespace detail
#ifndef VTKM_DEFAULT_SHAPE_STORAGE_TAG #ifndef VTKM_DEFAULT_SHAPES_STORAGE_TAG
#define VTKM_DEFAULT_SHAPE_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG #define VTKM_DEFAULT_SHAPES_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG
#endif
#ifndef VTKM_DEFAULT_NUM_INDICES_STORAGE_TAG
#define VTKM_DEFAULT_NUM_INDICES_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG
#endif #endif
#ifndef VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG #ifndef VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG
@ -52,51 +76,89 @@ struct CellSetExplicitConnectivityChooser
#define VTKM_DEFAULT_OFFSETS_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG #define VTKM_DEFAULT_OFFSETS_STORAGE_TAG VTKM_DEFAULT_STORAGE_TAG
#endif #endif
template <typename ShapeStorageTag = VTKM_DEFAULT_SHAPE_STORAGE_TAG, template <typename S1, typename S2>
typename NumIndicesStorageTag = VTKM_DEFAULT_NUM_INDICES_STORAGE_TAG, void ConvertNumIndicesToOffsets(const vtkm::cont::ArrayHandle<vtkm::Id, S1>& numIndices,
vtkm::cont::ArrayHandle<vtkm::Id, S2>& offsets)
{
vtkm::cont::Algorithm::ScanExtended(numIndices, offsets);
}
template <typename T, typename S1, typename S2>
void ConvertNumIndicesToOffsets(const vtkm::cont::ArrayHandle<T, S1>& numIndices,
vtkm::cont::ArrayHandle<vtkm::Id, S2>& offsets)
{
const auto castCounts = vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numIndices);
ConvertNumIndicesToOffsets(castCounts, offsets);
}
template <typename T, typename S1, typename S2>
void ConvertNumIndicesToOffsets(const vtkm::cont::ArrayHandle<T, S1>& numIndices,
vtkm::cont::ArrayHandle<vtkm::Id, S2>& offsets,
vtkm::Id& connectivitySize /* outparam */)
{
ConvertNumIndicesToOffsets(numIndices, offsets);
connectivitySize = vtkm::cont::ArrayGetValue(offsets.GetNumberOfValues() - 1, offsets);
}
template <typename T, typename S>
vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumIndicesToOffsets(
const vtkm::cont::ArrayHandle<T, S>& numIndices)
{
vtkm::cont::ArrayHandle<vtkm::Id> offsets;
ConvertNumIndicesToOffsets(numIndices, offsets);
return offsets;
}
template <typename T, typename S>
vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumIndicesToOffsets(
const vtkm::cont::ArrayHandle<T, S>& numIndices,
vtkm::Id& connectivityLength /* outparam */)
{
vtkm::cont::ArrayHandle<vtkm::Id> offsets;
ConvertNumIndicesToOffsets(numIndices, offsets, connectivityLength);
return offsets;
}
template <typename ShapesStorageTag = VTKM_DEFAULT_SHAPES_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename OffsetsStorageTag = VTKM_DEFAULT_OFFSETS_STORAGE_TAG> typename OffsetsStorageTag = VTKM_DEFAULT_OFFSETS_STORAGE_TAG>
class VTKM_ALWAYS_EXPORT CellSetExplicit : public CellSet class VTKM_ALWAYS_EXPORT CellSetExplicit : public CellSet
{ {
using Thisclass = CellSetExplicit<ShapeStorageTag, using Thisclass = CellSetExplicit<ShapesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>;
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>;
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
struct ConnectivityChooser struct ConnectivityChooser
{ {
using ConnectivityType = private:
typename detail::CellSetExplicitConnectivityChooser<Thisclass, using Chooser = typename detail::CellSetExplicitConnectivityChooser<Thisclass,
VisitTopology, VisitTopology,
IncidentTopology>::ConnectivityType; IncidentTopology>;
using ShapeArrayType = typename ConnectivityType::ShapeArrayType; public:
using NumIndicesArrayType = typename ConnectivityType::NumIndicesArrayType; using ConnectivityType = typename Chooser::ConnectivityType;
using ShapesArrayType = typename ConnectivityType::ShapesArrayType;
using ConnectivityArrayType = typename ConnectivityType::ConnectivityArrayType; using ConnectivityArrayType = typename ConnectivityType::ConnectivityArrayType;
using IndexOffsetArrayType = typename ConnectivityType::IndexOffsetArrayType; using OffsetsArrayType = typename ConnectivityType::OffsetsArrayType;
using NumIndicesArrayType =
vtkm::cont::ArrayHandleDecorator<detail::NumIndicesDecorator, OffsetsArrayType>;
}; };
using VisitCellsWithPointsInternalsType = using ConnTypes =
typename ConnectivityChooser<vtkm::TopologyElementTagCell, ConnectivityChooser<vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>;
vtkm::TopologyElementTagPoint>::ConnectivityType; using RConnTypes =
ConnectivityChooser<vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell>;
using VisitPointsWithCellsInternalsType = using CellPointIdsType = typename ConnTypes::ConnectivityType;
typename ConnectivityChooser<vtkm::TopologyElementTagPoint, using PointCellIdsType = typename RConnTypes::ConnectivityType;
vtkm::TopologyElementTagCell>::ConnectivityType;
public: public:
using SchedulingRangeType = vtkm::Id; using SchedulingRangeType = vtkm::Id;
//point to cell is used when iterating cells and asking for point properties using ShapesArrayType = typename CellPointIdsType::ShapesArrayType;
using VisitCellsWithPointsConnectivityType = using ConnectivityArrayType = typename CellPointIdsType::ConnectivityArrayType;
ConnectivityChooser<vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>; using OffsetsArrayType = typename CellPointIdsType::OffsetsArrayType;
using NumIndicesArrayType = typename ConnTypes::NumIndicesArrayType;
using ShapeArrayType = typename VisitCellsWithPointsConnectivityType::ShapeArrayType;
using NumIndicesArrayType = typename VisitCellsWithPointsConnectivityType::NumIndicesArrayType;
using ConnectivityArrayType =
typename VisitCellsWithPointsConnectivityType::ConnectivityArrayType;
using IndexOffsetArrayType = typename VisitCellsWithPointsConnectivityType::IndexOffsetArrayType;
VTKM_CONT CellSetExplicit(); VTKM_CONT CellSetExplicit();
VTKM_CONT CellSetExplicit(const Thisclass& src); VTKM_CONT CellSetExplicit(const Thisclass& src);
@ -105,28 +167,29 @@ public:
VTKM_CONT Thisclass& operator=(const Thisclass& src); VTKM_CONT Thisclass& operator=(const Thisclass& src);
VTKM_CONT Thisclass& operator=(Thisclass&& src) noexcept; VTKM_CONT Thisclass& operator=(Thisclass&& src) noexcept;
virtual ~CellSetExplicit(); VTKM_CONT virtual ~CellSetExplicit();
vtkm::Id GetNumberOfCells() const override; VTKM_CONT vtkm::Id GetNumberOfCells() const override;
vtkm::Id GetNumberOfPoints() const override; VTKM_CONT vtkm::Id GetNumberOfPoints() const override;
vtkm::Id GetNumberOfFaces() const override; VTKM_CONT vtkm::Id GetNumberOfFaces() const override;
vtkm::Id GetNumberOfEdges() const override; VTKM_CONT vtkm::Id GetNumberOfEdges() const override;
void PrintSummary(std::ostream& out) const override; VTKM_CONT void PrintSummary(std::ostream& out) const override;
void ReleaseResourcesExecution() override;
std::shared_ptr<CellSet> NewInstance() const override; VTKM_CONT void ReleaseResourcesExecution() override;
void DeepCopy(const CellSet* src) override;
VTKM_CONT std::shared_ptr<CellSet> NewInstance() const override;
VTKM_CONT void DeepCopy(const CellSet* src) override;
VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagCell) const; VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagCell) const;
VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagPoint) const; VTKM_CONT vtkm::Id GetSchedulingRange(vtkm::TopologyElementTagPoint) const;
VTKM_CONT vtkm::IdComponent GetNumberOfPointsInCell(vtkm::Id cellIndex) const override; VTKM_CONT vtkm::IdComponent GetNumberOfPointsInCell(vtkm::Id cellid) const override;
void GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const override; VTKM_CONT void GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const override;
VTKM_CONT vtkm::UInt8 GetCellShape(vtkm::Id cellIndex) const override; VTKM_CONT vtkm::UInt8 GetCellShape(vtkm::Id cellid) const override;
template <vtkm::IdComponent ItemTupleLength> template <vtkm::IdComponent NumIndices>
VTKM_CONT void GetIndices(vtkm::Id index, vtkm::Vec<vtkm::Id, ItemTupleLength>& ids) const; VTKM_CONT void GetIndices(vtkm::Id index, vtkm::Vec<vtkm::Id, NumIndices>& ids) const;
VTKM_CONT void GetIndices(vtkm::Id index, vtkm::cont::ArrayHandle<vtkm::Id>& ids) const; VTKM_CONT void GetIndices(vtkm::Id index, vtkm::cont::ArrayHandle<vtkm::Id>& ids) const;
@ -143,74 +206,69 @@ public:
/// the way you can fill the memory from another system without copying /// the way you can fill the memory from another system without copying
VTKM_CONT VTKM_CONT
void Fill(vtkm::Id numPoints, void Fill(vtkm::Id numPoints,
const vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorageTag>& cellTypes, const vtkm::cont::ArrayHandle<vtkm::UInt8, ShapesStorageTag>& cellTypes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageTag>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>& connectivity,
const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>& offsets = const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>& offsets);
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>());
template <typename DeviceAdapter, typename VisitTopology, typename IncidentTopology> template <typename Device, typename VisitTopology, typename IncidentTopology>
struct ExecutionTypes struct ExecutionTypes
{ {
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapter); private:
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
VTKM_IS_TOPOLOGY_ELEMENT_TAG(VisitTopology); VTKM_IS_TOPOLOGY_ELEMENT_TAG(VisitTopology);
VTKM_IS_TOPOLOGY_ELEMENT_TAG(IncidentTopology); VTKM_IS_TOPOLOGY_ELEMENT_TAG(IncidentTopology);
using ConnectivityTypes = ConnectivityChooser<VisitTopology, IncidentTopology>; using Chooser = ConnectivityChooser<VisitTopology, IncidentTopology>;
using ShapePortalType = typename ConnectivityTypes::ShapeArrayType::template ExecutionTypes< using ShapesAT = typename Chooser::ShapesArrayType;
DeviceAdapter>::PortalConst; using ConnAT = typename Chooser::ConnectivityArrayType;
using IndicePortalType = using OffsetsAT = typename Chooser::OffsetsArrayType;
typename ConnectivityTypes::NumIndicesArrayType::template ExecutionTypes<
DeviceAdapter>::PortalConst;
using ConnectivityPortalType =
typename ConnectivityTypes::ConnectivityArrayType::template ExecutionTypes<
DeviceAdapter>::PortalConst;
using IndexOffsetPortalType =
typename ConnectivityTypes::IndexOffsetArrayType::template ExecutionTypes<
DeviceAdapter>::PortalConst;
using ExecObjectType = vtkm::exec::ConnectivityExplicit<ShapePortalType, using ShapesET = typename ShapesAT::template ExecutionTypes<Device>;
IndicePortalType, using ConnET = typename ConnAT::template ExecutionTypes<Device>;
ConnectivityPortalType, using OffsetsET = typename OffsetsAT::template ExecutionTypes<Device>;
IndexOffsetPortalType>;
public:
using ShapesPortalType = typename ShapesET::PortalConst;
using ConnectivityPortalType = typename ConnET::PortalConst;
using OffsetsPortalType = typename OffsetsET::PortalConst;
using ExecObjectType =
vtkm::exec::ConnectivityExplicit<ShapesPortalType, ConnectivityPortalType, OffsetsPortalType>;
}; };
template <typename Device, typename VisitTopology, typename IncidentTopology> template <typename Device, typename VisitTopology, typename IncidentTopology>
typename ExecutionTypes<Device, VisitTopology, IncidentTopology>::ExecObjectType VTKM_CONT typename ExecutionTypes<Device, VisitTopology, IncidentTopology>::ExecObjectType
PrepareForInput(Device, VisitTopology, IncidentTopology) const; PrepareForInput(Device, VisitTopology, IncidentTopology) const;
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT const typename ConnectivityChooser<VisitTopology, IncidentTopology>::ShapeArrayType& VTKM_CONT const typename ConnectivityChooser<VisitTopology, IncidentTopology>::ShapesArrayType&
GetShapesArray(VisitTopology, IncidentTopology) const; GetShapesArray(VisitTopology, IncidentTopology) const;
template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT const typename ConnectivityChooser<VisitTopology,
IncidentTopology>::NumIndicesArrayType&
GetNumIndicesArray(VisitTopology, IncidentTopology) const;
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT const typename ConnectivityChooser<VisitTopology, VTKM_CONT const typename ConnectivityChooser<VisitTopology,
IncidentTopology>::ConnectivityArrayType& IncidentTopology>::ConnectivityArrayType&
GetConnectivityArray(VisitTopology, IncidentTopology) const; GetConnectivityArray(VisitTopology, IncidentTopology) const;
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT const typename ConnectivityChooser<VisitTopology, VTKM_CONT const typename ConnectivityChooser<VisitTopology, IncidentTopology>::OffsetsArrayType&
IncidentTopology>::IndexOffsetArrayType& GetOffsetsArray(VisitTopology, IncidentTopology) const;
GetIndexOffsetArray(VisitTopology, IncidentTopology) const;
// Can be used to check if e.g. CellToPoint table is built.
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT bool HasConnectivity(VisitTopology from, IncidentTopology to) const VTKM_CONT typename ConnectivityChooser<VisitTopology, IncidentTopology>::NumIndicesArrayType
GetNumIndicesArray(VisitTopology, IncidentTopology) const;
template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT bool HasConnectivity(VisitTopology visit, IncidentTopology incident) const
{ {
return this->HasConnectivityImpl(from, to); return this->HasConnectivityImpl(visit, incident);
} }
// Can be used to reset a connectivity table, mostly useful for benchmarking. // Can be used to reset a connectivity table, mostly useful for benchmarking.
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT void ResetConnectivity(VisitTopology from, IncidentTopology to) VTKM_CONT void ResetConnectivity(VisitTopology visit, IncidentTopology incident)
{ {
this->ResetConnectivityImpl(from, to); this->ResetConnectivityImpl(visit, incident);
} }
protected: protected:
@ -225,20 +283,20 @@ protected:
VTKM_CONT bool HasConnectivityImpl(vtkm::TopologyElementTagCell, VTKM_CONT bool HasConnectivityImpl(vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const vtkm::TopologyElementTagPoint) const
{ {
return this->Data->VisitCellsWithPoints.ElementsValid; return this->Data->CellPointIds.ElementsValid;
} }
VTKM_CONT bool HasConnectivityImpl(vtkm::TopologyElementTagPoint, VTKM_CONT bool HasConnectivityImpl(vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const vtkm::TopologyElementTagCell) const
{ {
return this->Data->VisitPointsWithCells.ElementsValid; return this->Data->PointCellIds.ElementsValid;
} }
VTKM_CONT void ResetConnectivityImpl(vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint) VTKM_CONT void ResetConnectivityImpl(vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint)
{ {
// Reset entire cell set // Reset entire cell set
this->Data->VisitCellsWithPoints = VisitCellsWithPointsInternalsType{}; this->Data->CellPointIds = CellPointIdsType{};
this->Data->VisitPointsWithCells = VisitPointsWithCellsInternalsType{}; this->Data->PointCellIds = PointCellIdsType{};
this->Data->ConnectivityAdded = -1; this->Data->ConnectivityAdded = -1;
this->Data->NumberOfCellsAdded = -1; this->Data->NumberOfCellsAdded = -1;
this->Data->NumberOfPoints = 0; this->Data->NumberOfPoints = 0;
@ -246,15 +304,15 @@ protected:
VTKM_CONT void ResetConnectivityImpl(vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell) VTKM_CONT void ResetConnectivityImpl(vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell)
{ {
this->Data->VisitPointsWithCells = VisitPointsWithCellsInternalsType{}; this->Data->PointCellIds = PointCellIdsType{};
} }
// Store internals in a shared pointer so shallow copies stay consistent. // Store internals in a shared pointer so shallow copies stay consistent.
// See #2268. // See #2268.
struct Internals struct Internals
{ {
VisitCellsWithPointsInternalsType VisitCellsWithPoints; CellPointIdsType CellPointIds;
VisitPointsWithCellsInternalsType VisitPointsWithCells; PointCellIdsType PointCellIds;
// These are used in the AddCell and related methods to incrementally add // These are used in the AddCell and related methods to incrementally add
// cells. They need to be protected as subclasses of CellSetExplicit // cells. They need to be protected as subclasses of CellSetExplicit
@ -275,42 +333,45 @@ protected:
std::shared_ptr<Internals> Data; std::shared_ptr<Internals> Data;
private: private:
const VisitCellsWithPointsInternalsType& GetConnectivity(vtkm::TopologyElementTagCell, VTKM_CONT
vtkm::TopologyElementTagPoint) const const CellPointIdsType& GetConnectivity(vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const
{ {
return this->Data->VisitCellsWithPoints; return this->Data->CellPointIds;
} }
const VisitCellsWithPointsInternalsType& GetConnectivity(vtkm::TopologyElementTagCell, VTKM_CONT
vtkm::TopologyElementTagPoint) const CellPointIdsType& GetConnectivity(vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint)
{ {
return this->Data->VisitCellsWithPoints; return this->Data->CellPointIds;
} }
const VisitPointsWithCellsInternalsType& GetConnectivity(vtkm::TopologyElementTagPoint, VTKM_CONT
vtkm::TopologyElementTagCell) const const PointCellIdsType& GetConnectivity(vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const
{ {
return this->Data->VisitPointsWithCells; return this->Data->PointCellIds;
} }
const VisitPointsWithCellsInternalsType& GetConnectivity(vtkm::TopologyElementTagPoint, VTKM_CONT
vtkm::TopologyElementTagCell) const PointCellIdsType& GetConnectivity(vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell)
{ {
return this->Data->VisitPointsWithCells; return this->Data->PointCellIds;
} }
}; };
namespace detail namespace detail
{ {
template <typename Storage1, typename Storage2, typename Storage3, typename Storage4> template <typename Storage1, typename Storage2, typename Storage3>
struct CellSetExplicitConnectivityChooser< struct CellSetExplicitConnectivityChooser<vtkm::cont::CellSetExplicit<Storage1, Storage2, Storage3>,
vtkm::cont::CellSetExplicit<Storage1, Storage2, Storage3, Storage4>, vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>
vtkm::TopologyElementTagPoint>
{ {
using ConnectivityType = using ConnectivityType =
vtkm::cont::internal::ConnectivityExplicitInternals<Storage1, Storage2, Storage3, Storage4>; vtkm::cont::internal::ConnectivityExplicitInternals<Storage1, Storage2, Storage3>;
}; };
template <typename CellSetType> template <typename CellSetType>
@ -332,7 +393,6 @@ struct CellSetExplicitConnectivityChooser<CellSetType,
extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetExplicit<>; // default extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetExplicit<>; // default
extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetExplicit< extern template class VTKM_CONT_TEMPLATE_EXPORT CellSetExplicit<
typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag, typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>; // CellSetSingleType base typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>; // CellSetSingleType base
#endif #endif
@ -348,17 +408,15 @@ namespace vtkm
namespace cont namespace cont
{ {
template <typename ShapeST, typename CountST, typename ConnectivityST, typename OffsetST> template <typename SST, typename CST, typename OST>
struct SerializableTypeString< struct SerializableTypeString<vtkm::cont::CellSetExplicit<SST, CST, OST>>
vtkm::cont::CellSetExplicit<ShapeST, CountST, ConnectivityST, OffsetST>>
{ {
static VTKM_CONT const std::string& Get() static VTKM_CONT const std::string& Get()
{ {
static std::string name = "CS_Explicit<" + static std::string name = "CS_Explicit<" +
SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeST>>::Get() + "_ST," + SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::UInt8, SST>>::Get() + "_ST," +
SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::IdComponent, CountST>>::Get() + "_ST," + SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::Id, CST>>::Get() + "_ST," +
SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityST>>::Get() + "_ST," + SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::Id, OST>>::Get() + "_ST>";
SerializableTypeString<vtkm::cont::ArrayHandle<vtkm::Id, OffsetST>>::Get() + "_ST>";
return name; return name;
} }
@ -369,11 +427,11 @@ struct SerializableTypeString<
namespace mangled_diy_namespace namespace mangled_diy_namespace
{ {
template <typename ShapeST, typename CountST, typename ConnectivityST, typename OffsetST> template <typename SST, typename CST, typename OST>
struct Serialization<vtkm::cont::CellSetExplicit<ShapeST, CountST, ConnectivityST, OffsetST>> struct Serialization<vtkm::cont::CellSetExplicit<SST, CST, OST>>
{ {
private: private:
using Type = vtkm::cont::CellSetExplicit<ShapeST, CountST, ConnectivityST, OffsetST>; using Type = vtkm::cont::CellSetExplicit<SST, CST, OST>;
public: public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs) static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
@ -381,29 +439,25 @@ public:
vtkmdiy::save(bb, cs.GetNumberOfPoints()); vtkmdiy::save(bb, cs.GetNumberOfPoints());
vtkmdiy::save( vtkmdiy::save(
bb, cs.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{})); bb, cs.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}));
vtkmdiy::save(
bb, cs.GetNumIndicesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}));
vtkmdiy::save( vtkmdiy::save(
bb, cs.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{})); bb, cs.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}));
vtkmdiy::save( vtkmdiy::save(
bb, cs.GetIndexOffsetArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{})); bb, cs.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}));
} }
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs) static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{ {
vtkm::Id numberOfPoints = 0; vtkm::Id numberOfPoints = 0;
vtkmdiy::load(bb, numberOfPoints); vtkmdiy::load(bb, numberOfPoints);
vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeST> shapes; vtkm::cont::ArrayHandle<vtkm::UInt8, SST> shapes;
vtkmdiy::load(bb, shapes); vtkmdiy::load(bb, shapes);
vtkm::cont::ArrayHandle<vtkm::IdComponent, CountST> counts; vtkm::cont::ArrayHandle<vtkm::Id, CST> connectivity;
vtkmdiy::load(bb, counts);
vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityST> connectivity;
vtkmdiy::load(bb, connectivity); vtkmdiy::load(bb, connectivity);
vtkm::cont::ArrayHandle<vtkm::Id, OffsetST> offsets; vtkm::cont::ArrayHandle<vtkm::Id, OST> offsets;
vtkmdiy::load(bb, offsets); vtkmdiy::load(bb, offsets);
cs = Type{}; cs = Type{};
cs.Fill(numberOfPoints, shapes, counts, connectivity, offsets); cs.Fill(numberOfPoints, shapes, connectivity, offsets);
} }
}; };

@ -10,302 +10,267 @@
#ifndef vtk_m_cont_CellSetExplicit_hxx #ifndef vtk_m_cont_CellSetExplicit_hxx
#define vtk_m_cont_CellSetExplicit_hxx #define vtk_m_cont_CellSetExplicit_hxx
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandleDecorator.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/RuntimeDeviceTracker.h> #include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/TryExecute.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.
//
// clang-format off
namespace vtkm namespace vtkm
{ {
namespace cont namespace cont
{ {
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, CellSetExplicit<SST, CST, OST>::CellSetExplicit()
typename OffsetsStorageTag>
VTKM_CONT CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CellSetExplicit()
: CellSet() : CellSet()
, Data(std::make_shared<Internals>()) , Data(std::make_shared<Internals>())
{ {
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, CellSetExplicit<SST, CST, OST>::CellSetExplicit(const Thisclass& src)
typename OffsetsStorageTag>
VTKM_CONT CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CellSetExplicit(const Thisclass& src)
: CellSet(src) : CellSet(src)
, Data(src.Data) , Data(src.Data)
{ {
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, CellSetExplicit<SST, CST, OST>::CellSetExplicit(Thisclass &&src) noexcept
typename OffsetsStorageTag> : CellSet(std::forward<CellSet>(src))
VTKM_CONT CellSetExplicit<ShapeStorageTag, , Data(std::move(src.Data))
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CellSetExplicit(Thisclass &&src) noexcept
: CellSet(std::forward<CellSet>(src)),
Data(std::move(src.Data))
{ {
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, auto CellSetExplicit<SST, CST, OST>::operator=(const Thisclass& src)
typename OffsetsStorageTag> -> Thisclass&
VTKM_CONT auto
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
operator=(const Thisclass& src) -> Thisclass&
{ {
this->CellSet::operator=(src); this->CellSet::operator=(src);
this->Data = src.Data; this->Data = src.Data;
return *this; return *this;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, auto CellSetExplicit<SST, CST, OST>::operator=(Thisclass&& src) noexcept
typename OffsetsStorageTag> -> Thisclass&
VTKM_CONT auto
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
operator=(Thisclass&& src) noexcept -> Thisclass&
{ {
this->CellSet::operator=(std::forward<CellSet>(src)); this->CellSet::operator=(std::forward<CellSet>(src));
this->Data = std::move(src.Data); this->Data = std::move(src.Data);
return *this; return *this;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, CellSetExplicit<SST, CST, OST>::~CellSetExplicit()
typename OffsetsStorageTag>
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
~CellSetExplicit()
// explicitly define instead of '=default' to workaround an intel compiler bug
// (see #179)
{ {
// explicitly define instead of '=default' to workaround an intel compiler bug
// (see #179)
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>::PrintSummary(std::ostream& out) const
typename OffsetsStorageTag>
void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::PrintSummary(std::ostream& out) const
{ {
out << " ExplicitCellSet: " << std::endl; out << " ExplicitCellSet:" << std::endl;
out << " VisitCellsWithPoints: " << std::endl; out << " CellPointIds:" << std::endl;
this->Data->VisitCellsWithPoints.PrintSummary(out); this->Data->CellPointIds.PrintSummary(out);
out << " VisitPointsWithCells: " << std::endl; out << " PointCellIds:" << std::endl;
this->Data->VisitPointsWithCells.PrintSummary(out); this->Data->PointCellIds.PrintSummary(out);
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>::ReleaseResourcesExecution()
typename OffsetStorageTag>
void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetStorageTag>::ReleaseResourcesExecution()
{ {
this->Data->VisitCellsWithPoints.ReleaseResourcesExecution(); this->Data->CellPointIds.ReleaseResourcesExecution();
this->Data->VisitPointsWithCells.ReleaseResourcesExecution(); this->Data->PointCellIds.ReleaseResourcesExecution();
} }
//---------------------------------------------------------------------------- template <typename SST, typename CST, typename OST>
VTKM_CONT
template <typename ShapeStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>::GetNumberOfCells() const
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
vtkm::Id CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetNumberOfCells() const
{ {
return this->Data->VisitCellsWithPoints.GetNumberOfElements(); return this->Data->CellPointIds.GetNumberOfElements();
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>::GetNumberOfPoints() const
typename OffsetsStorageTag>
vtkm::Id CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetNumberOfPoints() const
{ {
return this->Data->NumberOfPoints; return this->Data->NumberOfPoints;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>::GetNumberOfFaces() const
typename OffsetsStorageTag>
vtkm::Id CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetNumberOfFaces() const
{ {
return -1; return -1;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>::GetNumberOfEdges() const
typename OffsetsStorageTag>
vtkm::Id CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetNumberOfEdges() const
{ {
return -1; return -1;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>::GetCellPointIds(vtkm::Id cellId,
typename OffsetsStorageTag> vtkm::Id* ptids) const
void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const
{ {
auto arrayWrapper = vtkm::cont::make_ArrayHandle(ptids, this->GetNumberOfPointsInCell(id)); const auto offPortal = this->Data->CellPointIds.Offsets.GetPortalConstControl();
this->GetIndices(id, arrayWrapper); const vtkm::Id start = offPortal.Get(cellId);
const vtkm::Id end = offPortal.Get(cellId + 1);
const vtkm::IdComponent numIndices = static_cast<vtkm::IdComponent>(end - start);
auto connPortal = this->Data->CellPointIds.Connectivity.GetPortalConstControl();
for (vtkm::IdComponent i = 0; i < numIndices; i++)
{
ptids[i] = connPortal.Get(start + i);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::GetSchedulingRange(vtkm::TopologyElementTagCell) const
VTKM_CONT vtkm::Id
CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetSchedulingRange(vtkm::TopologyElementTagCell) const
{ {
return this->GetNumberOfCells(); return this->GetNumberOfCells();
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::Id CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::GetSchedulingRange(vtkm::TopologyElementTagPoint) const
VTKM_CONT vtkm::Id
CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetSchedulingRange(vtkm::TopologyElementTagPoint) const
{ {
return this->GetNumberOfPoints(); return this->GetNumberOfPoints();
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::IdComponent CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::GetNumberOfPointsInCell(vtkm::Id cellid) const
VTKM_CONT vtkm::IdComponent
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
GetNumberOfPointsInCell(vtkm::Id cellIndex) const
{ {
return this->Data->VisitCellsWithPoints.NumIndices.GetPortalConstControl().Get(cellIndex); const auto portal = this->Data->CellPointIds.Offsets.GetPortalConstControl();
return static_cast<vtkm::IdComponent>(portal.Get(cellid + 1) -
portal.Get(cellid));
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, vtkm::UInt8 CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::GetCellShape(vtkm::Id cellid) const
VTKM_CONT vtkm::UInt8 CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::GetCellShape(vtkm::Id cellIndex) const
{ {
return this->Data->VisitCellsWithPoints.Shapes.GetPortalConstControl().Get(cellIndex); return this->Data->CellPointIds.Shapes.GetPortalConstControl().Get(cellid);
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, template <vtkm::IdComponent NumVecIndices>
typename ConnectivityStorageTag, VTKM_CONT
typename OffsetsStorageTag> void CellSetExplicit<SST, CST, OST>
template <vtkm::IdComponent ItemTupleLength> ::GetIndices(vtkm::Id cellId, vtkm::Vec<vtkm::Id, NumVecIndices>& ids) const
VTKM_CONT void
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
GetIndices(vtkm::Id index, vtkm::Vec<vtkm::Id, ItemTupleLength>& ids) const
{ {
this->Data->VisitCellsWithPoints.BuildIndexOffsets(vtkm::cont::DeviceAdapterTagAny{}); const auto offPortal = this->Data->CellPointIds.Offsets.GetPortalConstControl();
vtkm::IdComponent numIndices = this->GetNumberOfPointsInCell(index); const vtkm::Id start = offPortal.Get(cellId);
vtkm::Id start = this->Data->VisitCellsWithPoints.IndexOffsets.GetPortalConstControl().Get(index); const vtkm::Id end = offPortal.Get(cellId + 1);
for (vtkm::IdComponent i = 0; i < numIndices && i < ItemTupleLength; i++) const auto numCellIndices = static_cast<vtkm::IdComponent>(end - start);
const auto connPortal = this->Data->CellPointIds.Connectivity.GetPortalConstControl();
VTKM_LOG_IF_S(vtkm::cont::LogLevel::Warn,
numCellIndices != NumVecIndices,
"GetIndices given a " << NumVecIndices
<< "-vec to fetch a cell with " << numCellIndices << "points. "
"Truncating result.");
const vtkm::IdComponent numIndices = vtkm::Min(NumVecIndices, numCellIndices);
for (vtkm::IdComponent i = 0; i < numIndices; i++)
{ {
ids[i] = this->Data->VisitCellsWithPoints.Connectivity.GetPortalConstControl().Get(start + i); ids[i] = connPortal.Get(start + i);
} }
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::GetIndices(vtkm::Id cellId, vtkm::cont::ArrayHandle<vtkm::Id>& ids) const
VTKM_CONT void
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
GetIndices(vtkm::Id index, vtkm::cont::ArrayHandle<vtkm::Id>& ids) const
{ {
this->Data->VisitCellsWithPoints.BuildIndexOffsets(vtkm::cont::DeviceAdapterTagAny{}); const auto offPortal = this->Data->CellPointIds.Offsets.GetPortalConstControl();
vtkm::IdComponent numIndices = this->GetNumberOfPointsInCell(index); const vtkm::Id start = offPortal.Get(cellId);
const vtkm::Id end = offPortal.Get(cellId + 1);
const vtkm::IdComponent numIndices = static_cast<vtkm::IdComponent>(end - start);
ids.Allocate(numIndices); ids.Allocate(numIndices);
vtkm::Id start = this->Data->VisitCellsWithPoints.IndexOffsets.GetPortalConstControl().Get(index); auto connPortal = this->Data->CellPointIds.Connectivity.GetPortalConstControl();
vtkm::cont::ArrayHandle<vtkm::Id>::PortalControl idPortal = ids.GetPortalControl();
auto PtCellPortal = this->Data->VisitCellsWithPoints.Connectivity.GetPortalConstControl();
for (vtkm::IdComponent i = 0; i < numIndices && i < numIndices; i++) auto outIdPortal = ids.GetPortalControl();
for (vtkm::IdComponent i = 0; i < numIndices; i++)
{ {
idPortal.Set(i, PtCellPortal.Get(start + i)); outIdPortal.Set(i, connPortal.Get(start + i));
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
namespace internal
template <typename ShapeStorageTag,
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
VTKM_CONT void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::PrepareToAddCells(vtkm::Id numCells,
vtkm::Id connectivityMaxLen)
{ {
this->Data->VisitCellsWithPoints.Shapes.Allocate(numCells);
this->Data->VisitCellsWithPoints.NumIndices.Allocate(numCells); // Sets the first value of the array to zero if the handle is writable,
this->Data->VisitCellsWithPoints.Connectivity.Allocate(connectivityMaxLen); // otherwise do nothing:
this->Data->VisitCellsWithPoints.IndexOffsets.Allocate(numCells); template <typename ArrayType>
typename std::enable_if<vtkm::cont::internal::IsWritableArrayHandle<ArrayType>::value>::type
SetFirstToZeroIfWritable(ArrayType&& array)
{
using ValueType = typename std::decay<ArrayType>::type::ValueType;
using Traits = vtkm::TypeTraits<ValueType>;
array.GetPortalControl().Set(0, Traits::ZeroInitialization());
}
template <typename ArrayType>
typename std::enable_if<!vtkm::cont::internal::IsWritableArrayHandle<ArrayType>::value>::type
SetFirstToZeroIfWritable(ArrayType&&)
{ /* no-op */ }
} // end namespace internal
template <typename SST, typename CST, typename OST>
VTKM_CONT
void CellSetExplicit<SST, CST, OST>
::PrepareToAddCells(vtkm::Id numCells,
vtkm::Id connectivityMaxLen)
{
this->Data->CellPointIds.Shapes.Allocate(numCells);
this->Data->CellPointIds.Connectivity.Allocate(connectivityMaxLen);
this->Data->CellPointIds.Offsets.Allocate(numCells + 1);
internal::SetFirstToZeroIfWritable(this->Data->CellPointIds.Offsets);
this->Data->NumberOfCellsAdded = 0; this->Data->NumberOfCellsAdded = 0;
this->Data->ConnectivityAdded = 0; this->Data->ConnectivityAdded = 0;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename IdVecType> template <typename IdVecType>
VTKM_CONT void VTKM_CONT
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>:: void CellSetExplicit<SST, CST, OST>::AddCell(vtkm::UInt8 cellType,
AddCell(vtkm::UInt8 cellType, vtkm::IdComponent numVertices, const IdVecType& ids) vtkm::IdComponent numVertices,
const IdVecType& ids)
{ {
using Traits = vtkm::VecTraits<IdVecType>; using Traits = vtkm::VecTraits<IdVecType>;
VTKM_STATIC_ASSERT_MSG((std::is_same<typename Traits::ComponentType, vtkm::Id>::value), VTKM_STATIC_ASSERT_MSG((std::is_same<typename Traits::ComponentType, vtkm::Id>::value),
@ -313,48 +278,45 @@ CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, O
if (Traits::GetNumberOfComponents(ids) < numVertices) if (Traits::GetNumberOfComponents(ids) < numVertices)
{ {
throw vtkm::cont::ErrorBadValue("Not enough indices given to CellSetSingleType::AddCell."); throw vtkm::cont::ErrorBadValue("Not enough indices given to CellSetExplicit::AddCell.");
} }
if (this->Data->NumberOfCellsAdded >= this->Data->VisitCellsWithPoints.Shapes.GetNumberOfValues()) if (this->Data->NumberOfCellsAdded >= this->Data->CellPointIds.Shapes.GetNumberOfValues())
{ {
throw vtkm::cont::ErrorBadValue("Added more cells then expected."); throw vtkm::cont::ErrorBadValue("Added more cells then expected.");
} }
if (this->Data->ConnectivityAdded + numVertices > if (this->Data->ConnectivityAdded + numVertices >
this->Data->VisitCellsWithPoints.Connectivity.GetNumberOfValues()) this->Data->CellPointIds.Connectivity.GetNumberOfValues())
{ {
throw vtkm::cont::ErrorBadValue( throw vtkm::cont::ErrorBadValue(
"Connectivity increased passed estimated maximum connectivity."); "Connectivity increased past estimated maximum connectivity.");
} }
this->Data->VisitCellsWithPoints.Shapes.GetPortalControl().Set(this->Data->NumberOfCellsAdded, auto shapes = this->Data->CellPointIds.Shapes.GetPortalControl();
cellType); auto conn = this->Data->CellPointIds.Connectivity.GetPortalControl();
this->Data->VisitCellsWithPoints.NumIndices.GetPortalControl().Set(this->Data->NumberOfCellsAdded, auto offsets = this->Data->CellPointIds.Offsets.GetPortalControl();
numVertices);
shapes.Set(this->Data->NumberOfCellsAdded, cellType);
for (vtkm::IdComponent iVec = 0; iVec < numVertices; ++iVec) for (vtkm::IdComponent iVec = 0; iVec < numVertices; ++iVec)
{ {
this->Data->VisitCellsWithPoints.Connectivity.GetPortalControl().Set( conn.Set(this->Data->ConnectivityAdded + iVec,
this->Data->ConnectivityAdded + iVec, Traits::GetComponent(ids, iVec)); Traits::GetComponent(ids, iVec));
} }
this->Data->VisitCellsWithPoints.IndexOffsets.GetPortalControl().Set(
this->Data->NumberOfCellsAdded, this->Data->ConnectivityAdded);
this->Data->NumberOfCellsAdded++; this->Data->NumberOfCellsAdded++;
this->Data->ConnectivityAdded += numVertices; this->Data->ConnectivityAdded += numVertices;
// Set the end offset for the added cell:
offsets.Set(this->Data->NumberOfCellsAdded, this->Data->ConnectivityAdded);
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>::CompleteAddingCells(vtkm::Id numPoints)
typename OffsetsStorageTag>
VTKM_CONT void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CompleteAddingCells(vtkm::Id numPoints)
{ {
this->Data->NumberOfPoints = numPoints; this->Data->NumberOfPoints = numPoints;
this->Data->VisitCellsWithPoints.Connectivity.Shrink(this->Data->ConnectivityAdded); this->Data->CellPointIds.Connectivity.Shrink(this->Data->ConnectivityAdded);
this->Data->VisitCellsWithPoints.ElementsValid = true; this->Data->CellPointIds.ElementsValid = true;
this->Data->VisitCellsWithPoints.IndexOffsetsValid = true;
if (this->Data->NumberOfCellsAdded != this->GetNumberOfCells()) if (this->Data->NumberOfCellsAdded != this->GetNumberOfCells())
{ {
@ -367,159 +329,132 @@ VTKM_CONT void CellSetExplicit<ShapeStorageTag,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::Fill(vtkm::Id numPoints,
VTKM_CONT void const vtkm::cont::ArrayHandle<vtkm::UInt8, SST>& shapes,
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>:: const vtkm::cont::ArrayHandle<vtkm::Id, CST>& connectivity,
Fill(vtkm::Id numPoints, const vtkm::cont::ArrayHandle<vtkm::Id, OST>& offsets)
const vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorageTag>& cellTypes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageTag>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>& connectivity,
const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>& offsets)
{ {
// Validate inputs:
// Even for an empty cellset, offsets must contain a single 0:
VTKM_ASSERT(offsets.GetNumberOfValues() > 0);
// Must be [numCells + 1] offsets and [numCells] shapes
VTKM_ASSERT(offsets.GetNumberOfValues() == shapes.GetNumberOfValues() + 1);
// The last offset must be the size of the connectivity array.
VTKM_ASSERT(vtkm::cont::ArrayGetValue(offsets.GetNumberOfValues() - 1,
offsets) ==
connectivity.GetNumberOfValues());
this->Data->NumberOfPoints = numPoints; this->Data->NumberOfPoints = numPoints;
this->Data->VisitCellsWithPoints.Shapes = cellTypes; this->Data->CellPointIds.Shapes = shapes;
this->Data->VisitCellsWithPoints.NumIndices = numIndices; this->Data->CellPointIds.Connectivity = connectivity;
this->Data->VisitCellsWithPoints.Connectivity = connectivity; this->Data->CellPointIds.Offsets = offsets;
this->Data->VisitCellsWithPoints.ElementsValid = true; this->Data->CellPointIds.ElementsValid = true;
if (offsets.GetNumberOfValues() == cellTypes.GetNumberOfValues())
{
this->Data->VisitCellsWithPoints.IndexOffsets = offsets;
this->Data->VisitCellsWithPoints.IndexOffsetsValid = true;
}
else
{
this->Data->VisitCellsWithPoints.IndexOffsetsValid = false;
if (offsets.GetNumberOfValues() != 0)
{
throw vtkm::cont::ErrorBadValue("Explicit cell offsets array unexpected size. "
"Use an empty array to automatically generate.");
}
}
this->ResetConnectivity(TopologyElementTagPoint{}, TopologyElementTagCell{}); this->ResetConnectivity(TopologyElementTagPoint{}, TopologyElementTagCell{});
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename Device, typename VisitTopology, typename IncidentTopology> template <typename Device, typename VisitTopology, typename IncidentTopology>
auto CellSetExplicit<ShapeStorageTag, VTKM_CONT
NumIndicesStorageTag, auto CellSetExplicit<SST, CST, OST>
ConnectivityStorageTag, ::PrepareForInput(Device, VisitTopology, IncidentTopology) const
OffsetsStorageTag>::PrepareForInput(Device, -> typename ExecutionTypes<Device,
VisitTopology, VisitTopology,
IncidentTopology) const -> IncidentTopology>::ExecObjectType
typename ExecutionTypes<Device, VisitTopology, IncidentTopology>::ExecObjectType
{ {
this->BuildConnectivity(Device{}, VisitTopology(), IncidentTopology()); this->BuildConnectivity(Device{}, VisitTopology{}, IncidentTopology{});
const auto& connectivity = this->GetConnectivity(VisitTopology(), IncidentTopology()); const auto& connectivity = this->GetConnectivity(VisitTopology{},
IncidentTopology{});
VTKM_ASSERT(connectivity.ElementsValid); VTKM_ASSERT(connectivity.ElementsValid);
using ExecObjType = using ExecObjType = typename ExecutionTypes<Device,
typename ExecutionTypes<Device, VisitTopology, IncidentTopology>::ExecObjectType; VisitTopology,
return ExecObjType(connectivity.Shapes.PrepareForInput(Device()), IncidentTopology>::ExecObjectType;
connectivity.NumIndices.PrepareForInput(Device()),
connectivity.Connectivity.PrepareForInput(Device()), return ExecObjType(connectivity.Shapes.PrepareForInput(Device{}),
connectivity.IndexOffsets.PrepareForInput(Device())); connectivity.Connectivity.PrepareForInput(Device{}),
connectivity.Offsets.PrepareForInput(Device{}));
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT auto CellSetExplicit<ShapeStorageTag, VTKM_CONT auto CellSetExplicit<SST, CST, OST>
NumIndicesStorageTag, ::GetShapesArray(VisitTopology, IncidentTopology) const
ConnectivityStorageTag, -> const typename ConnectivityChooser<VisitTopology,
OffsetsStorageTag>::GetShapesArray(VisitTopology, IncidentTopology>::ShapesArrayType&
IncidentTopology) const -> const
typename ConnectivityChooser<VisitTopology, IncidentTopology>::ShapeArrayType&
{ {
this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{}, VisitTopology(), IncidentTopology()); this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{},
return this->GetConnectivity(VisitTopology(), IncidentTopology()).Shapes; VisitTopology{},
IncidentTopology{});
return this->GetConnectivity(VisitTopology{}, IncidentTopology{}).Shapes;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT auto CellSetExplicit<ShapeStorageTag, VTKM_CONT
NumIndicesStorageTag, auto CellSetExplicit<SST, CST, OST>
ConnectivityStorageTag, ::GetConnectivityArray(VisitTopology, IncidentTopology) const
OffsetsStorageTag>::GetNumIndicesArray(VisitTopology, -> const typename ConnectivityChooser<VisitTopology,
IncidentTopology) const IncidentTopology>::ConnectivityArrayType&
-> const typename ConnectivityChooser<VisitTopology, IncidentTopology>::NumIndicesArrayType&
{ {
this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{}, VisitTopology(), IncidentTopology()); this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{},
return this->GetConnectivity(VisitTopology(), IncidentTopology()).NumIndices; VisitTopology{},
IncidentTopology{});
return this->GetConnectivity(VisitTopology{},
IncidentTopology{}).Connectivity;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT auto CellSetExplicit<ShapeStorageTag, VTKM_CONT
NumIndicesStorageTag, auto CellSetExplicit<SST, CST, OST>
ConnectivityStorageTag, ::GetOffsetsArray(VisitTopology, IncidentTopology) const
OffsetsStorageTag>::GetConnectivityArray(VisitTopology, -> const typename ConnectivityChooser<VisitTopology,
IncidentTopology) const IncidentTopology>::OffsetsArrayType&
-> const typename ConnectivityChooser<VisitTopology, IncidentTopology>::ConnectivityArrayType&
{ {
this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{}, VisitTopology(), IncidentTopology()); this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{},
return this->GetConnectivity(VisitTopology(), IncidentTopology()).Connectivity; VisitTopology{},
IncidentTopology{});
return this->GetConnectivity(VisitTopology{},
IncidentTopology{}).Offsets;
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
template <typename VisitTopology, typename IncidentTopology> template <typename VisitTopology, typename IncidentTopology>
VTKM_CONT auto CellSetExplicit<ShapeStorageTag, VTKM_CONT
NumIndicesStorageTag, auto CellSetExplicit<SST, CST, OST>
ConnectivityStorageTag, ::GetNumIndicesArray(VisitTopology visited, IncidentTopology incident) const
OffsetsStorageTag>::GetIndexOffsetArray(VisitTopology, -> typename ConnectivityChooser<VisitTopology,
IncidentTopology) const IncidentTopology>::NumIndicesArrayType
-> const typename ConnectivityChooser<VisitTopology, IncidentTopology>::IndexOffsetArrayType&
{ {
this->BuildConnectivity(vtkm::cont::DeviceAdapterTagAny{}, VisitTopology(), IncidentTopology()); auto offsets = this->GetOffsetsArray(visited, incident);
return this->GetConnectivity(VisitTopology(), IncidentTopology()).IndexOffsets; const vtkm::Id numVals = offsets.GetNumberOfValues() - 1;
return vtkm::cont::make_ArrayHandleDecorator(numVals,
detail::NumIndicesDecorator{},
std::move(offsets));
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, std::shared_ptr<CellSet> CellSetExplicit<SST, CST, OST>::NewInstance() const
typename OffsetsStorageTag>
std::shared_ptr<CellSet> CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::NewInstance() const
{ {
return std::make_shared<CellSetExplicit>(); return std::make_shared<CellSetExplicit>();
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>::DeepCopy(const CellSet* src)
typename OffsetsStorageTag>
void CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::DeepCopy(const CellSet* src)
{ {
const auto* other = dynamic_cast<const CellSetExplicit*>(src); const auto* other = dynamic_cast<const CellSetExplicit*>(src);
if (!other) if (!other)
@ -527,14 +462,18 @@ void CellSetExplicit<ShapeStorageTag,
throw vtkm::cont::ErrorBadType("CellSetExplicit::DeepCopy types don't match"); throw vtkm::cont::ErrorBadType("CellSetExplicit::DeepCopy types don't match");
} }
// TODO: implement actual deep-copy of the arrays ShapesArrayType shapes;
auto ct = vtkm::TopologyElementTagCell{}; ConnectivityArrayType conn;
auto pt = vtkm::TopologyElementTagPoint{}; OffsetsArrayType offsets;
this->Fill(other->GetNumberOfPoints(),
other->GetShapesArray(ct, pt), const auto ct = vtkm::TopologyElementTagCell{};
other->GetNumIndicesArray(ct, pt), const auto pt = vtkm::TopologyElementTagPoint{};
other->GetConnectivityArray(ct, pt),
other->GetIndexOffsetArray(ct, pt)); vtkm::cont::ArrayCopy(other->GetShapesArray(ct, pt), shapes);
vtkm::cont::ArrayCopy(other->GetConnectivityArray(ct, pt), conn);
vtkm::cont::ArrayCopy(other->GetOffsetsArray(ct, pt), offsets);
this->Fill(other->GetNumberOfPoints(), shapes, conn, offsets);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -542,33 +481,14 @@ void CellSetExplicit<ShapeStorageTag,
namespace detail namespace detail
{ {
template <typename VisitCellsWithPointsConnectivity> template <typename CellPointIdsT, typename PointCellIdsT>
struct BuildVisitCellsWithPointsConnectivityFunctor struct BuildPointCellIdsFunctor
{ {
explicit BuildVisitCellsWithPointsConnectivityFunctor(VisitCellsWithPointsConnectivity& obj) BuildPointCellIdsFunctor(CellPointIdsT &cellPointIds,
: VisitCellsWithPoints(&obj) PointCellIdsT &pointCellIds,
{ vtkm::Id numberOfPoints)
} : CellPointIds(cellPointIds)
, PointCellIds(pointCellIds)
template <typename Device>
bool operator()(Device) const
{
this->VisitCellsWithPoints->BuildIndexOffsets(Device());
return true;
}
VisitCellsWithPointsConnectivity* VisitCellsWithPoints;
};
template <typename VisitCellsWithPointsConnectivity, typename VisitPointsWithCellsConnectivity>
struct BuildVisitPointsWithCellsConnectivityFunctor
{
BuildVisitPointsWithCellsConnectivityFunctor(
VisitCellsWithPointsConnectivity& visitCellsWithPoints,
VisitPointsWithCellsConnectivity& visitPointsWithCells,
vtkm::Id numberOfPoints)
: VisitCellsWithPoints(&visitCellsWithPoints)
, VisitPointsWithCells(&visitPointsWithCells)
, NumberOfPoints(numberOfPoints) , NumberOfPoints(numberOfPoints)
{ {
} }
@ -576,81 +496,57 @@ struct BuildVisitPointsWithCellsConnectivityFunctor
template <typename Device> template <typename Device>
bool operator()(Device) const bool operator()(Device) const
{ {
this->VisitCellsWithPoints->BuildIndexOffsets(Device()); internal::ComputeRConnTable(this->PointCellIds,
internal::ComputeVisitPointsWithCellsConnectivity( this->CellPointIds,
*this->VisitPointsWithCells, *this->VisitCellsWithPoints, this->NumberOfPoints, Device()); this->NumberOfPoints,
this->VisitPointsWithCells->BuildIndexOffsets(Device()); Device{});
return true; return true;
} }
VisitCellsWithPointsConnectivity* VisitCellsWithPoints; CellPointIdsT &CellPointIds;
VisitPointsWithCellsConnectivity* VisitPointsWithCells; PointCellIdsT &PointCellIds;
vtkm::Id NumberOfPoints; vtkm::Id NumberOfPoints;
}; };
} // detail } // detail
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::BuildConnectivity(vtkm::cont::DeviceAdapterId,
VTKM_CONT void
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
BuildConnectivity(vtkm::cont::DeviceAdapterId device,
vtkm::TopologyElementTagCell, vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint) const vtkm::TopologyElementTagPoint) const
{ {
using VisitCellsWithPointsConnectivity = VTKM_ASSERT(this->Data->CellPointIds.ElementsValid);
typename ConnectivityChooser<vtkm::TopologyElementTagCell, // no-op
vtkm::TopologyElementTagPoint>::ConnectivityType;
VTKM_ASSERT(this->Data->VisitCellsWithPoints.ElementsValid);
if (!this->Data->VisitCellsWithPoints.IndexOffsetsValid)
{
auto self = const_cast<Thisclass*>(this);
auto functor =
detail::BuildVisitCellsWithPointsConnectivityFunctor<VisitCellsWithPointsConnectivity>(
self->Data->VisitCellsWithPoints);
if (!vtkm::cont::TryExecuteOnDevice(device, functor))
{
throw vtkm::cont::ErrorExecution("Failed to run BuildConnectivity.");
}
}
} }
template <typename ShapeStorageTag, template <typename SST, typename CST, typename OST>
typename NumIndicesStorageTag, VTKM_CONT
typename ConnectivityStorageTag, void CellSetExplicit<SST, CST, OST>
typename OffsetsStorageTag> ::BuildConnectivity(vtkm::cont::DeviceAdapterId device,
VTKM_CONT void
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
BuildConnectivity(vtkm::cont::DeviceAdapterId device,
vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const vtkm::TopologyElementTagCell) const
{ {
using VisitCellsWithPointsConnectivity = if (!this->Data->PointCellIds.ElementsValid)
typename ConnectivityChooser<vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint>::ConnectivityType;
using VisitPointsWithCellsConnectivity =
typename ConnectivityChooser<vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell>::ConnectivityType;
if (!this->Data->VisitPointsWithCells.ElementsValid ||
!this->Data->VisitPointsWithCells.IndexOffsetsValid)
{ {
auto self = const_cast<Thisclass*>(this); auto self = const_cast<Thisclass*>(this);
auto functor = using Func = detail::BuildPointCellIdsFunctor<CellPointIdsType, PointCellIdsType>;
detail::BuildVisitPointsWithCellsConnectivityFunctor<VisitCellsWithPointsConnectivity,
VisitPointsWithCellsConnectivity>( auto functor = Func(self->Data->CellPointIds,
self->Data->VisitCellsWithPoints, self->Data->PointCellIds,
self->Data->VisitPointsWithCells, self->Data->NumberOfPoints);
this->Data->NumberOfPoints);
if (!vtkm::cont::TryExecuteOnDevice(device, functor)) if (!vtkm::cont::TryExecuteOnDevice(device, functor))
{ {
throw vtkm::cont::ErrorExecution("Failed to run BuildConnectivity."); throw vtkm::cont::ErrorExecution("Failed to run CellSetExplicit reverse "
"connectivity builder.");
} }
} }
} }
} }
} // vtkm::cont } // vtkm::cont
// clang-format on
#endif #endif

@ -42,15 +42,12 @@ struct VTKM_ALWAYS_EXPORT CellSetListTagStructured3D
}; };
template <typename ShapeStorageTag = VTKM_DEFAULT_SHAPE_STORAGE_TAG, template <typename ShapesStorageTag = VTKM_DEFAULT_SHAPES_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_NUM_INDICES_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
typename OffsetsStorageTag = VTKM_DEFAULT_OFFSETS_STORAGE_TAG> typename OffsetsStorageTag = VTKM_DEFAULT_OFFSETS_STORAGE_TAG>
struct VTKM_ALWAYS_EXPORT CellSetListTagExplicit struct VTKM_ALWAYS_EXPORT CellSetListTagExplicit
: vtkm::ListTagBase<vtkm::cont::CellSetExplicit<ShapeStorageTag, : vtkm::ListTagBase<
NumIndicesStorageTag, vtkm::cont::CellSetExplicit<ShapesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>>
ConnectivityStorageTag,
OffsetsStorageTag>>
{ {
}; };

@ -12,13 +12,15 @@
#include <vtkm/CellShape.h> #include <vtkm/CellShape.h>
#include <vtkm/CellTraits.h> #include <vtkm/CellTraits.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleCast.h> #include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleGroupVecVariable.h> #include <vtkm/cont/ArrayHandleGroupVecVariable.h>
#include <vtkm/cont/ArrayHandlePermutation.h> #include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSet.h> #include <vtkm/cont/CellSet.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h> #include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/internal/ConnectivityStructuredInternals.h> #include <vtkm/internal/ConnectivityStructuredInternals.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h> #include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/exec/ConnectivityPermuted.h> #include <vtkm/exec/ConnectivityPermuted.h>
@ -35,7 +37,12 @@ namespace cont
namespace internal namespace internal
{ {
class CellSetPermutationVisitCellsWithPointsHelpers // To generate the reverse connectivity table with the
// ReverseConnectivityBuilder, we need a compact connectivity array that
// contains only the cell definitions from the permuted dataset, and an offsets
// array. These helpers are used to generate these arrays so that they can be
// converted in the reverse conn table.
class RConnTableHelpers
{ {
public: public:
struct WriteNumIndices : public vtkm::worklet::WorkletVisitCellsWithPoints struct WriteNumIndices : public vtkm::worklet::WorkletVisitCellsWithPoints
@ -70,102 +77,137 @@ public:
public: public:
template <typename CellSetPermutationType, typename Device> template <typename CellSetPermutationType, typename Device>
static vtkm::cont::ArrayHandle<vtkm::IdComponent> GetNumIndicesArray( static VTKM_CONT vtkm::cont::ArrayHandle<vtkm::IdComponent> GetNumIndicesArray(
const CellSetPermutationType& cs, const CellSetPermutationType& cs,
Device) Device)
{ {
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices; vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
vtkm::cont::Invoker{ Device{} }(WriteNumIndices{}, cs, numIndices);
vtkm::worklet::DispatcherMapTopology<WriteNumIndices> dispatcher;
dispatcher.SetDevice(Device());
dispatcher.Invoke(cs, numIndices);
return numIndices; return numIndices;
} }
template <typename NumIndicesStorageType, typename Device> template <typename NumIndicesStorageType, typename Device>
static vtkm::cont::ArrayHandle<vtkm::Id> GetIndexOffsetsArray( static VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> GetOffsetsArray(
const vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageType>& numIndices, const vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageType>& numIndices,
vtkm::Id& connectivityLength, vtkm::Id& connectivityLength /* outparam */,
Device) Device)
{ {
return vtkm::cont::ConvertNumComponentsToOffsets(numIndices, connectivityLength); return vtkm::cont::ConvertNumIndicesToOffsets(numIndices, connectivityLength);
} }
template <typename CellSetPermutationType, typename IndexOffsetsStorageType, typename Device> template <typename CellSetPermutationType, typename OffsetsStorageType, typename Device>
static vtkm::cont::ArrayHandle<vtkm::Id> GetConnectivityArray( static vtkm::cont::ArrayHandle<vtkm::Id> GetConnectivityArray(
const CellSetPermutationType& cs, const CellSetPermutationType& cs,
const vtkm::cont::ArrayHandle<vtkm::Id, IndexOffsetsStorageType>& indexOffsets, const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageType>& offsets,
vtkm::Id connectivityLength, vtkm::Id connectivityLength,
Device) Device)
{ {
vtkm::cont::ArrayHandle<vtkm::Id> connectivity; vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
connectivity.Allocate(connectivityLength); connectivity.Allocate(connectivityLength);
const auto offsetsTrim =
vtkm::worklet::DispatcherMapTopology<WriteConnectivity> dispatcher; vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
dispatcher.SetDevice(Device()); auto connWrap = vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim);
dispatcher.Invoke(cs, vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, indexOffsets)); vtkm::cont::Invoker{ Device{} }(WriteConnectivity{}, cs, connWrap);
return connectivity; return connectivity;
} }
}; };
// This holds the temporary input arrays for the ReverseConnectivityBuilder
// algorithm.
template <typename ConnectivityStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename OffsetsStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_STORAGE_TAG>
struct RConnBuilderInputData
{
using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>;
using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
using NumIndicesArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageTag>;
ConnectivityArrayType Connectivity;
OffsetsArrayType Offsets; // Includes the past-the-end offset.
NumIndicesArrayType NumIndices;
};
// default for CellSetPermutations of any cell type // default for CellSetPermutations of any cell type
template <typename CellSetPermutationType> template <typename CellSetPermutationType>
class CellSetPermutationVisitCellsWithPoints class RConnBuilderInput
{ {
public: public:
using ConnectivityArrays = vtkm::cont::internal::ConnectivityExplicitInternals<>; using ConnectivityArrays = vtkm::cont::internal::RConnBuilderInputData<>;
template <typename Device> template <typename Device>
static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device) static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device)
{ {
using Helper = RConnTableHelpers;
ConnectivityArrays conn; ConnectivityArrays conn;
vtkm::Id connectivityLength = 0; vtkm::Id connectivityLength = 0;
conn.NumIndices = conn.NumIndices = Helper::GetNumIndicesArray(cellset, Device{});
CellSetPermutationVisitCellsWithPointsHelpers::GetNumIndicesArray(cellset, Device{}); conn.Offsets = Helper::GetOffsetsArray(conn.NumIndices, connectivityLength, Device{});
conn.IndexOffsets = CellSetPermutationVisitCellsWithPointsHelpers::GetIndexOffsetsArray( conn.Connectivity =
conn.NumIndices, connectivityLength, Device{}); Helper::GetConnectivityArray(cellset, conn.Offsets, connectivityLength, Device{});
conn.Connectivity = CellSetPermutationVisitCellsWithPointsHelpers::GetConnectivityArray(
cellset, conn.IndexOffsets, connectivityLength, Device{});
return conn; return conn;
} }
}; };
// Specialization for CellSetExplicit/CellSetSingleType // Specialization for CellSetExplicit/CellSetSingleType
template <typename S1, typename S2, typename S3, typename S4, typename PermutationArrayHandleType> template <typename InShapesST,
class CellSetPermutationVisitCellsWithPoints< typename InConnST,
CellSetPermutation<CellSetExplicit<S1, S2, S3, S4>, PermutationArrayHandleType>> typename InOffsetsST,
typename PermutationArrayHandleType>
class RConnBuilderInput<CellSetPermutation<CellSetExplicit<InShapesST, InConnST, InOffsetsST>,
PermutationArrayHandleType>>
{ {
private: private:
using CellSetPermutationType = using BaseCellSetType = CellSetExplicit<InShapesST, InConnST, InOffsetsST>;
CellSetPermutation<CellSetExplicit<S1, S2, S3, S4>, PermutationArrayHandleType>; using CellSetPermutationType = CellSetPermutation<BaseCellSetType, PermutationArrayHandleType>;
using InShapesArrayType = typename BaseCellSetType::ShapesArrayType;
using InNumIndicesArrayType = typename BaseCellSetType::NumIndicesArrayType;
using ShapesStorageTag = StorageTagPermutation<PermutationArrayHandleType, InShapesArrayType>;
using ConnectivityStorageTag = vtkm::cont::ArrayHandle<vtkm::Id>::StorageTag;
using OffsetsStorageTag = vtkm::cont::ArrayHandle<vtkm::Id>::StorageTag;
using NumIndicesStorageTag =
StorageTagPermutation<PermutationArrayHandleType, InNumIndicesArrayType>;
using NumIndicesArrayType =
vtkm::cont::ArrayHandlePermutation<PermutationArrayHandleType,
vtkm::cont::ArrayHandle<vtkm::IdComponent, S2>>;
public: public:
using ConnectivityArrays = vtkm::cont::internal::ConnectivityExplicitInternals< using ConnectivityArrays = vtkm::cont::internal::RConnBuilderInputData<ConnectivityStorageTag,
VTKM_DEFAULT_STORAGE_TAG, // shapes array is not used OffsetsStorageTag,
typename NumIndicesArrayType::StorageTag>; NumIndicesStorageTag>;
template <typename Device> template <typename Device>
static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device) static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device)
{ {
ConnectivityArrays conn; using Helper = RConnTableHelpers;
vtkm::Id connectivityLength = 0;
conn.NumIndices = static constexpr vtkm::TopologyElementTagCell cell;
NumIndicesArrayType(cellset.GetValidCellIds(), static constexpr vtkm::TopologyElementTagPoint point;
cellset.GetFullCellSet().GetNumIndicesArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint())); auto fullCellSet = cellset.GetFullCellSet();
conn.IndexOffsets = CellSetPermutationVisitCellsWithPointsHelpers::GetIndexOffsetsArray(
conn.NumIndices, connectivityLength, Device{}); vtkm::Id connectivityLength = 0;
conn.Connectivity = CellSetPermutationVisitCellsWithPointsHelpers::GetConnectivityArray( ConnectivityArrays conn;
cellset, conn.IndexOffsets, connectivityLength, Device{});
fullCellSet.GetOffsetsArray(cell, point);
// We can use the implicitly generated NumIndices array to save a bit of
// memory:
conn.NumIndices = vtkm::cont::make_ArrayHandlePermutation(
cellset.GetValidCellIds(), fullCellSet.GetNumIndicesArray(cell, point));
// Need to generate the offsets from scratch so that they're ordered for the
// lower-bounds binary searches in ReverseConnectivityBuilder.
conn.Offsets = Helper::GetOffsetsArray(conn.NumIndices, connectivityLength, Device{});
// Need to create a copy of this containing *only* the permuted cell defs,
// in order, since the ReverseConnectivityBuilder will process every entry
// in the connectivity array and we don't want the removed cells to be
// included.
conn.Connectivity =
Helper::GetConnectivityArray(cellset, conn.Offsets, connectivityLength, Device{});
return conn; return conn;
} }
@ -173,7 +215,7 @@ public:
// Specialization for CellSetStructured // Specialization for CellSetStructured
template <vtkm::IdComponent DIMENSION, typename PermutationArrayHandleType> template <vtkm::IdComponent DIMENSION, typename PermutationArrayHandleType>
class CellSetPermutationVisitCellsWithPoints< class RConnBuilderInput<
CellSetPermutation<CellSetStructured<DIMENSION>, PermutationArrayHandleType>> CellSetPermutation<CellSetStructured<DIMENSION>, PermutationArrayHandleType>>
{ {
private: private:
@ -181,11 +223,10 @@ private:
CellSetPermutation<CellSetStructured<DIMENSION>, PermutationArrayHandleType>; CellSetPermutation<CellSetStructured<DIMENSION>, PermutationArrayHandleType>;
public: public:
using ConnectivityArrays = vtkm::cont::internal::ConnectivityExplicitInternals< using ConnectivityArrays = vtkm::cont::internal::RConnBuilderInputData<
VTKM_DEFAULT_STORAGE_TAG, // shapes array is not used
typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag,
VTKM_DEFAULT_STORAGE_TAG, VTKM_DEFAULT_STORAGE_TAG,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>; typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag,
typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag>;
template <typename Device> template <typename Device>
static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device) static ConnectivityArrays Get(const CellSetPermutationType& cellset, Device)
@ -197,9 +238,9 @@ public:
ConnectivityArrays conn; ConnectivityArrays conn;
conn.NumIndices = make_ArrayHandleConstant(numPointsInCell, numberOfCells); conn.NumIndices = make_ArrayHandleConstant(numPointsInCell, numberOfCells);
conn.IndexOffsets = ArrayHandleCounting<vtkm::Id>(0, numPointsInCell, numberOfCells); conn.Offsets = ArrayHandleCounting<vtkm::Id>(0, numPointsInCell, numberOfCells + 1);
conn.Connectivity = CellSetPermutationVisitCellsWithPointsHelpers::GetConnectivityArray( conn.Connectivity =
cellset, conn.IndexOffsets, connectivityLength, Device{}); RConnTableHelpers::GetConnectivityArray(cellset, conn.Offsets, connectivityLength, Device{});
return conn; return conn;
} }
@ -312,11 +353,11 @@ public:
const auto* other = dynamic_cast<const CellSetPermutation*>(src); const auto* other = dynamic_cast<const CellSetPermutation*>(src);
if (!other) if (!other)
{ {
throw vtkm::cont::ErrorBadType("CellSetPermutaion::DeepCopy types don't match"); throw vtkm::cont::ErrorBadType("CellSetPermutation::DeepCopy types don't match");
} }
this->FullCellSet.DeepCopy(&(other->GetFullCellSet())); this->FullCellSet.DeepCopy(&(other->GetFullCellSet()));
this->ValidCellIds = other->GetValidCellIds(); vtkm::cont::ArrayCopy(other->GetValidCellIds(), this->ValidCellIds);
} }
//This is the way you can fill the memory from another system without copying //This is the way you can fill the memory from another system without copying
@ -361,17 +402,16 @@ public:
{ {
VTKM_IS_DEVICE_ADAPTER_TAG(Device); VTKM_IS_DEVICE_ADAPTER_TAG(Device);
using ConnectiviyPortalType = using ConnectivityPortalType =
typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<Device>::PortalConst; typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<Device>::PortalConst;
using NumIndicesPortalType = typename vtkm::cont::ArrayHandle< using NumIndicesPortalType = typename vtkm::cont::ArrayHandle<
vtkm::IdComponent>::template ExecutionTypes<Device>::PortalConst; vtkm::IdComponent>::template ExecutionTypes<Device>::PortalConst;
using IndexOffsetPortalType = using OffsetPortalType =
typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<Device>::PortalConst; typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<Device>::PortalConst;
using ExecObjectType = using ExecObjectType =
vtkm::exec::ConnectivityPermutedVisitPointsWithCells<ConnectiviyPortalType, vtkm::exec::ConnectivityPermutedVisitPointsWithCells<ConnectivityPortalType,
NumIndicesPortalType, OffsetPortalType>;
IndexOffsetPortalType>;
}; };
template <typename Device> template <typename Device>
@ -397,19 +437,16 @@ public:
{ {
if (!this->VisitPointsWithCells.ElementsValid) if (!this->VisitPointsWithCells.ElementsValid)
{ {
auto pointToCell = auto connTable = internal::RConnBuilderInput<CellSetPermutation>::Get(*this, device);
internal::CellSetPermutationVisitCellsWithPoints<CellSetPermutation>::Get(*this, device); internal::ComputeRConnTable(
internal::ComputeVisitPointsWithCellsConnectivity( this->VisitPointsWithCells, connTable, this->GetNumberOfPoints(), device);
this->VisitPointsWithCells, pointToCell, this->GetNumberOfPoints(), device);
this->VisitPointsWithCells.BuildIndexOffsets(device);
} }
using ConnectivityType = typename ExecutionTypes<Device, using ConnectivityType = typename ExecutionTypes<Device,
vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell>::ExecObjectType; vtkm::TopologyElementTagCell>::ExecObjectType;
return ConnectivityType(this->VisitPointsWithCells.Connectivity.PrepareForInput(device), return ConnectivityType(this->VisitPointsWithCells.Connectivity.PrepareForInput(device),
this->VisitPointsWithCells.NumIndices.PrepareForInput(device), this->VisitPointsWithCells.Offsets.PrepareForInput(device));
this->VisitPointsWithCells.IndexOffsets.PrepareForInput(device));
} }
VTKM_CONT VTKM_CONT

@ -30,19 +30,16 @@ namespace cont
template <typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG> template <typename ConnectivityStorageTag = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG>
class VTKM_ALWAYS_EXPORT CellSetSingleType class VTKM_ALWAYS_EXPORT CellSetSingleType
: public vtkm::cont::CellSetExplicit< : public vtkm::cont::CellSetExplicit<
typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag, //ShapeStorageTag typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag, //ShapesStorageTag
typename vtkm::cont::ArrayHandleConstant<
vtkm::IdComponent>::StorageTag, //NumIndicesStorageTag
ConnectivityStorageTag, ConnectivityStorageTag,
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag //IndexOffsetStorageTag typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag //OffsetsStorageTag
> >
{ {
using Thisclass = vtkm::cont::CellSetSingleType<ConnectivityStorageTag>; using Thisclass = vtkm::cont::CellSetSingleType<ConnectivityStorageTag>;
using Superclass = vtkm::cont::CellSetExplicit< using Superclass =
typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag, vtkm::cont::CellSetExplicit<typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
typename vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag, ConnectivityStorageTag,
ConnectivityStorageTag, typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>;
typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>;
public: public:
VTKM_CONT VTKM_CONT
@ -98,7 +95,7 @@ public:
{ {
this->CellShapeAsId = vtkm::CELL_SHAPE_EMPTY; this->CellShapeAsId = vtkm::CELL_SHAPE_EMPTY;
this->Data->VisitCellsWithPoints.Connectivity.Allocate(connectivityMaxLen); this->Data->CellPointIds.Connectivity.Allocate(connectivityMaxLen);
this->Data->NumberOfCellsAdded = 0; this->Data->NumberOfCellsAdded = 0;
this->Data->ConnectivityAdded = 0; this->Data->ConnectivityAdded = 0;
@ -119,10 +116,10 @@ public:
} }
if (this->Data->ConnectivityAdded + numVertices > if (this->Data->ConnectivityAdded + numVertices >
this->Data->VisitCellsWithPoints.Connectivity.GetNumberOfValues()) this->Data->CellPointIds.Connectivity.GetNumberOfValues())
{ {
throw vtkm::cont::ErrorBadValue( throw vtkm::cont::ErrorBadValue(
"Connectivity increased passed estimated maximum connectivity."); "Connectivity increased past estimated maximum connectivity.");
} }
if (this->CellShapeAsId == vtkm::CELL_SHAPE_EMPTY) if (this->CellShapeAsId == vtkm::CELL_SHAPE_EMPTY)
@ -147,10 +144,10 @@ public:
"Inconsistent number of points in cells for CellSetSingleType."); "Inconsistent number of points in cells for CellSetSingleType.");
} }
} }
auto conn = this->Data->CellPointIds.Connectivity.GetPortalControl();
for (vtkm::IdComponent iVert = 0; iVert < numVertices; ++iVert) for (vtkm::IdComponent iVert = 0; iVert < numVertices; ++iVert)
{ {
this->Data->VisitCellsWithPoints.Connectivity.GetPortalControl().Set( conn.Set(this->Data->ConnectivityAdded + iVert, Traits::GetComponent(ids, iVert));
this->Data->ConnectivityAdded + iVert, Traits::GetComponent(ids, iVert));
} }
this->Data->NumberOfCellsAdded++; this->Data->NumberOfCellsAdded++;
this->Data->ConnectivityAdded += numVertices; this->Data->ConnectivityAdded += numVertices;
@ -161,19 +158,16 @@ public:
void CompleteAddingCells(vtkm::Id numPoints) void CompleteAddingCells(vtkm::Id numPoints)
{ {
this->Data->NumberOfPoints = numPoints; this->Data->NumberOfPoints = numPoints;
this->VisitCellsWithPoints.Connectivity.Shrink(this->ConnectivityAdded); this->CellPointIds.Connectivity.Shrink(this->ConnectivityAdded);
vtkm::Id numCells = this->NumberOfCellsAdded; vtkm::Id numCells = this->NumberOfCellsAdded;
this->VisitCellsWithPoints.Shapes = this->CellPointIds.Shapes =
vtkm::cont::make_ArrayHandleConstant(this->GetCellShape(0), numCells); vtkm::cont::make_ArrayHandleConstant(this->GetCellShape(0), numCells);
this->VisitCellsWithPoints.NumIndices = this->CellPointIds.IndexOffsets = vtkm::cont::make_ArrayHandleCounting(
vtkm::cont::make_ArrayHandleConstant(this->NumberOfPointsPerCell, numCells);
this->VisitCellsWithPoints.IndexOffsets = vtkm::cont::make_ArrayHandleCounting(
vtkm::Id(0), static_cast<vtkm::Id>(this->NumberOfPointsPerCell), numCells); vtkm::Id(0), static_cast<vtkm::Id>(this->NumberOfPointsPerCell), numCells);
this->VisitCellsWithPoints.ElementsValid = true; this->CellPointIds.ElementsValid = true;
this->VisitCellsWithPoints.IndexOffsetsValid = true;
if (this->ExpectedNumberOfCellsAdded != this->GetNumberOfCells()) if (this->ExpectedNumberOfCellsAdded != this->GetNumberOfCells())
{ {
@ -195,18 +189,18 @@ public:
this->Data->NumberOfPoints = numPoints; this->Data->NumberOfPoints = numPoints;
this->CellShapeAsId = shapeId; this->CellShapeAsId = shapeId;
this->CheckNumberOfPointsPerCell(numberOfPointsPerCell); this->CheckNumberOfPointsPerCell(numberOfPointsPerCell);
const vtkm::Id numCells = connectivity.GetNumberOfValues() / numberOfPointsPerCell; const vtkm::Id numCells = connectivity.GetNumberOfValues() / numberOfPointsPerCell;
VTKM_ASSERT((connectivity.GetNumberOfValues() % numberOfPointsPerCell) == 0); VTKM_ASSERT((connectivity.GetNumberOfValues() % numberOfPointsPerCell) == 0);
this->Data->VisitCellsWithPoints.Shapes =
vtkm::cont::make_ArrayHandleConstant(shapeId, numCells);
this->Data->VisitCellsWithPoints.NumIndices =
vtkm::cont::make_ArrayHandleConstant(numberOfPointsPerCell, numCells);
this->Data->VisitCellsWithPoints.IndexOffsets = vtkm::cont::make_ArrayHandleCounting(
vtkm::Id(0), static_cast<vtkm::Id>(numberOfPointsPerCell), numCells);
this->Data->VisitCellsWithPoints.Connectivity = connectivity;
this->Data->VisitCellsWithPoints.ElementsValid = true; this->Data->CellPointIds.Shapes = vtkm::cont::make_ArrayHandleConstant(shapeId, numCells);
this->Data->VisitCellsWithPoints.IndexOffsetsValid = true;
this->Data->CellPointIds.Offsets = vtkm::cont::make_ArrayHandleCounting(
vtkm::Id(0), static_cast<vtkm::Id>(numberOfPointsPerCell), numCells + 1);
this->Data->CellPointIds.Connectivity = connectivity;
this->Data->CellPointIds.ElementsValid = true;
this->ResetConnectivity(TopologyElementTagPoint{}, TopologyElementTagCell{}); this->ResetConnectivity(TopologyElementTagPoint{}, TopologyElementTagCell{});
} }
@ -242,11 +236,11 @@ public:
virtual void PrintSummary(std::ostream& out) const override virtual void PrintSummary(std::ostream& out) const override
{ {
out << " CellSetSingleType ShapeType " << this->CellShapeAsId << std::endl; out << " CellSetSingleType: Type=" << this->CellShapeAsId << std::endl;
out << " VisitCellsWithPoints: " << std::endl; out << " CellPointIds:" << std::endl;
this->Data->VisitCellsWithPoints.PrintSummary(out); this->Data->CellPointIds.PrintSummary(out);
out << " VisitPointsWithCells: " << std::endl; out << " PointCellIds:" << std::endl;
this->Data->VisitPointsWithCells.PrintSummary(out); this->Data->PointCellIds.PrintSummary(out);
} }
private: private:

@ -10,6 +10,8 @@
#ifndef vtk_m_cont_DataSetBuilderExplicit_h #ifndef vtk_m_cont_DataSetBuilderExplicit_h
#define vtk_m_cont_DataSetBuilderExplicit_h #define vtk_m_cont_DataSetBuilderExplicit_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h> #include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayPortalToIterators.h> #include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/CoordinateSystem.h> #include <vtkm/cont/CoordinateSystem.h>
@ -21,17 +23,9 @@ namespace cont
{ {
//Coordinates builder?? //Coordinates builder??
//Need a singlecellset handler.
class VTKM_CONT_EXPORT DataSetBuilderExplicit class VTKM_CONT_EXPORT DataSetBuilderExplicit
{ {
template <typename T>
VTKM_CONT static void CopyInto(const std::vector<T>& input, vtkm::cont::ArrayHandle<T>& output)
{
output.Allocate(static_cast<vtkm::Id>(input.size()));
std::copy(input.begin(), input.end(), ArrayPortalToIteratorBegin(output.GetPortalControl()));
}
public: public:
VTKM_CONT VTKM_CONT
DataSetBuilderExplicit() {} DataSetBuilderExplicit() {}
@ -84,8 +78,10 @@ public:
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords") const std::string& coordsNm = "coords")
{ {
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
return DataSetBuilderExplicit::BuildDataSet( return DataSetBuilderExplicit::BuildDataSet(
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm); xVals, yVals, zVals, shapes, offsets, connectivity, coordsNm);
} }
template <typename T> template <typename T>
@ -103,7 +99,8 @@ public:
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords") const std::string& coordsNm = "coords")
{ {
return DataSetBuilderExplicit::BuildDataSet(coords, shapes, numIndices, connectivity, coordsNm); auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
return DataSetBuilderExplicit::BuildDataSet(coords, shapes, offsets, connectivity, coordsNm);
} }
template <typename T, typename CellShapeTag> template <typename T, typename CellShapeTag>
@ -127,20 +124,19 @@ public:
private: private:
template <typename T> template <typename T>
static vtkm::cont::DataSet BuildDataSet( static vtkm::cont::DataSet BuildDataSet(const vtkm::cont::ArrayHandle<T>& X,
const vtkm::cont::ArrayHandle<T>& X, const vtkm::cont::ArrayHandle<T>& Y,
const vtkm::cont::ArrayHandle<T>& Y, const vtkm::cont::ArrayHandle<T>& Z,
const vtkm::cont::ArrayHandle<T>& Z, const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes, const vtkm::cont::ArrayHandle<vtkm::Id>& offsets,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const std::string& coordsNm);
const std::string& coordsNm);
template <typename T> template <typename T>
VTKM_CONT static vtkm::cont::DataSet BuildDataSet( VTKM_CONT static vtkm::cont::DataSet BuildDataSet(
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& coords, const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& coords,
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes, const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices, const vtkm::cont::ArrayHandle<vtkm::Id>& offsets,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm); const std::string& coordsNm);
@ -165,19 +161,18 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
{ {
VTKM_ASSERT(xVals.size() == yVals.size() && yVals.size() == zVals.size() && xVals.size() > 0); VTKM_ASSERT(xVals.size() == yVals.size() && yVals.size() == zVals.size() && xVals.size() > 0);
vtkm::cont::ArrayHandle<T> Xc, Yc, Zc; auto xArray = vtkm::cont::make_ArrayHandle(xVals, vtkm::CopyFlag::On);
DataSetBuilderExplicit::CopyInto(xVals, Xc); auto yArray = vtkm::cont::make_ArrayHandle(yVals, vtkm::CopyFlag::On);
DataSetBuilderExplicit::CopyInto(yVals, Yc); auto zArray = vtkm::cont::make_ArrayHandle(zVals, vtkm::CopyFlag::On);
DataSetBuilderExplicit::CopyInto(zVals, Zc);
vtkm::cont::ArrayHandle<vtkm::UInt8> Sc; auto shapesArray = vtkm::cont::make_ArrayHandle(shapes, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandle<vtkm::IdComponent> Nc; auto connArray = vtkm::cont::make_ArrayHandle(connectivity, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandle<vtkm::Id> Cc;
DataSetBuilderExplicit::CopyInto(shapes, Sc);
DataSetBuilderExplicit::CopyInto(numIndices, Nc);
DataSetBuilderExplicit::CopyInto(connectivity, Cc);
return DataSetBuilderExplicit::BuildDataSet(Xc, Yc, Zc, Sc, Nc, Cc, coordsNm); auto offsetsArray = vtkm::cont::ConvertNumIndicesToOffsets(
vtkm::cont::make_ArrayHandle(numIndices, vtkm::CopyFlag::Off));
return DataSetBuilderExplicit::BuildDataSet(
xArray, yArray, zArray, shapesArray, offsetsArray, connArray, coordsNm);
} }
template <typename T> template <typename T>
@ -186,13 +181,13 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
const vtkm::cont::ArrayHandle<T>& Y, const vtkm::cont::ArrayHandle<T>& Y,
const vtkm::cont::ArrayHandle<T>& Z, const vtkm::cont::ArrayHandle<T>& Z,
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes, const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices, const vtkm::cont::ArrayHandle<vtkm::Id>& offsets,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm) const std::string& coordsNm)
{ {
VTKM_ASSERT(X.GetNumberOfValues() == Y.GetNumberOfValues() && VTKM_ASSERT(X.GetNumberOfValues() == Y.GetNumberOfValues() &&
Y.GetNumberOfValues() == Z.GetNumberOfValues() && X.GetNumberOfValues() > 0 && Y.GetNumberOfValues() == Z.GetNumberOfValues() && X.GetNumberOfValues() > 0 &&
shapes.GetNumberOfValues() == numIndices.GetNumberOfValues()); shapes.GetNumberOfValues() + 1 == offsets.GetNumberOfValues());
vtkm::cont::DataSet dataSet; vtkm::cont::DataSet dataSet;
dataSet.AddCoordinateSystem( dataSet.AddCoordinateSystem(
@ -200,7 +195,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
vtkm::Id nPts = X.GetNumberOfValues(); vtkm::Id nPts = X.GetNumberOfValues();
vtkm::cont::CellSetExplicit<> cellSet; vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(nPts, shapes, numIndices, connectivity); cellSet.Fill(nPts, shapes, connectivity, offsets);
dataSet.SetCellSet(cellSet); dataSet.SetCellSet(cellSet);
return dataSet; return dataSet;
@ -214,24 +209,22 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
const std::vector<vtkm::Id>& connectivity, const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm) const std::string& coordsNm)
{ {
vtkm::cont::ArrayHandle<Vec<T, 3>> coordsArray; auto coordsArray = vtkm::cont::make_ArrayHandle(coords, vtkm::CopyFlag::On);
DataSetBuilderExplicit::CopyInto(coords, coordsArray); auto shapesArray = vtkm::cont::make_ArrayHandle(shapes, vtkm::CopyFlag::On);
auto connArray = vtkm::cont::make_ArrayHandle(connectivity, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandle<vtkm::UInt8> Sc; auto offsetsArray = vtkm::cont::ConvertNumIndicesToOffsets(
vtkm::cont::ArrayHandle<vtkm::IdComponent> Nc; vtkm::cont::make_ArrayHandle(numIndices, vtkm::CopyFlag::Off));
vtkm::cont::ArrayHandle<vtkm::Id> Cc;
DataSetBuilderExplicit::CopyInto(shapes, Sc);
DataSetBuilderExplicit::CopyInto(numIndices, Nc);
DataSetBuilderExplicit::CopyInto(connectivity, Cc);
return DataSetBuilderExplicit::Create(coordsArray, Sc, Nc, Cc, coordsNm); return DataSetBuilderExplicit::BuildDataSet(
coordsArray, shapesArray, offsetsArray, connArray, coordsNm);
} }
template <typename T> template <typename T>
inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet( inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& coords, const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& coords,
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes, const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices, const vtkm::cont::ArrayHandle<vtkm::Id>& offsets,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity, const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm) const std::string& coordsNm)
{ {
@ -241,7 +234,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
vtkm::Id nPts = static_cast<vtkm::Id>(coords.GetNumberOfValues()); vtkm::Id nPts = static_cast<vtkm::Id>(coords.GetNumberOfValues());
vtkm::cont::CellSetExplicit<> cellSet; vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(nPts, shapes, numIndices, connectivity); cellSet.Fill(nPts, shapes, connectivity, offsets);
dataSet.SetCellSet(cellSet); dataSet.SetCellSet(cellSet);
return dataSet; return dataSet;
@ -255,13 +248,11 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
const std::vector<vtkm::Id>& connectivity, const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm) const std::string& coordsNm)
{ {
vtkm::cont::ArrayHandle<Vec<T, 3>> coordsArray; auto coordsArray = vtkm::cont::make_ArrayHandle(coords, vtkm::CopyFlag::On);
DataSetBuilderExplicit::CopyInto(coords, coordsArray); auto connArray = vtkm::cont::make_ArrayHandle(connectivity, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandle<vtkm::Id> Cc; return DataSetBuilderExplicit::Create(
DataSetBuilderExplicit::CopyInto(connectivity, Cc); coordsArray, tag, numberOfPointsPerCell, connArray, coordsNm);
return DataSetBuilderExplicit::Create(coordsArray, tag, numberOfPointsPerCell, Cc, coordsNm);
} }
template <typename T, typename CellShapeTag> template <typename T, typename CellShapeTag>

@ -12,6 +12,7 @@
#include <vtkm/CellShape.h> #include <vtkm/CellShape.h>
#include <vtkm/cont/Algorithm.h> #include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandle.h> #include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h> #include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleConstant.h> #include <vtkm/cont/ArrayHandleConstant.h>
@ -26,67 +27,24 @@ namespace cont
namespace internal namespace internal
{ {
template <typename NumIndicesArrayType, typename IndexOffsetArrayType> template <typename ShapesStorageTag = VTKM_DEFAULT_STORAGE_TAG,
void buildIndexOffsets(const NumIndicesArrayType& numIndices,
IndexOffsetArrayType& offsets,
vtkm::cont::DeviceAdapterId device,
std::true_type)
{
//We first need to make sure that NumIndices and IndexOffsetArrayType
//have the same type so we can call scane exclusive
using CastedNumIndicesType = vtkm::cont::ArrayHandleCast<vtkm::Id, NumIndicesArrayType>;
// Although technically we are making changes to this object, the changes
// are logically consistent with the previous state, so we consider it
// valid under const.
vtkm::cont::Algorithm::ScanExclusive(device, CastedNumIndicesType(numIndices), offsets);
}
template <typename NumIndicesArrayType, typename IndexOffsetArrayType>
void buildIndexOffsets(const NumIndicesArrayType&,
IndexOffsetArrayType&,
vtkm::cont::DeviceAdapterId,
std::false_type)
{
//this is a no-op as the storage for the offsets is an implicit handle
//and should already be built. This signature exists so that
//the compiler doesn't try to generate un-used code that will
//try and run Algorithm::ScanExclusive on an implicit array which will
//cause a compile time failure.
}
template <typename ArrayHandleIndices, typename ArrayHandleOffsets>
void buildIndexOffsets(const ArrayHandleIndices& numIndices,
ArrayHandleOffsets offsets,
vtkm::cont::DeviceAdapterId deviceId)
{
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<ArrayHandleOffsets>;
buildIndexOffsets(numIndices, offsets, deviceId, typename IsWritable::type());
}
template <typename ShapeStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_STORAGE_TAG, typename ConnectivityStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename IndexOffsetStorageTag = VTKM_DEFAULT_STORAGE_TAG> typename OffsetsStorageTag = VTKM_DEFAULT_STORAGE_TAG>
struct ConnectivityExplicitInternals struct ConnectivityExplicitInternals
{ {
using ShapeArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorageTag>; using ShapesArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapesStorageTag>;
using NumIndicesArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorageTag>;
using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>; using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag>;
using IndexOffsetArrayType = vtkm::cont::ArrayHandle<vtkm::Id, IndexOffsetStorageTag>; using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
ShapeArrayType Shapes; ShapesArrayType Shapes;
NumIndicesArrayType NumIndices;
ConnectivityArrayType Connectivity; ConnectivityArrayType Connectivity;
mutable IndexOffsetArrayType IndexOffsets; OffsetsArrayType Offsets;
bool ElementsValid; bool ElementsValid;
mutable bool IndexOffsetsValid;
VTKM_CONT VTKM_CONT
ConnectivityExplicitInternals() ConnectivityExplicitInternals()
: ElementsValid(false) : ElementsValid(false)
, IndexOffsetsValid(false)
{ {
} }
@ -102,26 +60,8 @@ struct ConnectivityExplicitInternals
void ReleaseResourcesExecution() void ReleaseResourcesExecution()
{ {
this->Shapes.ReleaseResourcesExecution(); this->Shapes.ReleaseResourcesExecution();
this->NumIndices.ReleaseResourcesExecution();
this->Connectivity.ReleaseResourcesExecution(); this->Connectivity.ReleaseResourcesExecution();
this->IndexOffsets.ReleaseResourcesExecution(); this->Offsets.ReleaseResourcesExecution();
}
VTKM_CONT void BuildIndexOffsets(vtkm::cont::DeviceAdapterId deviceId) const
{
if (deviceId == vtkm::cont::DeviceAdapterTagUndefined())
{
throw vtkm::cont::ErrorBadValue("Cannot build indices using DeviceAdapterTagUndefined");
}
VTKM_ASSERT(this->ElementsValid);
if (!this->IndexOffsetsValid)
{
buildIndexOffsets(this->NumIndices, this->IndexOffsets, deviceId);
this->IndexOffsetsValid = true;
}
} }
VTKM_CONT VTKM_CONT
@ -131,19 +71,10 @@ struct ConnectivityExplicitInternals
{ {
out << " Shapes: "; out << " Shapes: ";
vtkm::cont::printSummary_ArrayHandle(this->Shapes, out); vtkm::cont::printSummary_ArrayHandle(this->Shapes, out);
out << " NumIndices: ";
vtkm::cont::printSummary_ArrayHandle(this->NumIndices, out);
out << " Connectivity: "; out << " Connectivity: ";
vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out); vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out);
if (this->IndexOffsetsValid) out << " Offsets: ";
{ vtkm::cont::printSummary_ArrayHandle(this->Offsets, out);
out << " IndexOffsets: ";
vtkm::cont::printSummary_ArrayHandle(this->IndexOffsets, out);
}
else
{
out << " IndexOffsets: Not Allocated" << std::endl;
}
} }
else else
{ {
@ -225,95 +156,73 @@ struct ConnIdxToCellIdCalcSingleType
vtkm::Id operator()(vtkm::Id inIdx) const { return inIdx / this->CellSize; } vtkm::Id operator()(vtkm::Id inIdx) const { return inIdx / this->CellSize; }
}; };
template <typename VisitCellsWithPoints, typename VisitPointsWithCells, typename Device> template <typename ConnTableT, typename RConnTableT, typename Device>
void ComputeVisitPointsWithCellsConnectivity(VisitPointsWithCells& cell2Point, void ComputeRConnTable(RConnTableT& rConnTable,
const VisitCellsWithPoints& point2Cell, const ConnTableT& connTable,
vtkm::Id numberOfPoints, vtkm::Id numberOfPoints,
Device) Device)
{ {
if (cell2Point.ElementsValid) if (rConnTable.ElementsValid)
{ {
return; return;
} }
auto& conn = point2Cell.Connectivity; const auto& conn = connTable.Connectivity;
auto& rConn = cell2Point.Connectivity; auto& rConn = rConnTable.Connectivity;
auto& rNumIndices = cell2Point.NumIndices; auto& rOffsets = rConnTable.Offsets;
auto& rIndexOffsets = cell2Point.IndexOffsets; const vtkm::Id rConnSize = conn.GetNumberOfValues();
vtkm::Id rConnSize = conn.GetNumberOfValues();
auto offInPortal = point2Cell.IndexOffsets.PrepareForInput(Device{}); const auto offInPortal = connTable.Offsets.PrepareForInput(Device{});
PassThrough idxCalc{}; PassThrough idxCalc{};
ConnIdxToCellIdCalc<decltype(offInPortal)> cellIdCalc{ offInPortal }; ConnIdxToCellIdCalc<decltype(offInPortal)> cellIdCalc{ offInPortal };
vtkm::cont::internal::ReverseConnectivityBuilder builder; vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, Device());
rConn,
rNumIndices,
rIndexOffsets,
idxCalc,
cellIdCalc,
numberOfPoints,
rConnSize,
Device());
// Set the VisitPointsWithCells information rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
cell2Point.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints); static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
cell2Point.ElementsValid = true; rConnTable.ElementsValid = true;
cell2Point.IndexOffsetsValid = true;
} }
// Specialize for CellSetSingleType: // Specialize for CellSetSingleType:
template <typename ShapeStorageTag, template <typename RConnTableT, typename ConnectivityStorageTag, typename Device>
typename ConnectivityStorageTag, void ComputeRConnTable(RConnTableT& rConnTable,
typename IndexOffsetStorageTag, const ConnectivityExplicitInternals< // SingleType specialization types:
typename VisitPointsWithCells, typename vtkm::cont::ArrayHandleConstant<vtkm::UInt8>::StorageTag,
typename Device> ConnectivityStorageTag,
void ComputeVisitPointsWithCellsConnectivity( typename vtkm::cont::ArrayHandleCounting<vtkm::Id>::StorageTag>& connTable,
VisitPointsWithCells& cell2Point, vtkm::Id numberOfPoints,
const ConnectivityExplicitInternals< Device)
ShapeStorageTag,
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent>::StorageTag, // nIndices
ConnectivityStorageTag,
IndexOffsetStorageTag>& point2Cell,
vtkm::Id numberOfPoints,
Device)
{ {
if (cell2Point.ElementsValid) if (rConnTable.ElementsValid)
{ {
return; return;
} }
auto& conn = point2Cell.Connectivity; const auto& conn = connTable.Connectivity;
auto& rConn = cell2Point.Connectivity; auto& rConn = rConnTable.Connectivity;
auto& rNumIndices = cell2Point.NumIndices; auto& rOffsets = rConnTable.Offsets;
auto& rIndexOffsets = cell2Point.IndexOffsets; const vtkm::Id rConnSize = conn.GetNumberOfValues();
vtkm::Id rConnSize = conn.GetNumberOfValues();
auto sizesInPortal = point2Cell.NumIndices.GetPortalConstControl(); const vtkm::IdComponent cellSize = [&]() -> vtkm::IdComponent {
vtkm::IdComponent cellSize = sizesInPortal.GetNumberOfValues() > 0 ? sizesInPortal.Get(0) : 0; 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{}; PassThrough idxCalc{};
ConnIdxToCellIdCalcSingleType cellIdCalc{ cellSize }; ConnIdxToCellIdCalcSingleType cellIdCalc{ cellSize };
vtkm::cont::internal::ReverseConnectivityBuilder builder; vtkm::cont::internal::ReverseConnectivityBuilder builder;
builder.Run(conn, builder.Run(conn, rConn, rOffsets, idxCalc, cellIdCalc, numberOfPoints, rConnSize, Device());
rConn,
rNumIndices,
rIndexOffsets,
idxCalc,
cellIdCalc,
numberOfPoints,
rConnSize,
Device());
// Set the VisitPointsWithCells information rConnTable.Shapes = vtkm::cont::make_ArrayHandleConstant(
cell2Point.Shapes = vtkm::cont::make_ArrayHandleConstant(
static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints); static_cast<vtkm::UInt8>(CELL_SHAPE_VERTEX), numberOfPoints);
cell2Point.ElementsValid = true; rConnTable.ElementsValid = true;
cell2Point.IndexOffsetsValid = true;
} }
} }
} }

@ -131,15 +131,13 @@ public:
VTKM_CONT VTKM_CONT
template <typename ConnArray, template <typename ConnArray,
typename RConnArray, typename RConnArray,
typename RNumArray, typename ROffsetsArray,
typename RIndexArray,
typename RConnToConnIdxCalc, typename RConnToConnIdxCalc,
typename ConnIdxToCellIdxCalc, typename ConnIdxToCellIdxCalc,
typename Device> typename Device>
inline void Run(const ConnArray& conn, inline void Run(const ConnArray& conn,
RConnArray& rConn, RConnArray& rConn,
RNumArray& rNumIndices, ROffsetsArray& rOffsets,
RIndexArray& rIndexOffsets,
const RConnToConnIdxCalc& rConnToConnCalc, const RConnToConnIdxCalc& rConnToConnCalc,
const ConnIdxToCellIdxCalc& cellIdCalc, const ConnIdxToCellIdxCalc& cellIdCalc,
vtkm::Id numberOfPoints, vtkm::Id numberOfPoints,
@ -152,12 +150,13 @@ public:
auto zeros = vtkm::cont::make_ArrayHandleConstant(vtkm::IdComponent{ 0 }, numberOfPoints); auto zeros = vtkm::cont::make_ArrayHandleConstant(vtkm::IdComponent{ 0 }, numberOfPoints);
// Compute RConn offsets by atomically building a histogram and doing an // Compute RConn offsets by atomically building a histogram and doing an
// exclusive scan. // extended scan.
// //
// Example: // Example:
// (in) Conn: | 3 0 1 2 | 3 0 1 3 | 3 0 3 4 | 3 3 4 5 | // (in) Conn: | 3 0 1 2 | 3 0 1 3 | 3 0 3 4 | 3 3 4 5 |
// (out) RNumIndices: 3 2 1 3 2 1 // (out) RNumIndices: 3 2 1 3 2 1
// (out) RIdxOffsets: 0 3 5 6 9 11 // (out) RIdxOffsets: 0 3 5 6 9 11 12
vtkm::cont::ArrayHandle<vtkm::IdComponent> rNumIndices;
{ // allocate and zero the numIndices array: { // allocate and zero the numIndices array:
Algo::Copy(zeros, rNumIndices); Algo::Copy(zeros, rNumIndices);
} }
@ -165,17 +164,15 @@ public:
{ // Build histogram: { // Build histogram:
vtkm::cont::AtomicArray<vtkm::IdComponent> atomicCounter{ rNumIndices }; vtkm::cont::AtomicArray<vtkm::IdComponent> atomicCounter{ rNumIndices };
auto ac = atomicCounter.PrepareForExecution(Device()); auto ac = atomicCounter.PrepareForExecution(Device());
rcb::BuildHistogram<decltype(ac), decltype(connPortal), RConnToConnIdxCalc> histoGen{ using BuildHisto =
ac, connPortal, rConnToConnCalc rcb::BuildHistogram<decltype(ac), decltype(connPortal), RConnToConnIdxCalc>;
}; BuildHisto histoGen{ ac, connPortal, rConnToConnCalc };
Algo::Schedule(histoGen, rConnSize); Algo::Schedule(histoGen, rConnSize);
} }
{ // Compute offsets: { // Compute offsets:
auto rNumIndicesAsId = Algo::ScanExtended(vtkm::cont::make_ArrayHandleCast<vtkm::Id>(rNumIndices), rOffsets);
vtkm::cont::make_ArrayHandleCast<typename RIndexArray::ValueType>(rNumIndices);
Algo::ScanExclusive(rNumIndicesAsId, rIndexOffsets);
} }
{ // Reset the numIndices array to 0's: { // Reset the numIndices array to 0's:
@ -198,16 +195,16 @@ public:
{ {
vtkm::cont::AtomicArray<vtkm::IdComponent> atomicCounter{ rNumIndices }; vtkm::cont::AtomicArray<vtkm::IdComponent> atomicCounter{ rNumIndices };
auto ac = atomicCounter.PrepareForExecution(Device()); auto ac = atomicCounter.PrepareForExecution(Device());
auto rOffsetPortal = rIndexOffsets.PrepareForInput(Device()); auto rOffsetPortal = rOffsets.PrepareForInput(Device());
auto rConnPortal = rConn.PrepareForOutput(rConnSize, Device()); auto rConnPortal = rConn.PrepareForOutput(rConnSize, Device());
rcb::GenerateRConn<decltype(ac), using GenRConnT = rcb::GenerateRConn<decltype(ac),
decltype(connPortal), decltype(connPortal),
decltype(rOffsetPortal), decltype(rOffsetPortal),
decltype(rConnPortal), decltype(rConnPortal),
RConnToConnIdxCalc, RConnToConnIdxCalc,
ConnIdxToCellIdxCalc> ConnIdxToCellIdxCalc>;
rConnGen{ ac, connPortal, rOffsetPortal, rConnPortal, rConnToConnCalc, cellIdCalc }; GenRConnT rConnGen{ ac, connPortal, rOffsetPortal, rConnPortal, rConnToConnCalc, cellIdCalc };
Algo::Schedule(rConnGen, rConnSize); Algo::Schedule(rConnGen, rConnSize);
} }

@ -229,11 +229,10 @@ namespace detail
struct TestEqualCellSet struct TestEqualCellSet
{ {
template <typename ShapeST, typename CountST, typename ConnectivityST, typename OffsetST> template <typename ShapeST, typename ConnectivityST, typename OffsetST>
void operator()( void operator()(const vtkm::cont::CellSetExplicit<ShapeST, ConnectivityST, OffsetST>& cs1,
const vtkm::cont::CellSetExplicit<ShapeST, CountST, ConnectivityST, OffsetST>& cs1, const vtkm::cont::CellSetExplicit<ShapeST, ConnectivityST, OffsetST>& cs2,
const vtkm::cont::CellSetExplicit<ShapeST, CountST, ConnectivityST, OffsetST>& cs2, TestEqualResult& result) const
TestEqualResult& result) const
{ {
vtkm::TopologyElementTagCell visitTopo{}; vtkm::TopologyElementTagCell visitTopo{};
vtkm::TopologyElementTagPoint incidentTopo{}; vtkm::TopologyElementTagPoint incidentTopo{};
@ -266,8 +265,8 @@ struct TestEqualCellSet
result.PushMessage("connectivity arrays don't match"); result.PushMessage("connectivity arrays don't match");
return; return;
} }
result = test_equal_ArrayHandles(cs1.GetIndexOffsetArray(visitTopo, incidentTopo), result = test_equal_ArrayHandles(cs1.GetOffsetsArray(visitTopo, incidentTopo),
cs2.GetIndexOffsetArray(visitTopo, incidentTopo)); cs2.GetOffsetsArray(visitTopo, incidentTopo));
if (!result) if (!result)
{ {
result.PushMessage("offsets arrays don't match"); result.PushMessage("offsets arrays don't match");

@ -100,14 +100,14 @@ private:
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes = vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapes =
cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell()); cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices = auto numIndices =
cellset.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell()); cellset.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::Id> conn = vtkm::cont::ArrayHandle<vtkm::Id> conn =
cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell()); cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
VTKM_TEST_ASSERT(TestArrayHandle(shapes, correctShapes, numPoints), "Got incorrect shapes"); VTKM_TEST_ASSERT(TestArrayHandle(shapes, correctShapes, numPoints), "Got incorrect shapes");
VTKM_TEST_ASSERT(TestArrayHandle(numIndices, correctNumIndices, numPoints), VTKM_TEST_ASSERT(TestArrayHandle(numIndices, correctNumIndices, numPoints),
"Got incorrect shapes"); "Got incorrect numIndices");
// Some device adapters have unstable sorts, which may cause the order of // Some device adapters have unstable sorts, which may cause the order of
// the indices for each point to be different but still correct. Iterate // the indices for each point to be different but still correct. Iterate

@ -105,26 +105,20 @@ private:
//verify that the point to cell connectivity types are correct //verify that the point to cell connectivity types are correct
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapesPointToCell = vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapesPointToCell =
cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
vtkm::cont::ArrayHandleConstant<vtkm::IdComponent> numIndicesPointToCell =
cellset.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
vtkm::cont::ArrayHandle<vtkm::Id> connPointToCell = vtkm::cont::ArrayHandle<vtkm::Id> connPointToCell =
cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
VTKM_TEST_ASSERT(shapesPointToCell.GetNumberOfValues() == 3, "Wrong number of shapes"); VTKM_TEST_ASSERT(shapesPointToCell.GetNumberOfValues() == 3, "Wrong number of shapes");
VTKM_TEST_ASSERT(numIndicesPointToCell.GetNumberOfValues() == 3, "Wrong number of indices");
VTKM_TEST_ASSERT(connPointToCell.GetNumberOfValues() == 9, "Wrong connectivity length"); VTKM_TEST_ASSERT(connPointToCell.GetNumberOfValues() == 9, "Wrong connectivity length");
//verify that the cell to point connectivity types are correct //verify that the cell to point connectivity types are correct
//note the handle storage types differ compared to point to cell //note the handle storage types differ compared to point to cell
vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapesCellToPoint = vtkm::cont::ArrayHandleConstant<vtkm::UInt8> shapesCellToPoint =
cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell()); cellset.GetShapesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndicesCellToPoint =
cellset.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::Id> connCellToPoint = vtkm::cont::ArrayHandle<vtkm::Id> connCellToPoint =
cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell()); cellset.GetConnectivityArray(vtkm::TopologyElementTagPoint(), vtkm::TopologyElementTagCell());
VTKM_TEST_ASSERT(shapesCellToPoint.GetNumberOfValues() == 5, "Wrong number of shapes"); VTKM_TEST_ASSERT(shapesCellToPoint.GetNumberOfValues() == 5, "Wrong number of shapes");
VTKM_TEST_ASSERT(numIndicesCellToPoint.GetNumberOfValues() == 5, "Wrong number of indices");
VTKM_TEST_ASSERT(connCellToPoint.GetNumberOfValues() == 9, "Wrong connectivity length"); VTKM_TEST_ASSERT(connCellToPoint.GetNumberOfValues() == 9, "Wrong connectivity length");
//run a basic for-each topology algorithm on this //run a basic for-each topology algorithm on this

@ -75,8 +75,10 @@ vtkm::cont::CellSetExplicit<> MakeCellSetExplicit()
vtkm::cont::ArrayHandle<vtkm::Id> connectivity; vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
vtkm::cont::ArrayCopy(BaseLineConnectivity, connectivity); vtkm::cont::ArrayCopy(BaseLineConnectivity, connectivity);
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
vtkm::cont::CellSetExplicit<> cellset; vtkm::cont::CellSetExplicit<> cellset;
cellset.Fill(BaseLineNumberOfPoints, shapes, numIndices, connectivity); cellset.Fill(BaseLineNumberOfPoints, shapes, connectivity, offsets);
return cellset; return cellset;
} }

@ -22,18 +22,18 @@ using PointTag = vtkm::TopologyElementTagPoint;
const vtkm::Id numberOfPoints = 11; const vtkm::Id numberOfPoints = 11;
vtkm::UInt8 g_shapes[] = { static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_HEXAHEDRON), const vtkm::UInt8 g_shapes[] = { static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_HEXAHEDRON),
static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_PYRAMID), static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_PYRAMID),
static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_TETRA), static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_TETRA),
static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_WEDGE) }; static_cast<vtkm::UInt8>(vtkm::CELL_SHAPE_WEDGE) };
const vtkm::UInt8 g_shapes2[] = { g_shapes[1], g_shapes[2] };
vtkm::IdComponent g_numIndices[] = { 8, 5, 4, 6 }; const vtkm::Id g_offsets[] = { 0, 8, 13, 17, 23 };
const vtkm::Id g_offsets2[] = { 0, 5, 9 };
vtkm::Id g_indexOffset[] = { 0, 8, 13, 17 }; const vtkm::Id g_connectivity[] = { 0, 1, 5, 4, 3, 2, 6, 7, 1, 5, 6, 2,
8, 5, 8, 10, 6, 4, 7, 9, 5, 6, 10 };
vtkm::Id g_connectivity[] = { const vtkm::Id g_connectivity2[] = { 1, 5, 6, 2, 8, 5, 8, 10, 6 };
0, 1, 5, 4, 3, 2, 6, 7, 1, 5, 6, 2, 8, 5, 8, 10, 6, 4, 7, 9, 5, 6, 10
};
template <typename T, std::size_t Length> template <typename T, std::size_t Length>
vtkm::Id ArrayLength(const T (&)[Length]) vtkm::Id ArrayLength(const T (&)[Length])
@ -46,10 +46,9 @@ vtkm::cont::CellSetExplicit<> MakeTestCellSet1()
{ {
vtkm::cont::CellSetExplicit<> cs; vtkm::cont::CellSetExplicit<> cs;
cs.Fill(numberOfPoints, cs.Fill(numberOfPoints,
vtkm::cont::make_ArrayHandle(g_shapes, 4), vtkm::cont::make_ArrayHandle(g_shapes, ArrayLength(g_shapes)),
vtkm::cont::make_ArrayHandle(g_numIndices, 4),
vtkm::cont::make_ArrayHandle(g_connectivity, ArrayLength(g_connectivity)), vtkm::cont::make_ArrayHandle(g_connectivity, ArrayLength(g_connectivity)),
vtkm::cont::make_ArrayHandle(g_indexOffset, 4)); vtkm::cont::make_ArrayHandle(g_offsets, ArrayLength(g_offsets)));
return cs; return cs;
} }
@ -58,10 +57,9 @@ vtkm::cont::CellSetExplicit<> MakeTestCellSet2()
{ {
vtkm::cont::CellSetExplicit<> cs; vtkm::cont::CellSetExplicit<> cs;
cs.Fill(numberOfPoints, cs.Fill(numberOfPoints,
vtkm::cont::make_ArrayHandle(g_shapes + 1, 2), vtkm::cont::make_ArrayHandle(g_shapes2, ArrayLength(g_shapes2)),
vtkm::cont::make_ArrayHandle(g_numIndices + 1, 2), vtkm::cont::make_ArrayHandle(g_connectivity2, ArrayLength(g_connectivity2)),
vtkm::cont::make_ArrayHandle(g_connectivity + g_indexOffset[1], vtkm::cont::make_ArrayHandle(g_offsets2, ArrayLength(g_offsets2)));
g_indexOffset[3] - g_indexOffset[1]));
return cs; return cs;
} }
@ -107,7 +105,8 @@ void TestCellSetExplicit()
"result length not equal to number of cells"); "result length not equal to number of cells");
for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i) for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i)
{ {
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(i) == g_numIndices[i], "incorrect result"); VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(i) == cellset.GetNumberOfPointsInCell(i),
"incorrect result");
} }
std::cout << "\tTesting CellToPoint\n"; std::cout << "\tTesting CellToPoint\n";
@ -131,9 +130,11 @@ void TestCellSetExplicit()
VTKM_TEST_ASSERT(result.GetNumberOfValues() == cellset.GetNumberOfCells(), VTKM_TEST_ASSERT(result.GetNumberOfValues() == cellset.GetNumberOfCells(),
"result length not equal to number of cells"); "result length not equal to number of cells");
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(0) == g_numIndices[1] && for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i)
result.GetPortalConstControl().Get(1) == g_numIndices[2], {
"incorrect result"); VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(i) == cellset.GetNumberOfPointsInCell(i),
"incorrect result");
}
std::cout << "\tTesting CellToPoint\n"; std::cout << "\tTesting CellToPoint\n";
vtkm::worklet::DispatcherMapTopology<WorkletCellToPoint>().Invoke(cellset, result); vtkm::worklet::DispatcherMapTopology<WorkletCellToPoint>().Invoke(cellset, result);
@ -144,7 +145,8 @@ void TestCellSetExplicit()
vtkm::Id expected2[] = { 0, 1, 1, 0, 0, 2, 2, 0, 2, 0, 1 }; vtkm::Id expected2[] = { 0, 1, 1, 0, 0, 2, 2, 0, 2, 0, 1 };
for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i) for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i)
{ {
VTKM_TEST_ASSERT(result.GetPortalConstControl().Get(i) == expected2[i], "incorrect result"); VTKM_TEST_ASSERT(
result.GetPortalConstControl().Get(i) == expected2[i], "incorrect result at ", i);
} }
std::cout << "----------------------------------------------------\n"; std::cout << "----------------------------------------------------\n";
@ -152,7 +154,7 @@ void TestCellSetExplicit()
std::cout << "\tTesting resource releasing in CellSetExplicit\n"; std::cout << "\tTesting resource releasing in CellSetExplicit\n";
cellset.ReleaseResourcesExecution(); cellset.ReleaseResourcesExecution();
VTKM_TEST_ASSERT(cellset.GetNumberOfCells() == ArrayLength(g_numIndices) / 2, VTKM_TEST_ASSERT(cellset.GetNumberOfCells() == ArrayLength(g_shapes) / 2,
"release execution resources should not change the number of cells"); "release execution resources should not change the number of cells");
VTKM_TEST_ASSERT(cellset.GetNumberOfPoints() == ArrayLength(expected2), VTKM_TEST_ASSERT(cellset.GetNumberOfPoints() == ArrayLength(expected2),
"release execution resources should not change the number of points"); "release execution resources should not change the number of points");

@ -20,10 +20,7 @@ namespace vtkm
namespace exec namespace exec
{ {
template <typename ShapePortalType, template <typename ShapesPortalType, typename ConnectivityPortalType, typename OffsetsPortalType>
typename NumIndicesPortalType,
typename ConnectivityPortalType,
typename IndexOffsetPortalType>
class ConnectivityExplicit class ConnectivityExplicit
{ {
public: public:
@ -31,14 +28,12 @@ public:
ConnectivityExplicit() {} ConnectivityExplicit() {}
ConnectivityExplicit(const ShapePortalType& shapePortal, ConnectivityExplicit(const ShapesPortalType& shapesPortal,
const NumIndicesPortalType& numIndicesPortal,
const ConnectivityPortalType& connPortal, const ConnectivityPortalType& connPortal,
const IndexOffsetPortalType& indexOffsetPortal) const OffsetsPortalType& offsetsPortal)
: Shapes(shapePortal) : Shapes(shapesPortal)
, NumIndices(numIndicesPortal)
, Connectivity(connPortal) , Connectivity(connPortal)
, IndexOffset(indexOffsetPortal) , Offsets(offsetsPortal)
{ {
} }
@ -51,7 +46,10 @@ public:
CellShapeTag GetCellShape(vtkm::Id index) const { return CellShapeTag(this->Shapes.Get(index)); } CellShapeTag GetCellShape(vtkm::Id index) const { return CellShapeTag(this->Shapes.Get(index)); }
VTKM_EXEC VTKM_EXEC
vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const { return this->NumIndices.Get(index); } vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const
{
return static_cast<vtkm::IdComponent>(this->Offsets.Get(index + 1) - this->Offsets.Get(index));
}
using IndicesType = vtkm::VecFromPortal<ConnectivityPortalType>; using IndicesType = vtkm::VecFromPortal<ConnectivityPortalType>;
@ -63,16 +61,17 @@ public:
VTKM_EXEC VTKM_EXEC
IndicesType GetIndices(vtkm::Id index) const IndicesType GetIndices(vtkm::Id index) const
{ {
vtkm::Id offset = this->IndexOffset.Get(index); const vtkm::Id offset = this->Offsets.Get(index);
vtkm::IdComponent length = this->NumIndices.Get(index); const vtkm::Id endOffset = this->Offsets.Get(index + 1);
const auto length = static_cast<vtkm::IdComponent>(endOffset - offset);
return IndicesType(this->Connectivity, length, offset); return IndicesType(this->Connectivity, length, offset);
} }
private: private:
ShapePortalType Shapes; ShapesPortalType Shapes;
NumIndicesPortalType NumIndices;
ConnectivityPortalType Connectivity; ConnectivityPortalType Connectivity;
IndexOffsetPortalType IndexOffset; OffsetsPortalType Offsets;
}; };
} // namespace exec } // namespace exec

@ -80,9 +80,7 @@ public:
OriginalConnectivity Connectivity; OriginalConnectivity Connectivity;
}; };
template <typename ConnectivityPortalType, template <typename ConnectivityPortalType, typename OffsetPortalType>
typename NumIndicesPortalType,
typename IndexOffsetPortalType>
class ConnectivityPermutedVisitPointsWithCells class ConnectivityPermutedVisitPointsWithCells
{ {
public: public:
@ -93,32 +91,36 @@ public:
ConnectivityPermutedVisitPointsWithCells() = default; ConnectivityPermutedVisitPointsWithCells() = default;
ConnectivityPermutedVisitPointsWithCells(const ConnectivityPortalType& connectivity, ConnectivityPermutedVisitPointsWithCells(const ConnectivityPortalType& connectivity,
const NumIndicesPortalType& numIndices, const OffsetPortalType& offsets)
const IndexOffsetPortalType& indexOffset)
: Connectivity(connectivity) : Connectivity(connectivity)
, NumIndices(numIndices) , Offsets(offsets)
, IndexOffset(indexOffset)
{ {
} }
VTKM_EXEC VTKM_EXEC
SchedulingRangeType GetNumberOfElements() const { return this->NumIndices.GetNumberOfValues(); } SchedulingRangeType GetNumberOfElements() const { return this->Offsets.GetNumberOfValues() - 1; }
VTKM_EXEC CellShapeTag GetCellShape(vtkm::Id) const { return CellShapeTag(); } VTKM_EXEC CellShapeTag GetCellShape(vtkm::Id) const { return CellShapeTag(); }
VTKM_EXEC VTKM_EXEC
vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const { return this->NumIndices.Get(index); } vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const
{
const vtkm::Id offBegin = this->Offsets.Get(index);
const vtkm::Id offEnd = this->Offsets.Get(index + 1);
return static_cast<vtkm::IdComponent>(offEnd - offBegin);
}
VTKM_EXEC IndicesType GetIndices(vtkm::Id index) const VTKM_EXEC IndicesType GetIndices(vtkm::Id index) const
{ {
const vtkm::Id offBegin = this->Offsets.Get(index);
const vtkm::Id offEnd = this->Offsets.Get(index + 1);
return IndicesType( return IndicesType(
this->Connectivity, this->NumIndices.Get(index), this->IndexOffset.Get(index)); this->Connectivity, static_cast<vtkm::IdComponent>(offEnd - offBegin), offBegin);
} }
private: private:
ConnectivityPortalType Connectivity; ConnectivityPortalType Connectivity;
NumIndicesPortalType NumIndices; OffsetPortalType Offsets;
IndexOffsetPortalType IndexOffset;
}; };
} }
} // namespace vtkm::exec } // namespace vtkm::exec

@ -44,22 +44,24 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes; vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
vtkm::cont::ArrayHandle<vtkm::Id> offsets; vtkm::cont::ArrayHandle<vtkm::Id> offsets;
vtkm::Id connectivitySize; vtkm::Id connectivitySize;
vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connectivitySize); vtkm::cont::ConvertNumIndicesToOffsets(numIndices, offsets, connectivitySize);
numIndices.ReleaseResourcesExecution(); numIndices.ReleaseResourcesExecution();
vtkm::cont::ArrayHandle<vtkm::Id> connectivity; vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
connectivity.Allocate(connectivitySize); connectivity.Allocate(connectivitySize);
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
this->Invoke(worklet::CellDeepCopy::PassCellStructure{}, this->Invoke(worklet::CellDeepCopy::PassCellStructure{},
deducedCellSet, deducedCellSet,
shapes, shapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets)); vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim));
shapes.ReleaseResourcesExecution(); shapes.ReleaseResourcesExecution();
offsets.ReleaseResourcesExecution(); offsets.ReleaseResourcesExecution();
connectivity.ReleaseResourcesExecution(); connectivity.ReleaseResourcesExecution();
outputCellSet.Fill( outputCellSet.Fill(deducedCellSet.GetNumberOfPoints(), shapes, connectivity, offsets);
deducedCellSet.GetNumberOfPoints(), shapes, numIndices, connectivity, offsets);
//Release the input grid from the execution space //Release the input grid from the execution space
deducedCellSet.ReleaseResourcesExecution(); deducedCellSet.ReleaseResourcesExecution();

@ -154,8 +154,9 @@ private:
} }
else else
{ {
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
vtkm::cont::CellSetExplicit<> cellSet; vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(numPoints, shapes, numIndices, connectivity); cellSet.Fill(numPoints, shapes, connectivity, offsets);
this->DataSet.SetCellSet(cellSet); this->DataSet.SetCellSet(cellSet);
} }

@ -80,8 +80,9 @@ private:
} }
else else
{ {
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
vtkm::cont::CellSetExplicit<> cellSet; vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(numPoints, shapes, numIndices, connectivity); cellSet.Fill(numPoints, shapes, connectivity, offsets);
this->DataSet.SetCellSet(cellSet); this->DataSet.SetCellSet(cellSet);
} }

@ -685,9 +685,10 @@ void MeshConnectivityBuilder::BuildConnectivity(
const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray( const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
const vtkm::cont::ArrayHandleCounting<vtkm::Id> shapeOffsets = const vtkm::cont::ArrayHandleCounting<vtkm::Id> offsets = cellSetUnstructured.GetOffsetsArray(
cellSetUnstructured.GetIndexOffsetArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
vtkm::TopologyElementTagPoint()); const auto shapeOffsets =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity; vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity;
vtkm::cont::ArrayHandle<vtkm::Id3> cellFaceId; vtkm::cont::ArrayHandle<vtkm::Id3> cellFaceId;
@ -746,8 +747,10 @@ void MeshConnectivityBuilder::BuildConnectivity(
const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray( const vtkm::cont::ArrayHandle<vtkm::Id> conn = cellSetUnstructured.GetConnectivityArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
const vtkm::cont::ArrayHandle<vtkm::Id> shapeOffsets = cellSetUnstructured.GetIndexOffsetArray( const vtkm::cont::ArrayHandle<vtkm::Id> offsets = cellSetUnstructured.GetOffsetsArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
const auto shapeOffsets =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity; vtkm::cont::ArrayHandle<vtkm::Id> faceConnectivity;
vtkm::cont::ArrayHandle<vtkm::Id3> cellFaceId; vtkm::cont::ArrayHandle<vtkm::Id3> cellFaceId;

@ -71,7 +71,7 @@ UnstructuredContainer::UnstructuredContainer(const vtkm::cont::CellSetExplicit<>
CellConn = CellConn =
Cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); Cellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
CellOffsets = CellOffsets =
Cellset.GetIndexOffsetArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); Cellset.GetOffsetsArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
Shapes = Cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); Shapes = Cellset.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
Intersector.SetData(Coords, Triangles); Intersector.SetData(Coords, Triangles);

@ -62,18 +62,15 @@ struct CellDeepCopy
template <typename InCellSetType, template <typename InCellSetType,
typename ShapeStorage, typename ShapeStorage,
typename NumIndicesStorage,
typename ConnectivityStorage, typename ConnectivityStorage,
typename OffsetsStorage> typename OffsetsStorage>
VTKM_CONT static void Run(const InCellSetType& inCellSet, VTKM_CONT static void Run(
vtkm::cont::CellSetExplicit<ShapeStorage, const InCellSetType& inCellSet,
NumIndicesStorage, vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& outCellSet)
ConnectivityStorage,
OffsetsStorage>& outCellSet)
{ {
VTKM_IS_DYNAMIC_OR_STATIC_CELL_SET(InCellSetType); VTKM_IS_DYNAMIC_OR_STATIC_CELL_SET(InCellSetType);
vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage> numIndices; vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
vtkm::worklet::DispatcherMapTopology<CountCellPoints> countDispatcher; vtkm::worklet::DispatcherMapTopology<CountCellPoints> countDispatcher;
countDispatcher.Invoke(inCellSet, numIndices); countDispatcher.Invoke(inCellSet, numIndices);
@ -83,17 +80,18 @@ struct CellDeepCopy
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage> offsets; vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage> offsets;
vtkm::Id connectivitySize; vtkm::Id connectivitySize;
vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connectivitySize); vtkm::cont::ConvertNumIndicesToOffsets(numIndices, offsets, connectivitySize);
connectivity.Allocate(connectivitySize); connectivity.Allocate(connectivitySize);
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
vtkm::worklet::DispatcherMapTopology<PassCellStructure> passDispatcher; vtkm::worklet::DispatcherMapTopology<PassCellStructure> passDispatcher;
passDispatcher.Invoke( passDispatcher.Invoke(
inCellSet, shapes, vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets)); inCellSet, shapes, vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim));
vtkm::cont:: vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage> newCellSet;
CellSetExplicit<ShapeStorage, NumIndicesStorage, ConnectivityStorage, OffsetsStorage> newCellSet.Fill(inCellSet.GetNumberOfPoints(), shapes, connectivity, offsets);
newCellSet;
newCellSet.Fill(inCellSet.GetNumberOfPoints(), shapes, numIndices, connectivity, offsets);
outCellSet = newCellSet; outCellSet = newCellSet;
} }

@ -692,7 +692,10 @@ public:
vtkm::cont::CellSetExplicit<> output; vtkm::cont::CellSetExplicit<> output;
vtkm::Id numberOfPoints = scalars.GetNumberOfValues() + vtkm::Id numberOfPoints = scalars.GetNumberOfValues() +
this->EdgePointsInterpolation.GetNumberOfValues() + total.NumberOfInCellPoints; this->EdgePointsInterpolation.GetNumberOfValues() + total.NumberOfInCellPoints;
output.Fill(numberOfPoints, shapes, numberOfIndices, connectivity);
vtkm::cont::ConvertNumIndicesToOffsets(numberOfIndices, offsets);
output.Fill(numberOfPoints, shapes, connectivity, offsets);
return output; return output;
} }

@ -27,6 +27,7 @@
#include <vtkm/cont/ArrayHandleIndex.h> #include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandlePermutation.h> #include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleTransform.h> #include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/CellSetExplicit.h> #include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/DataSet.h> #include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h> #include <vtkm/cont/Field.h>
@ -668,16 +669,11 @@ public:
/// ///
/// Faster Run() method for uniform and rectilinear grid types. /// Faster Run() method for uniform and rectilinear grid types.
/// Uses grid extents to find cells on the boundaries of the grid. /// Uses grid extents to find cells on the boundaries of the grid.
template <typename ShapeStorage, template <typename ShapeStorage, typename ConnectivityStorage, typename OffsetsStorage>
typename NumIndicesStorage, VTKM_CONT void Run(
typename ConnectivityStorage, const vtkm::cont::CellSetStructured<3>& inCellSet,
typename OffsetsStorage> const vtkm::cont::CoordinateSystem& coord,
VTKM_CONT void Run(const vtkm::cont::CellSetStructured<3>& inCellSet, vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& outCellSet)
const vtkm::cont::CoordinateSystem& coord,
vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
ConnectivityStorage,
OffsetsStorage>& outCellSet)
{ {
vtkm::Vec3f_64 MinPoint; vtkm::Vec3f_64 MinPoint;
vtkm::Vec3f_64 MaxPoint; vtkm::Vec3f_64 MaxPoint;
@ -732,7 +728,7 @@ public:
vtkm::Id connectivitySize = 4 * numberOfExternalFaces; vtkm::Id connectivitySize = 4 * numberOfExternalFaces;
vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage> faceConnectivity; vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage> faceConnectivity;
vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage> faceShapes; vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage> faceShapes;
vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage> facePointCount; vtkm::cont::ArrayHandle<vtkm::IdComponent> facePointCount;
// Must pre allocate because worklet invocation will not have enough // Must pre allocate because worklet invocation will not have enough
// information to. // information to.
faceConnectivity.Allocate(connectivitySize); faceConnectivity.Allocate(connectivitySize);
@ -748,23 +744,23 @@ public:
facePointCount, facePointCount,
vtkm::cont::make_ArrayHandleGroupVec<4>(faceConnectivity), vtkm::cont::make_ArrayHandleGroupVec<4>(faceConnectivity),
coordData); coordData);
outCellSet.Fill(inCellSet.GetNumberOfPoints(), faceShapes, facePointCount, faceConnectivity);
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(facePointCount);
outCellSet.Fill(inCellSet.GetNumberOfPoints(), faceShapes, faceConnectivity, offsets);
} }
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
/// \brief ExternalFaces: Extract Faces on outside of geometry /// \brief ExternalFaces: Extract Faces on outside of geometry
template <typename InCellSetType, template <typename InCellSetType,
typename ShapeStorage, typename ShapeStorage,
typename NumIndicesStorage,
typename ConnectivityStorage, typename ConnectivityStorage,
typename OffsetsStorage> typename OffsetsStorage>
VTKM_CONT void Run(const InCellSetType& inCellSet, VTKM_CONT void Run(
vtkm::cont::CellSetExplicit<ShapeStorage, const InCellSetType& inCellSet,
NumIndicesStorage, vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& outCellSet)
ConnectivityStorage,
OffsetsStorage>& outCellSet)
{ {
using PointCountArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage>; using PointCountArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent>;
using ShapeArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage>; using ShapeArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage>;
using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>; using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>;
using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage>; using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage>;
@ -802,7 +798,7 @@ public:
countPolyDataCellPointsDispatcher.Invoke(inCellSet, polyDataPointCount); countPolyDataCellPointsDispatcher.Invoke(inCellSet, polyDataPointCount);
vtkm::cont::ConvertNumComponentsToOffsets( vtkm::cont::ConvertNumIndicesToOffsets(
polyDataPointCount, polyDataOffsets, polyDataConnectivitySize); polyDataPointCount, polyDataOffsets, polyDataConnectivitySize);
vtkm::worklet::DispatcherMapTopology<PassPolyDataCells> passPolyDataCellsDispatcher( vtkm::worklet::DispatcherMapTopology<PassPolyDataCells> passPolyDataCellsDispatcher(
@ -810,10 +806,13 @@ public:
polyDataConnectivity.Allocate(polyDataConnectivitySize); polyDataConnectivity.Allocate(polyDataConnectivitySize);
auto pdOffsetsTrim = vtkm::cont::make_ArrayHandleView(
polyDataOffsets, 0, polyDataOffsets.GetNumberOfValues() - 1);
passPolyDataCellsDispatcher.Invoke( passPolyDataCellsDispatcher.Invoke(
inCellSet, inCellSet,
polyDataShapes, polyDataShapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, polyDataOffsets), vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, pdOffsetsTrim),
polyDataCellIdMap); polyDataCellIdMap);
} }
} }
@ -830,11 +829,8 @@ public:
else else
{ {
// Pass only input poly data to output // Pass only input poly data to output
outCellSet.Fill(inCellSet.GetNumberOfPoints(), outCellSet.Fill(
polyDataShapes, inCellSet.GetNumberOfPoints(), polyDataShapes, polyDataConnectivity, polyDataOffsets);
polyDataPointCount,
polyDataConnectivity,
polyDataOffsets);
this->CellIdMap = polyDataCellIdMap; this->CellIdMap = polyDataCellIdMap;
return; return;
} }
@ -866,7 +862,7 @@ public:
OffsetsArrayType faceOffsets; OffsetsArrayType faceOffsets;
vtkm::Id connectivitySize; vtkm::Id connectivitySize;
vtkm::cont::ConvertNumComponentsToOffsets(facePointCount, faceOffsets, connectivitySize); vtkm::cont::ConvertNumIndicesToOffsets(facePointCount, faceOffsets, connectivitySize);
ConnectivityArrayType faceConnectivity; ConnectivityArrayType faceConnectivity;
// Must pre allocate because worklet invocation will not have enough // Must pre allocate because worklet invocation will not have enough
@ -878,19 +874,22 @@ public:
vtkm::cont::ArrayHandle<vtkm::Id> faceToCellIdMap; vtkm::cont::ArrayHandle<vtkm::Id> faceToCellIdMap;
// Create a view that doesn't have the last offset:
auto faceOffsetsTrim =
vtkm::cont::make_ArrayHandleView(faceOffsets, 0, faceOffsets.GetNumberOfValues() - 1);
buildConnectivityDispatcher.Invoke( buildConnectivityDispatcher.Invoke(
faceKeys, faceKeys,
inCellSet, inCellSet,
originCells, originCells,
originFaces, originFaces,
faceShapes, faceShapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsets), vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsetsTrim),
faceToCellIdMap); faceToCellIdMap);
if (!polyDataConnectivitySize) if (!polyDataConnectivitySize)
{ {
outCellSet.Fill( outCellSet.Fill(inCellSet.GetNumberOfPoints(), faceShapes, faceConnectivity, faceOffsets);
inCellSet.GetNumberOfPoints(), faceShapes, facePointCount, faceConnectivity, faceOffsets);
this->CellIdMap = faceToCellIdMap; this->CellIdMap = faceToCellIdMap;
} }
else else
@ -912,13 +911,11 @@ public:
vtkm::cont::ArrayCopy(connectivityArray, joinedConnectivity); vtkm::cont::ArrayCopy(connectivityArray, joinedConnectivity);
// Adjust poly data offsets array with face connectivity size before join // Adjust poly data offsets array with face connectivity size before join
using TransformBiasArrayType = auto adjustedPolyDataOffsets = vtkm::cont::make_ArrayHandleTransform(
vtkm::cont::ArrayHandleTransform<OffsetsArrayType, BiasFunctor<vtkm::Id>>; polyDataOffsets, BiasFunctor<vtkm::Id>(faceConnectivity.GetNumberOfValues()));
TransformBiasArrayType adjustedPolyDataOffsets =
vtkm::cont::make_ArrayHandleTransform<OffsetsArrayType>( auto offsetsArray =
polyDataOffsets, BiasFunctor<vtkm::Id>(faceConnectivity.GetNumberOfValues())); vtkm::cont::make_ArrayHandleConcatenate(faceOffsetsTrim, adjustedPolyDataOffsets);
vtkm::cont::ArrayHandleConcatenate<OffsetsArrayType, TransformBiasArrayType> offsetsArray(
faceOffsets, adjustedPolyDataOffsets);
OffsetsArrayType joinedOffsets; OffsetsArrayType joinedOffsets;
vtkm::cont::ArrayCopy(offsetsArray, joinedOffsets); vtkm::cont::ArrayCopy(offsetsArray, joinedOffsets);
@ -928,11 +925,8 @@ public:
vtkm::cont::ArrayHandle<vtkm::Id> joinedCellIdMap; vtkm::cont::ArrayHandle<vtkm::Id> joinedCellIdMap;
vtkm::cont::ArrayCopy(cellIdMapArray, joinedCellIdMap); vtkm::cont::ArrayCopy(cellIdMapArray, joinedCellIdMap);
outCellSet.Fill(inCellSet.GetNumberOfPoints(), outCellSet.Fill(
joinedShapesArray, inCellSet.GetNumberOfPoints(), joinedShapesArray, joinedConnectivity, joinedOffsets);
joinedPointCountArray,
joinedConnectivity,
joinedOffsets);
this->CellIdMap = joinedCellIdMap; this->CellIdMap = joinedCellIdMap;
} }
} }

@ -443,18 +443,11 @@ public:
points = vtkm::cont::ArrayHandleVirtualCoordinates(concretePoints); points = vtkm::cont::ArrayHandleVirtualCoordinates(concretePoints);
} }
template <typename ShapeStorage, template <typename ShapeStorage, typename ConnectivityStorage, typename OffsetsStorage>
typename NumIndicesStorage, VTKM_CONT
typename ConnectivityStorage, vtkm::cont::CellSetExplicit<ShapeStorage, VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, OffsetsStorage>
typename OffsetsStorage> MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>&
VTKM_CONT vtkm::cont::CellSetExplicit<ShapeStorage, inCellSet) const
NumIndicesStorage,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
OffsetsStorage>
MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
ConnectivityStorage,
OffsetsStorage>& inCellSet) const
{ {
return vtkm::worklet::RemoveUnusedPoints::MapCellSet( return vtkm::worklet::RemoveUnusedPoints::MapCellSet(
inCellSet, this->PointInputToOutputMap, this->MergeKeys.GetInputRange()); inCellSet, this->PointInputToOutputMap, this->MergeKeys.GetInputRange());

@ -71,14 +71,9 @@ public:
VTKM_CONT VTKM_CONT
RemoveUnusedPoints() {} RemoveUnusedPoints() {}
template <typename ShapeStorage, template <typename ShapeStorage, typename ConnectivityStorage, typename OffsetsStorage>
typename NumIndicesStorage, VTKM_CONT RemoveUnusedPoints(
typename ConnectivityStorage, const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& inCellSet)
typename OffsetsStorage>
VTKM_CONT RemoveUnusedPoints(const vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
ConnectivityStorage,
OffsetsStorage>& inCellSet)
{ {
this->FindPointsStart(); this->FindPointsStart();
this->FindPoints(inCellSet); this->FindPoints(inCellSet);
@ -93,14 +88,9 @@ public:
/// points are those that are not found in any cell sets passed to this /// points are those that are not found in any cell sets passed to this
/// method. /// method.
/// ///
template <typename ShapeStorage, template <typename ShapeStorage, typename ConnectivityStorage, typename OffsetsStorage>
typename NumIndicesStorage, VTKM_CONT void FindPoints(
typename ConnectivityStorage, const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& inCellSet)
typename OffsetsStorage>
VTKM_CONT void FindPoints(const vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
ConnectivityStorage,
OffsetsStorage>& inCellSet)
{ {
if (this->MaskArray.GetNumberOfValues() < 1) if (this->MaskArray.GetNumberOfValues() < 1)
{ {
@ -133,18 +123,11 @@ public:
/// returns a new cell set with cell points transformed to use the indices of /// returns a new cell set with cell points transformed to use the indices of
/// the new reduced point arrays. /// the new reduced point arrays.
/// ///
template <typename ShapeStorage, template <typename ShapeStorage, typename ConnectivityStorage, typename OffsetsStorage>
typename NumIndicesStorage, VTKM_CONT
typename ConnectivityStorage, vtkm::cont::CellSetExplicit<ShapeStorage, VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, OffsetsStorage>
typename OffsetsStorage> MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>&
VTKM_CONT vtkm::cont::CellSetExplicit<ShapeStorage, inCellSet) const
NumIndicesStorage,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
OffsetsStorage>
MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
ConnectivityStorage,
OffsetsStorage>& inCellSet) const
{ {
VTKM_ASSERT(this->PointScatter); VTKM_ASSERT(this->PointScatter);
@ -166,20 +149,16 @@ public:
/// of \c MapCellSet. /// of \c MapCellSet.
/// ///
template <typename ShapeStorage, template <typename ShapeStorage,
typename NumIndicesStorage,
typename ConnectivityStorage, typename ConnectivityStorage,
typename OffsetsStorage, typename OffsetsStorage,
typename MapStorage> typename MapStorage>
VTKM_CONT static vtkm::cont::CellSetExplicit<ShapeStorage, VTKM_CONT static vtkm::cont::CellSetExplicit<ShapeStorage,
NumIndicesStorage,
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG, VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
OffsetsStorage> OffsetsStorage>
MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage, MapCellSet(
NumIndicesStorage, const vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage>& inCellSet,
ConnectivityStorage, const vtkm::cont::ArrayHandle<vtkm::Id, MapStorage>& inputToOutputPointMap,
OffsetsStorage>& inCellSet, vtkm::Id numberOfPoints)
const vtkm::cont::ArrayHandle<vtkm::Id, MapStorage>& inputToOutputPointMap,
vtkm::Id numberOfPoints)
{ {
using VisitTopology = vtkm::TopologyElementTagCell; using VisitTopology = vtkm::TopologyElementTagCell;
using IncidentTopology = vtkm::TopologyElementTagPoint; using IncidentTopology = vtkm::TopologyElementTagPoint;
@ -193,14 +172,11 @@ public:
inputToOutputPointMap, inputToOutputPointMap,
newConnectivityArray); newConnectivityArray);
vtkm::cont:: vtkm::cont::CellSetExplicit<ShapeStorage, NewConnectivityStorage, OffsetsStorage> outCellSet;
CellSetExplicit<ShapeStorage, NumIndicesStorage, NewConnectivityStorage, OffsetsStorage>
outCellSet;
outCellSet.Fill(numberOfPoints, outCellSet.Fill(numberOfPoints,
inCellSet.GetShapesArray(VisitTopology(), IncidentTopology()), inCellSet.GetShapesArray(VisitTopology(), IncidentTopology()),
inCellSet.GetNumIndicesArray(VisitTopology(), IncidentTopology()),
newConnectivityArray, newConnectivityArray,
inCellSet.GetIndexOffsetArray(VisitTopology(), IncidentTopology())); inCellSet.GetOffsetsArray(VisitTopology(), IncidentTopology()));
return outCellSet; return outCellSet;
} }

@ -482,8 +482,8 @@ public:
auto connectivityArrayHandle = newCellset.GetConnectivityArray(vtkm::TopologyElementTagCell(), auto connectivityArrayHandle = newCellset.GetConnectivityArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagPoint());
auto connectivityArrayHandleP = connectivityArrayHandle.GetPortalControl(); auto connectivityArrayHandleP = connectivityArrayHandle.GetPortalControl();
auto offsetArrayHandle = newCellset.GetIndexOffsetArray(vtkm::TopologyElementTagCell(), auto offsetArrayHandle =
vtkm::TopologyElementTagPoint()); newCellset.GetOffsetsArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto offsetArrayHandleP = offsetArrayHandle.GetPortalControl(); auto offsetArrayHandleP = offsetArrayHandle.GetPortalControl();
for (vtkm::Id i = 0; i < cellTopologyUpdateTuples.GetNumberOfValues(); i++) for (vtkm::Id i = 0; i < cellTopologyUpdateTuples.GetNumberOfValues(); i++)
{ {

@ -379,8 +379,8 @@ public:
makeStreamLines, fieldArray, seedIdArray, seedPosArray, numIndices, validPoint, streamArray); makeStreamLines, fieldArray, seedIdArray, seedPosArray, numIndices, validPoint, streamArray);
// Size of connectivity based on size of returned streamlines // Size of connectivity based on size of returned streamlines
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndicesOut; vtkm::Id connectivityLen;
vtkm::IdComponent connectivityLen = Algorithm::ScanExclusive(numIndices, numIndicesOut); auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices, connectivityLen);
// Connectivity is sequential // Connectivity is sequential
vtkm::cont::ArrayHandleCounting<vtkm::Id> connCount(0, 1, connectivityLen); vtkm::cont::ArrayHandleCounting<vtkm::Id> connCount(0, 1, connectivityLen);
@ -395,7 +395,7 @@ public:
vtkm::cont::DataSet OutDataSet; vtkm::cont::DataSet OutDataSet;
vtkm::cont::CellSetExplicit<> outCellSet; vtkm::cont::CellSetExplicit<> outCellSet;
outCellSet.Fill(coordinates.GetNumberOfValues(), cellTypes, numIndices, connectivity); outCellSet.Fill(coordinates.GetNumberOfValues(), cellTypes, connectivity, offsets);
OutDataSet.SetCellSet(outCellSet); OutDataSet.SetCellSet(outCellSet);
OutDataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates)); OutDataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", coordinates));

@ -28,6 +28,7 @@
#include <vtkm/cont/ArrayHandleCounting.h> #include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleGroupVec.h> #include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/ArrayHandleGroupVecVariable.h> #include <vtkm/cont/ArrayHandleGroupVecVariable.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/ArrayRangeCompute.h> #include <vtkm/cont/ArrayRangeCompute.h>
#include <vtkm/cont/CellSetExplicit.h> #include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/CellSetSingleType.h> #include <vtkm/cont/CellSetSingleType.h>
@ -237,26 +238,28 @@ public:
{ // Multiple cell types: { // Multiple cell types:
vtkm::cont::ArrayHandle<vtkm::Id> offsets; vtkm::cont::ArrayHandle<vtkm::Id> offsets;
vtkm::Id connSize; vtkm::Id connSize;
vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connSize); vtkm::cont::ConvertNumIndicesToOffsets(numIndices, offsets, connSize);
numIndices.ReleaseResourcesExecution(); numIndices.ReleaseResourcesExecution();
vtkm::cont::ArrayHandle<vtkm::Id> conn; vtkm::cont::ArrayHandle<vtkm::Id> conn;
conn.Allocate(connSize); conn.Allocate(connSize);
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets); // Trim the last value off for the group vec array:
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
WorkletWindToCellNormalsGeneric worklet; WorkletWindToCellNormalsGeneric worklet;
invoker(worklet, cellSet, coords, cellNormals, connGroupVec); invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
vtkm::cont::CellSetExplicit<> outCells; vtkm::cont::CellSetExplicit<> outCells;
outCells.Fill(cellSet.GetNumberOfPoints(), cellShapes, numIndices, conn, offsets); outCells.Fill(cellSet.GetNumberOfPoints(), cellShapes, conn, offsets);
this->Result = outCells; this->Result = outCells;
} }
} }
// Specialization for CellSetExplicit // Specialization for CellSetExplicit
template <typename S, template <typename S,
typename N,
typename C, typename C,
typename O, typename O,
typename PointComponentType, typename PointComponentType,
@ -264,7 +267,7 @@ public:
typename CellNormalComponentType, typename CellNormalComponentType,
typename CellNormalStorageType> typename CellNormalStorageType>
VTKM_CONT void operator()( VTKM_CONT void operator()(
const vtkm::cont::CellSetExplicit<S, N, C, O>& cellSet, const vtkm::cont::CellSetExplicit<S, C, O>& cellSet,
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& coords, const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& coords,
const vtkm::cont::ArrayHandle<vtkm::Vec<CellNormalComponentType, 3>, CellNormalStorageType>& const vtkm::cont::ArrayHandle<vtkm::Vec<CellNormalComponentType, 3>, CellNormalStorageType>&
cellNormals, cellNormals,
@ -286,19 +289,19 @@ public:
vtkm::cont::Algorithm::Copy(connIn, conn); vtkm::cont::Algorithm::Copy(connIn, conn);
} }
const auto& offsets = cellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell{}, const auto& offsets =
vtkm::TopologyElementTagPoint{}); cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets); auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
WindToCellNormals dispatcher; WindToCellNormals dispatcher;
dispatcher.Invoke(cellNormals, cells, coords); dispatcher.Invoke(cellNormals, cells, coords);
const auto& shapes = const auto& shapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}); cellSet.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
const auto& numIndices = vtkm::cont::CellSetExplicit<S, vtkm::cont::StorageTagBasic, O> newCells;
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}); newCells.Fill(cellSet.GetNumberOfPoints(), shapes, conn, offsets);
vtkm::cont::CellSetExplicit<S, N, vtkm::cont::StorageTagBasic, O> newCells;
newCells.Fill(cellSet.GetNumberOfPoints(), shapes, numIndices, conn, offsets);
this->Result = newCells; this->Result = newCells;
} }
@ -332,9 +335,11 @@ public:
vtkm::cont::Algorithm::Copy(connIn, conn); vtkm::cont::Algorithm::Copy(connIn, conn);
} }
const auto& offsets = cellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell{}, const auto& offsets =
vtkm::TopologyElementTagPoint{}); cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets); auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
WindToCellNormals dispatcher; WindToCellNormals dispatcher;
dispatcher.Invoke(cellNormals, cells, coords); dispatcher.Invoke(cellNormals, cells, coords);

@ -143,12 +143,10 @@ template <typename DeviceAdapter>
class ExplicitCellInterpolationHelper : public vtkm::exec::CellInterpolationHelper class ExplicitCellInterpolationHelper : public vtkm::exec::CellInterpolationHelper
{ {
using ShapeType = vtkm::cont::ArrayHandle<vtkm::UInt8>; using ShapeType = vtkm::cont::ArrayHandle<vtkm::UInt8>;
using NumIdxType = vtkm::cont::ArrayHandle<vtkm::IdComponent>;
using OffsetType = vtkm::cont::ArrayHandle<vtkm::Id>; using OffsetType = vtkm::cont::ArrayHandle<vtkm::Id>;
using ConnType = vtkm::cont::ArrayHandle<vtkm::Id>; using ConnType = vtkm::cont::ArrayHandle<vtkm::Id>;
using ShapePortalType = typename ShapeType::template ExecutionTypes<DeviceAdapter>::PortalConst; using ShapePortalType = typename ShapeType::template ExecutionTypes<DeviceAdapter>::PortalConst;
using NumIdxPortalType = typename NumIdxType::template ExecutionTypes<DeviceAdapter>::PortalConst;
using OffsetPortalType = typename OffsetType::template ExecutionTypes<DeviceAdapter>::PortalConst; using OffsetPortalType = typename OffsetType::template ExecutionTypes<DeviceAdapter>::PortalConst;
using ConnPortalType = typename ConnType::template ExecutionTypes<DeviceAdapter>::PortalConst; using ConnPortalType = typename ConnType::template ExecutionTypes<DeviceAdapter>::PortalConst;
@ -157,11 +155,9 @@ public:
VTKM_CONT VTKM_CONT
ExplicitCellInterpolationHelper(const ShapeType& shape, ExplicitCellInterpolationHelper(const ShapeType& shape,
const NumIdxType& numIdx,
const OffsetType& offset, const OffsetType& offset,
const ConnType& connectivity) const ConnType& connectivity)
: Shape(shape.PrepareForInput(DeviceAdapter())) : Shape(shape.PrepareForInput(DeviceAdapter()))
, NumIdx(numIdx.PrepareForInput(DeviceAdapter()))
, Offset(offset.PrepareForInput(DeviceAdapter())) , Offset(offset.PrepareForInput(DeviceAdapter()))
, Connectivity(connectivity.PrepareForInput(DeviceAdapter())) , Connectivity(connectivity.PrepareForInput(DeviceAdapter()))
{ {
@ -173,17 +169,16 @@ public:
vtkm::IdComponent& numVerts, vtkm::IdComponent& numVerts,
vtkm::VecVariable<vtkm::Id, 8>& indices) const override vtkm::VecVariable<vtkm::Id, 8>& indices) const override
{ {
cellShape = Shape.Get(cellId); cellShape = this->Shape.Get(cellId);
numVerts = NumIdx.Get(cellId); const vtkm::Id offset = this->Offset.Get(cellId);
vtkm::Id offset = Offset.Get(cellId); numVerts = static_cast<vtkm::IdComponent>(this->Offset.Get(cellId + 1) - offset);
for (vtkm::IdComponent i = 0; i < numVerts; i++) for (vtkm::IdComponent i = 0; i < numVerts; i++)
indices.Append(Connectivity.Get(offset + i)); indices.Append(this->Connectivity.Get(offset + i));
} }
private: private:
ShapePortalType Shape; ShapePortalType Shape;
NumIdxPortalType NumIdx;
OffsetPortalType Offset; OffsetPortalType Offset;
ConnPortalType Connectivity; ConnPortalType Connectivity;
}; };
@ -341,10 +336,8 @@ public:
vtkm::cont::CellSetExplicit<> CellSet = cellSet.Cast<vtkm::cont::CellSetExplicit<>>(); vtkm::cont::CellSetExplicit<> CellSet = cellSet.Cast<vtkm::cont::CellSetExplicit<>>();
Shape = Shape =
CellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); CellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
NumIdx = Offset =
CellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); CellSet.GetOffsetsArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
Offset = CellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint());
Connectivity = CellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), Connectivity = CellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint()); vtkm::TopologyElementTagPoint());
} }
@ -360,10 +353,8 @@ public:
HandleType& execInterpolator) const HandleType& execInterpolator) const
{ {
using ExecutionType = vtkm::exec::ExplicitCellInterpolationHelper<DeviceAdapter>; using ExecutionType = vtkm::exec::ExplicitCellInterpolationHelper<DeviceAdapter>;
ExecutionType* execObject = new ExecutionType(contInterpolator.Shape, ExecutionType* execObject = new ExecutionType(
contInterpolator.NumIdx, contInterpolator.Shape, contInterpolator.Offset, contInterpolator.Connectivity);
contInterpolator.Offset,
contInterpolator.Connectivity);
execInterpolator.Reset(execObject); execInterpolator.Reset(execObject);
return true; return true;
} }
@ -384,7 +375,6 @@ public:
private: private:
vtkm::cont::ArrayHandle<vtkm::UInt8> Shape; vtkm::cont::ArrayHandle<vtkm::UInt8> Shape;
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumIdx;
vtkm::cont::ArrayHandle<vtkm::Id> Offset; vtkm::cont::ArrayHandle<vtkm::Id> Offset;
vtkm::cont::ArrayHandle<vtkm::Id> Connectivity; vtkm::cont::ArrayHandle<vtkm::Id> Connectivity;
mutable HandleType ExecHandle; mutable HandleType ExecHandle;

@ -238,11 +238,10 @@ private:
numSeeds); numSeeds);
vtkm::cont::ArrayCopy(polyLineShape, cellTypes); vtkm::cont::ArrayCopy(polyLineShape, cellTypes);
vtkm::cont::ArrayHandle<vtkm::IdComponent> cellCounts; auto numIndices = vtkm::cont::make_ArrayHandleCast(stepsTakenNow, vtkm::IdComponent());
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleCast(stepsTakenNow, vtkm::IdComponent()), auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
cellCounts);
polyLines.Fill(positions.GetNumberOfValues(), cellTypes, cellCounts, connectivity); polyLines.Fill(positions.GetNumberOfValues(), cellTypes, connectivity, offsets);
} }
IntegratorType integrator; IntegratorType integrator;

@ -72,9 +72,9 @@ void CheckOutput(const vtkm::cont::CellSetExplicit<>& copiedCells)
"Bad number of points in cell"); "Bad number of points in cell");
// Only checking 3 points. All cells should have at least 3 // Only checking 3 points. All cells should have at least 3
vtkm::Id3 cellPoints; vtkm::Id3 cellPoints{ 0 };
copiedCells.GetIndices(cellIndex, cellPoints); copiedCells.GetIndices(cellIndex, cellPoints);
vtkm::Id3 oCellPoints; vtkm::Id3 oCellPoints{ 0 };
originalCells.GetIndices(oCellIndex, oCellPoints); originalCells.GetIndices(oCellIndex, oCellPoints);
VTKM_TEST_ASSERT(cellPoints == oCellPoints, "Point indices not copied correctly"); VTKM_TEST_ASSERT(cellPoints == oCellPoints, "Point indices not copied correctly");
} }

@ -57,8 +57,10 @@ void Validate(vtkm::cont::DataSet dataSet)
const auto conn = const auto conn =
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}); cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
const auto offsets = const auto offsets =
cellSet.GetIndexOffsetArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}); cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
const auto cellArray = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets); const auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
const auto cellArray = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
const auto cellNormalsVar = dataSet.GetCellField("normals").GetData(); const auto cellNormalsVar = dataSet.GetCellField("normals").GetData();
const auto cellNormalsArray = cellNormalsVar.Cast<vtkm::cont::ArrayHandle<MyNormalT>>(); const auto cellNormalsArray = cellNormalsVar.Cast<vtkm::cont::ArrayHandle<MyNormalT>>();