Reintroduce explicit connectivity class for cont environment

(Re-) Add a helper structure that holds the connectivity information for
a particular topology connection (e.g. from points to cells) to make it
easier to manage connections in multiple different directions in
CellSetExplicit.

Unlike the previous version of connectivity, this structure is
considered "internal" and not exposed through the API so that
CellSetExplicit can better manage the data. Also, many of the helper
methods remain in CellSetExplicit since they were specific for point-to-

Also, CellSetExplicit has a mechanism to take an arbitrary pair of
TopologyElementTags and get the appropriate connectivity. This should
simplify adding connections in the future.
This commit is contained in:
Kenneth Moreland 2015-08-11 12:42:34 -06:00
parent 63b45ad1e5
commit 1862970a0b
5 changed files with 266 additions and 98 deletions

@ -22,20 +22,37 @@
#include <vtkm/TopologyElementTag.h>
#include <vtkm/cont/CellSet.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/exec/ConnectivityExplicit.h>
namespace vtkm {
namespace cont {
namespace detail {
template<typename CellSetType, typename FromTopology, typename ToTopology>
struct CellSetExplicitConnectivityChooser
{
typedef vtkm::cont::internal::ConnectivityExplicitInternals<>
ConnectivityType;
};
} // namespace detail
template<typename ShapeStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_STORAGE_TAG >
class CellSetExplicit : public CellSet
{
typedef vtkm::cont::ArrayHandle<vtkm::Id, ShapeStorageTag> ShapeArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id, NumIndicesStorageTag> NumIndicesArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag> ConnectivityArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id> MapCellToConnectivityIndexArrayType;
template<typename FromTopology, typename ToTopology>
struct ConnectivityChooser
{
typedef typename detail::CellSetExplicitConnectivityChooser<
CellSetExplicit<
ShapeStorageTag,NumIndicesStorageTag,ConnectivityStorageTag>,
FromTopology,
ToTopology>::ConnectivityType ConnectivityType;
};
public:
typedef vtkm::Id SchedulingRangeType;
@ -44,22 +61,22 @@ public:
CellSetExplicit(const std::string &name = std::string(),
vtkm::IdComponent dimensionality = 3)
: CellSet(name, dimensionality),
ConnectivityLength(0),
NumberOfCells(0)
ConnectivityLength(-1),
NumberOfCells(-1)
{
}
VTKM_CONT_EXPORT
CellSetExplicit(int dimensionality)
: CellSet(std::string(), dimensionality),
ConnectivityLength(0),
NumberOfCells(0)
ConnectivityLength(-1),
NumberOfCells(-1)
{
}
virtual vtkm::Id GetNumberOfCells() const
{
return this->Shapes.GetNumberOfValues();
return this->PointToCell.GetNumberOfElements();
}
VTKM_CONT_EXPORT
@ -71,13 +88,13 @@ public:
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfPointsInCell(vtkm::Id cellIndex) const
{
return this->NumIndices.GetPortalConstControl().Get(cellIndex);
return this->PointToCell.NumIndices.GetPortalConstControl().Get(cellIndex);
}
VTKM_CONT_EXPORT
vtkm::Id GetCellShape(vtkm::Id cellIndex) const
{
return this->Shapes.GetPortalConstControl().Get(cellIndex);
return this->PointToCell.Shapes.GetPortalConstControl().Get(cellIndex);
}
template <vtkm::IdComponent ItemTupleLength>
@ -85,9 +102,10 @@ public:
void GetIndices(vtkm::Id index,
vtkm::Vec<vtkm::Id,ItemTupleLength> &ids) const
{
this->PointToCell.BuildIndexOffsets(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
vtkm::Id numIndices = this->GetNumberOfIndices(index);
vtkm::Id start =
this->MapCellToConnectivityIndex.GetPortalConstControl().Get(index);
this->PointToCell.IndexOffset.GetPortalConstControl().Get(index);
for (vtkm::IdComponent i=0; i<numIndices && i<ItemTupleLength; i++)
ids[i] = this->Connectivity.GetPortalConstControl().Get(start+i);
}
@ -96,10 +114,10 @@ public:
VTKM_CONT_EXPORT
void PrepareToAddCells(vtkm::Id numShapes, vtkm::Id connectivityMaxLen)
{
this->Shapes.Allocate(numShapes);
this->NumIndices.Allocate(numShapes);
this->Connectivity.Allocate(connectivityMaxLen);
this->MapCellToConnectivityIndex.Allocate(numShapes);
this->PointToCell.Shapes.Allocate(numShapes);
this->PointToCell.NumIndices.Allocate(numShapes);
this->PointToCell.Connectivity.Allocate(connectivityMaxLen);
this->PointToCell.IndexOffsets.Allocate(numShapes);
this->NumberOfCells = 0;
this->ConnectivityLength = 0;
}
@ -110,14 +128,14 @@ public:
int numVertices,
const vtkm::Vec<vtkm::Id,ItemTupleLength> &ids)
{
this->Shapes.GetPortalControl().Set(this->NumberOfCells, cellType);
this->NumIndices.GetPortalControl().Set(this->NumberOfCells, numVertices);
this->PointToCell.Shapes.GetPortalControl().Set(this->NumberOfCells, cellType);
this->PointToCell.NumIndices.GetPortalControl().Set(this->NumberOfCells, numVertices);
for (vtkm::IdComponent i=0; i < numVertices; ++i)
{
this->Connectivity.GetPortalControl().Set(
this->PointToCell.Connectivity.GetPortalControl().Set(
this->ConnectivityLength+i,ids[i]);
}
this->MapCellToConnectivityIndex.GetPortalControl().Set(
this->PointToCell.IndexOffsets.GetPortalControl().Set(
this->NumberOfCells, this->ConnectivityLength);
this->NumberOfCells++;
this->ConnectivityLength += numVertices;
@ -126,7 +144,9 @@ public:
VTKM_CONT_EXPORT
void CompleteAddingCells()
{
Connectivity.Shrink(ConnectivityLength);
this->PointToCell.Connectivity.Shrink(ConnectivityLength);
this->PointToCell.ElementsValid = true;
this->NumberOfCells = this->ConnectivityLength = -1;
}
/// Second method to add cells -- all at once.
@ -137,29 +157,23 @@ public:
const std::vector<vtkm::Id> &connectivity)
{
this->Shapes.Allocate( static_cast<vtkm::Id>(cellTypes.size()) );
this->PointToCell.Shapes.Allocate( static_cast<vtkm::Id>(cellTypes.size()) );
std::copy(cellTypes.begin(), cellTypes.end(),
vtkm::cont::ArrayPortalToIteratorBegin(this->Shapes.GetPortalControl()));
vtkm::cont::ArrayPortalToIteratorBegin(
this->PointToCell.Shapes.GetPortalControl()));
this->NumIndices.Allocate( static_cast<vtkm::Id>(numIndices.size()) );
this->PointToCell.NumIndices.Allocate( static_cast<vtkm::Id>(numIndices.size()) );
std::copy(numIndices.begin(), numIndices.end(),
vtkm::cont::ArrayPortalToIteratorBegin(this->NumIndices.GetPortalControl()));
vtkm::cont::ArrayPortalToIteratorBegin(
this->PointToCell.NumIndices.GetPortalControl()));
this->Connectivity.Allocate( static_cast<vtkm::Id>(connectivity.size()) );
this->PointToCell.Connectivity.Allocate( static_cast<vtkm::Id>(connectivity.size()) );
std::copy(connectivity.begin(), connectivity.end(),
vtkm::cont::ArrayPortalToIteratorBegin(this->Connectivity.GetPortalControl()));
vtkm::cont::ArrayPortalToIteratorBegin(
this->PointToCell.Connectivity.GetPortalControl()));
this->NumberOfCells = this->Shapes.GetNumberOfValues();
this->ConnectivityLength = this->Connectivity.GetNumberOfValues();
// allocate and build reverse index
this->MapCellToConnectivityIndex.Allocate(this->NumberOfCells);
vtkm::Id counter = 0;
for (vtkm::Id i=0; i<this->NumberOfCells; ++i)
{
this->MapCellToConnectivityIndex.GetPortalControl().Set(i, counter);
counter += this->NumIndices.GetPortalConstControl().Get(i);
}
this->PointToCell.ElementsValid = true;
this->PointToCell.IndexOffsetsValid = false;
}
/// Second method to add cells -- all at once.
@ -169,21 +183,12 @@ public:
const vtkm::cont::ArrayHandle<vtkm::Id, NumIndicesStorageTag> &numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag> &connectivity)
{
this->Shapes = cellTypes;
this->NumIndices = numIndices;
this->Connectivity = connectivity;
this->PointToCell.Shapes = cellTypes;
this->PointToCell.NumIndices = numIndices;
this->PointToCell.Connectivity = connectivity;
this->NumberOfCells = this->Shapes.GetNumberOfValues();
this->ConnectivityLength = this->Connectivity.GetNumberOfValues();
// allocate and build reverse index
this->MapCellToConnectivityIndex.Allocate(this->NumberOfCells);
vtkm::Id counter = 0;
for (vtkm::Id i=0; i<this->NumberOfCells; ++i)
{
this->MapCellToConnectivityIndex.GetPortalControl().Set(i, counter);
counter += this->NumIndices.GetPortalConstControl().Get(i);
}
this->PointToCell.ElementsValid = true;
this->PointToCell.IndexOffsetsValid = false;
}
template <typename DeviceAdapter, typename FromTopology, typename ToTopology>
@ -193,76 +198,129 @@ public:
VTKM_IS_TOPOLOGY_ELEMENT_TAG(FromTopology);
VTKM_IS_TOPOLOGY_ELEMENT_TAG(ToTopology);
typedef typename ShapeArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst ShapePortalType;
typedef typename NumIndicesArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst IndicePortalType;
typedef typename ConnectivityArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst ConnectivityPortalType;
typedef typename MapCellToConnectivityIndexArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst MapConnectivityPortalType;
typedef typename
ConnectivityChooser<FromTopology,ToTopology>::ConnectivityType
ContObjectType;
typedef typename ContObjectType::ShapeArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst ShapePortalType;
typedef typename ContObjectType::NumIndicesArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst IndicePortalType;
typedef typename ContObjectType::ConnectivityArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst ConnectivityPortalType;
typedef typename ContObjectType::IndexOffsetArrayType::template ExecutionTypes<DeviceAdapter>::PortalConst IndexOffsetPortalType;
typedef vtkm::exec::ConnectivityExplicit<ShapePortalType,
IndicePortalType,
ConnectivityPortalType,
MapConnectivityPortalType
IndexOffsetPortalType
> ExecObjectType;
};
template<typename Device>
typename ExecutionTypes<Device,vtkm::TopologyElementTagPoint,vtkm::TopologyElementTagCell>::ExecObjectType
PrepareForInput(Device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell) const
template<typename Device, typename FromTopology, typename ToTopology>
typename ExecutionTypes<Device,FromTopology,ToTopology>::ExecObjectType
PrepareForInput(Device, FromTopology, ToTopology) const
{
typedef typename ExecutionTypes<Device,vtkm::TopologyElementTagPoint,vtkm::TopologyElementTagCell>::ExecObjectType ExecObjType;
return ExecObjType(this->Shapes.PrepareForInput(Device()),
this->NumIndices.PrepareForInput(Device()),
this->Connectivity.PrepareForInput(Device()),
this->MapCellToConnectivityIndex.PrepareForInput(Device()));
const typename
ConnectivityChooser<FromTopology,ToTopology>::ConnectivityType
&connectivity = this->GetConnectivity(FromTopology(), ToTopology());
VTKM_ASSERT_CONT(connectivity.ElementsValid);
connectivity.BuildIndexOffsets(Device());
typedef typename
ExecutionTypes<Device,FromTopology,ToTopology>::ExecObjectType
ExecObjType;
return ExecObjType(connectivity.Shapes.PrepareForInput(Device()),
connectivity.NumIndices.PrepareForInput(Device()),
connectivity.Connectivity.PrepareForInput(Device()),
connectivity.IndexOffsets.PrepareForInput(Device()));
}
virtual void PrintSummary(std::ostream &out) const
{
out << " ExplicitCellSet: " << this->Name
<< " dim= " << this->Dimensionality << std::endl;
out <<" Shapes: ";
vtkm::cont::printSummary_ArrayHandle(this->Shapes, out);
out << std::endl;
out << " NumIndices: ";
vtkm::cont::printSummary_ArrayHandle(this->NumIndices, out);
out << std::endl;
out << " Connectivity: ";
vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out);
out << std::endl;
out << " MapCellToConnectivityIndex: ";
vtkm::cont::printSummary_ArrayHandle(
this->MapCellToConnectivityIndex, out);
out << " PointToCell: " << std::endl;
this->PointToCell.PrintSummary(out);
out << " CellToPoint: " << std::endl;
this->CellToPoint.PrintSummary(out);
}
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<vtkm::Id, ShapeStorageTag> &
GetShapesArray() const { return this->Shapes; }
GetShapesArray() const { return this->PointToCell.Shapes; }
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<vtkm::Id, NumIndicesStorageTag> &
GetNumIndicesArray() const { return this->NumIndices; }
GetNumIndicesArray() const { return this->PointToCell.NumIndices; }
VTKM_CONT_EXPORT
const vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag> &
GetConnectivityArray() const { return this->Connectivity; }
GetConnectivityArray() const { return this->PointToCell.Connectivity; }
VTKM_CONT_EXPORT
const vtkm::cont::ArrayHandle<vtkm::Id> &
GetCellToConnectivityIndexArray() const {
return this->MapCellToConnectivityIndex;
GetIndexOffsetArray() const {
return this->PointToCell.IndexOffsets;
}
public:
private:
typename ConnectivityChooser<
vtkm::TopologyElementTagPoint,vtkm::TopologyElementTagCell>::
ConnectivityType PointToCell;
// TODO: Actually implement CellToPoint and other connectivity. (That is,
// derive the connectivity from PointToCell.
typename ConnectivityChooser<
vtkm::TopologyElementTagCell,vtkm::TopologyElementTagPoint>::
ConnectivityType CellToPoint;
// A set of overloaded methods to get the connectivity from a pair of
// topology element types.
#define VTKM_GET_CONNECTIVITY_METHOD(FromTopology,ToTopology,Ivar) \
VTKM_CONT_EXPORT \
const typename ConnectivityChooser< \
FromTopology,ToTopology>::ConnectivityType & \
GetConnectivity(FromTopology, ToTopology) const \
{ \
return this->Ivar; \
} \
VTKM_CONT_EXPORT \
typename ConnectivityChooser< \
FromTopology,ToTopology>::ConnectivityType & \
GetConnectivity(FromTopology, ToTopology) \
{ \
return this->Ivar; \
}
VTKM_GET_CONNECTIVITY_METHOD(vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell,
PointToCell)
VTKM_GET_CONNECTIVITY_METHOD(vtkm::TopologyElementTagCell,
vtkm::TopologyElementTagPoint,
CellToPoint)
#undef VTKM_GET_CONNECTIVITY_METHOD
// These are used in the AddCell and related methods to incrementally add
// cells.
vtkm::Id ConnectivityLength;
vtkm::Id NumberOfCells;
ShapeArrayType Shapes;
NumIndicesArrayType NumIndices;
ConnectivityArrayType Connectivity;
MapCellToConnectivityIndexArrayType MapCellToConnectivityIndex;
};
namespace detail {
template<typename Storage1, typename Storage2, typename Storage3>
struct CellSetExplicitConnectivityChooser<
vtkm::cont::CellSetExplicit<Storage1,Storage2,Storage3>,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell>
{
typedef vtkm::cont::internal::ConnectivityExplicitInternals<
Storage1,Storage2,Storage3> ConnectivityType;
};
} // namespace detail
}
} // namespace vtkm::cont

@ -26,6 +26,7 @@ set(headers
ArrayPortalFromIterators.h
ArrayPortalShrink.h
ArrayTransfer.h
ConnectivityExplicitInternals.h
DeviceAdapterAlgorithmGeneral.h
DeviceAdapterAlgorithmSerial.h
DeviceAdapterError.h

@ -0,0 +1,109 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_internal_ConnectivityExplicitInternals_h
#define vtk_m_cont_internal_ConnectivityExplicitInternals_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/Assert.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
namespace vtkm {
namespace cont {
namespace internal {
template<typename ShapeStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename NumIndicesStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename ConnectivityStorageTag = VTKM_DEFAULT_STORAGE_TAG,
typename IndexOffsetStorageTag = VTKM_DEFAULT_STORAGE_TAG>
struct ConnectivityExplicitInternals
{
typedef vtkm::cont::ArrayHandle<vtkm::Id, ShapeStorageTag> ShapeArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id, NumIndicesStorageTag> NumIndicesArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorageTag> ConnectivityArrayType;
typedef vtkm::cont::ArrayHandle<vtkm::Id, IndexOffsetStorageTag> IndexOffsetArrayType;
ShapeArrayType Shapes;
NumIndicesArrayType NumIndices;
ConnectivityArrayType Connectivity;
IndexOffsetArrayType IndexOffsets;
bool ElementsValid;
bool IndexOffsetsValid;
VTKM_CONT_EXPORT
ConnectivityExplicitInternals()
: ElementsValid(false), IndexOffsetsValid(false) { }
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfElements() const {
return this->Shapes.GetNumberOfValues();
}
VTKM_CONT_EXPORT
void ReleaseResourcesExecution() {
this->Shapes.ReleaseResourcesExecution();
this->NumIndices.ReleaseResourcesExecution();
this->Connectivity.ReleaseResourcesExecution();
this->IndexOffsets.ReleaseResourcesExecution();
}
template<typename Device>
VTKM_CONT_EXPORT
void BuildIndexOffsets(Device) const
{
VTKM_ASSERT_CONT(this->ElementsValid);
if (!this->IndexOffsetsValid)
{
// 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::DeviceAdapterAlgorithm<Device>::ScanExclusive(
this->NumIndices,
const_cast<IndexOffsetArrayType&>(this->IndexOffsets));
const_cast<bool&>(this->IndexOffsetsValid) = true;
}
else
{
// Index offsets already built. Nothing to do.
}
}
VTKM_CONT_EXPORT
void PrintSummary(std::ostream &out) const
{
out <<" Shapes: ";
vtkm::cont::printSummary_ArrayHandle(this->Shapes, out);
out << std::endl;
out << " NumIndices: ";
vtkm::cont::printSummary_ArrayHandle(this->NumIndices, out);
out << std::endl;
out << " Connectivity: ";
vtkm::cont::printSummary_ArrayHandle(this->Connectivity, out);
out << std::endl;
out << " IndexOffsets: ";
vtkm::cont::printSummary_ArrayHandle(this->IndexOffsets, out);
}
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_internal_ConnectivityExplicitInternals_h

@ -30,7 +30,7 @@ namespace exec {
template<typename ShapePortalType,
typename NumIndicesPortalType,
typename ConnectivityPortalType,
typename MapConnectivityPortalType
typename IndexOffsetPortalType
>
class ConnectivityExplicit
{
@ -38,14 +38,14 @@ public:
ConnectivityExplicit() {}
ConnectivityExplicit(const ShapePortalType& shapePortal,
const NumIndicesPortalType& indicePortal,
const NumIndicesPortalType& numIndicesPortal,
const ConnectivityPortalType& connPortal,
const MapConnectivityPortalType& mapConnPortal
const IndexOffsetPortalType& indexOffsetPortal
)
: Shapes(shapePortal),
NumIndices(indicePortal),
NumIndices(numIndicesPortal),
Connectivity(connPortal),
MapCellToConnectivityIndex(mapConnPortal)
IndexOffset(indexOffsetPortal)
{
}
@ -73,7 +73,7 @@ public:
void GetIndices(vtkm::Id index, vtkm::Vec<vtkm::Id,ItemTupleLength> &ids)
{
vtkm::Id n = GetNumberOfIndices(index);
vtkm::Id start = MapCellToConnectivityIndex.Get(index);
vtkm::Id start = IndexOffset.Get(index);
for (vtkm::IdComponent i=0; i<n && i<ItemTupleLength; i++)
ids[i] = Connectivity.Get(start+i);
}
@ -82,7 +82,7 @@ private:
ShapePortalType Shapes;
NumIndicesPortalType NumIndices;
ConnectivityPortalType Connectivity;
MapConnectivityPortalType MapCellToConnectivityIndex;
IndexOffsetPortalType IndexOffset;
};
} // namespace exec

@ -62,7 +62,7 @@ vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &dataSet,
vtkm::cont::ArrayHandle<PointType> pointArray = dataSet.GetField("xyz").GetData().CastToArrayHandle<PointType, VTKM_DEFAULT_STORAGE_TAG>();
vtkm::cont::ArrayHandle<vtkm::Id> pointIdArray = cellSet.GetConnectivityArray();
vtkm::cont::ArrayHandle<vtkm::Id> cellToConnectivityIndexArray = cellSet.GetCellToConnectivityIndexArray();
vtkm::cont::ArrayHandle<vtkm::Id> indexOffsetArray = cellSet.GetIndexOffsetArray();
vtkm::cont::ArrayHandle<PointType> output_pointArray ;
vtkm::cont::ArrayHandle<vtkm::Id3> output_pointId3Array ;
@ -71,7 +71,7 @@ vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &dataSet,
vtkm::worklet::VertexClustering<VTKM_DEFAULT_DEVICE_ADAPTER_TAG>().run(
pointArray,
pointIdArray,
cellToConnectivityIndexArray,
indexOffsetArray,
bounds,
nDivisions,
output_pointArray,