Some fixes to VertexClustering

VertexClustering previously only worked with data of a specific floating
point type (32 bit for point coordinates). Add some templates to accept
either 32 bit or 64 bit floating points for point coordintes and be a
bit more careful about implicit type conversions.

I also made some changes to conform better with the VTK-m coding
standards. The most common changes are using 2 space indentation for all
block levels, capitolizing and using camel case for all class members,
and prefixing "this->" to all use of internal class members.
This commit is contained in:
Kenneth Moreland 2015-06-29 15:14:50 -06:00
parent ba20680728
commit cc8a5d35ec
5 changed files with 218 additions and 113 deletions

74
vtkm/exec/Assert.h Normal file

@ -0,0 +1,74 @@
//============================================================================
// 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_exec_Assert_h
#define vtk_m_exec_Assert_h
#include <vtkm/internal/ExportMacros.h>
// Stringify macros for DAX_ASSERT_EXEC
#define __VTKM_ASSERT_EXEC_STRINGIFY_2ND(s) #s
#define __VTKM_ASSERT_EXEC_STRINGIFY(s) __VTKM_ASSERT_EXEC_STRINGIFY_2ND(s)
/// \def VTKM_ASSERT_EXEC(condition, work)
///
/// Asserts that \a condition resolves to true. If \a condition is false, then
/// an error is raised. This macro is meant to work in the VTK-m execution
/// environment and requires the \a work object to raise the error and throw it
/// in the control environment.
///
#ifndef NDEBUG
#define VTKM_ASSERT_EXEC(condition, work) \
if (!(condition)) \
::vtkm::exec::Assert( \
condition, \
__FILE__ ":" __VTKM_ASSERT_EXEC_STRINGIFY(__LINE__) ": " \
"Assert Failed (" #condition ")", \
work)
#else
//in release mode we just act like we use the result of the condition
//and the worklet so that we don't introduce new issues.
#define VTKM_ASSERT_EXEC(condition, work) \
(void)(condition); \
(void)(work);
#endif
namespace vtkm {
namespace exec {
/// Implements the assert functionality of VTKM_ASSERT_EXEC.
///
template<typename WorkType>
VTKM_EXEC_EXPORT
void Assert(bool condition, const char *message, WorkType work)
{
if (condition)
{
// Do nothing.
}
else
{
work.RaiseError(message);
}
}
}
} // namespace vtkm::exec
#endif //vtk_m_exec_Assert_h

@ -19,6 +19,7 @@
##============================================================================
set(headers
Assert.h
ExecutionObjectBase.h
ExplicitConnectivity.h
FunctorBase.h

@ -30,6 +30,7 @@
#include <vtkm/cont/Timer.h>
#include <vtkm/Pair.h>
#include <vtkm/Types.h>
#include <vtkm/VecTraits.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
@ -46,7 +47,10 @@ struct DivideWorklet: public vtkm::worklet::WorkletMapField{
VTKM_EXEC_EXPORT void operator()(
const ValueType &v, const vtkm::Id &count, ValueType &vout) const
{ vout = v * (1./count); }
{
typedef typename VecTraits<ValueType>::ComponentType ComponentType;
vout = v * ComponentType(1./count);
}
};
template<typename _Tp>

@ -20,7 +20,9 @@
#ifndef vtk_m_worklet_VertexClustering_h
#define vtk_m_worklet_VertexClustering_h
#include <numeric>
#include <vtkm/Math.h>
#include <vtkm/exec/Assert.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
@ -46,65 +48,59 @@
namespace vtkm{ namespace worklet
{
template <class DeviceAdapter>
template<typename DeviceAdapter>
struct VertexClustering{
typedef vtkm::Vec<vtkm::Float32,3> Vector3;
typedef Vector3 PointType;
template<typename PointType>
struct GridInfo
{
int dim[3];
Vector3 origin;
vtkm::Float64 grid_width;
vtkm::Float64 inv_grid_width; // = 1/grid_width
vtkm::Id dim[3];
PointType origin;
typename PointType::ComponentType grid_width;
typename PointType::ComponentType inv_grid_width; // = 1/grid_width
};
// input: points output: cid of the points
template<typename PointType>
class MapPointsWorklet : public vtkm::worklet::WorkletMapField {
private:
//const VTKM_EXEC_CONSTANT_EXPORT GridInfo grid;
GridInfo grid;
VTKM_EXEC_EXPORT
vtkm::Id min(vtkm::Id a, vtkm::Id b) const {
return (a<b)?a:b;
}
//const VTKM_EXEC_CONSTANT_EXPORT GridInfo<PointType> Grid;
GridInfo<PointType> Grid;
public:
typedef void ControlSignature(FieldIn<> , FieldOut<>);
typedef void ExecutionSignature(_1, _2);
typedef void ControlSignature(FieldIn<> , FieldOut<>);
typedef void ExecutionSignature(_1, _2);
VTKM_CONT_EXPORT
MapPointsWorklet(const GridInfo &grid_)
: grid(grid_)
{ }
VTKM_CONT_EXPORT
MapPointsWorklet(const GridInfo<PointType> &grid)
: Grid(grid)
{ }
/// determine grid resolution for clustering
VTKM_EXEC_EXPORT
vtkm::Id get_cluster_id( const Vector3 &p) const
{
Vector3 p_rel = (p - grid.origin) * grid.inv_grid_width;
vtkm::Id x = min((vtkm::Id)p_rel[0], grid.dim[0]-1);
vtkm::Id y = min((vtkm::Id)p_rel[1], grid.dim[1]-1);
vtkm::Id z = min((vtkm::Id)p_rel[2], grid.dim[2]-1);
return x + grid.dim[0] * (y + grid.dim[1] * z); // get a unique hash value
}
/// determine grid resolution for clustering
VTKM_EXEC_EXPORT
vtkm::Id GetClusterId(const PointType &p) const
{
PointType p_rel = (p - this->Grid.origin) * this->Grid.inv_grid_width;
vtkm::Id x = vtkm::Min((vtkm::Id)p_rel[0], this->Grid.dim[0]-1);
vtkm::Id y = vtkm::Min((vtkm::Id)p_rel[1], this->Grid.dim[1]-1);
vtkm::Id z = vtkm::Min((vtkm::Id)p_rel[2], this->Grid.dim[2]-1);
return x + this->Grid.dim[0] * (y + this->Grid.dim[1] * z); // get a unique hash value
}
VTKM_EXEC_EXPORT
void operator()(const PointType &point, vtkm::Id &cid) const
{
cid = get_cluster_id(point);
VTKM_ASSERT_CONT(cid>=0); // the id could overflow if too many cells
}
VTKM_EXEC_EXPORT
void operator()(const PointType &point, vtkm::Id &cid) const
{
cid = this->GetClusterId(point);
VTKM_ASSERT_EXEC(cid>=0, *this); // the id could overflow if too many cells
}
};
class MapCellsWorklet: public vtkm::worklet::WorkletMapField {
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IdPortalType;
IdPortalType pointIdPortal;
IdPortalType pointCidPortal;
IdPortalType numIndicesPortal;
IdPortalType PointIdPortal;
IdPortalType PointCidPortal;
IdPortalType NumIndicesPortal;
public:
typedef void ControlSignature(FieldIn<> , FieldOut<>);
typedef void ExecutionSignature(_1, _2);
@ -113,18 +109,18 @@ struct VertexClustering{
MapCellsWorklet(
const IdArrayHandle &pointIdArray, // the given point Ids
const IdArrayHandle &pointCidArray) // the cluser ids each pointId will map to
: pointIdPortal(pointIdArray.PrepareForInput(DeviceAdapter()) ),
pointCidPortal( pointCidArray.PrepareForInput(DeviceAdapter()))
: PointIdPortal(pointIdArray.PrepareForInput(DeviceAdapter())),
PointCidPortal(pointCidArray.PrepareForInput(DeviceAdapter()))
{ }
VTKM_EXEC_EXPORT
void operator()(const vtkm::Id &pointIdIndex, vtkm::Id3 &cid3) const
{
//VTKM_ASSERT_CONT(pointIdIndex % 3 == 0); // TODO: may ignore non-triangle cells
//VTKM_ASSERT_EXEC(pointIdIndex % 3 == 0, *this); // TODO: may ignore non-triangle cells
// assume it's a triangle
cid3[0] = pointCidPortal.Get( pointIdPortal.Get(pointIdIndex) );
cid3[1] = pointCidPortal.Get( pointIdPortal.Get(pointIdIndex+1) );
cid3[2] = pointCidPortal.Get( pointIdPortal.Get(pointIdIndex+2) );
cid3[0] = this->PointCidPortal.Get( this->PointIdPortal.Get(pointIdIndex) );
cid3[1] = this->PointCidPortal.Get( this->PointIdPortal.Get(pointIdIndex+1) );
cid3[2] = this->PointCidPortal.Get( this->PointIdPortal.Get(pointIdIndex+2) );
}
};
@ -132,11 +128,11 @@ struct VertexClustering{
class IndexingWorklet : public vtkm::worklet::WorkletMapField
{
public:
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
private:
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::Portal IdPortalType;
IdArrayHandle cidIndexArray;
IdPortalType cidIndexRaw;
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::Portal IdPortalType;
IdArrayHandle CidIndexArray;
IdPortalType CidIndexRaw;
public:
typedef void ControlSignature(FieldIn<>, FieldIn<>);
typedef void ExecutionSignature(_1, _2);
@ -144,19 +140,19 @@ struct VertexClustering{
VTKM_CONT_EXPORT
IndexingWorklet( vtkm::Id n )
{
cidIndexRaw = cidIndexArray.PrepareForOutput(n, DeviceAdapter() );
this->CidIndexRaw = this->CidIndexArray.PrepareForOutput(n, DeviceAdapter() );
}
VTKM_EXEC_EXPORT
void operator()(const vtkm::Id &counter, const vtkm::Id &cid) const
{
cidIndexRaw.Set(cid, counter);
this->CidIndexRaw.Set(cid, counter);
}
VTKM_CONT_EXPORT
IdArrayHandle &getOutput()
IdArrayHandle &GetOutput()
{
return cidIndexArray;
return this->CidIndexArray;
}
};
@ -164,32 +160,32 @@ struct VertexClustering{
class Cid2PointIdWorklet : public vtkm::worklet::WorkletMapField
{
public:
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
typedef typename vtkm::cont::ArrayHandle<vtkm::Id> IdArrayHandle;
private:
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IdPortalType;
const IdPortalType cidIndexRaw;
typedef typename IdArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst IdPortalType;
const IdPortalType CidIndexRaw;
public:
typedef void ControlSignature(FieldIn<>, FieldOut<>);
typedef void ExecutionSignature(_1, _2);
typedef void ControlSignature(FieldIn<>, FieldOut<>);
typedef void ExecutionSignature(_1, _2);
VTKM_CONT_EXPORT
Cid2PointIdWorklet( IdArrayHandle &cidIndexArray )
: cidIndexRaw ( cidIndexArray.PrepareForInput(DeviceAdapter()) )
{
}
VTKM_CONT_EXPORT
Cid2PointIdWorklet( IdArrayHandle &cidIndexArray )
: CidIndexRaw ( cidIndexArray.PrepareForInput(DeviceAdapter()) )
{
}
VTKM_EXEC_EXPORT
void operator()(const vtkm::Id3 &cid3, vtkm::Id3 &pointId3) const
VTKM_EXEC_EXPORT
void operator()(const vtkm::Id3 &cid3, vtkm::Id3 &pointId3) const
{
if (cid3[0]==cid3[1] || cid3[0]==cid3[2] || cid3[1]==cid3[2])
{
if (cid3[0]==cid3[1] || cid3[0]==cid3[2] || cid3[1]==cid3[2])
{
pointId3[0] = pointId3[1] = pointId3[2] = -1 ; // invalid cell to be removed
} else {
pointId3[0] = cidIndexRaw.Get( cid3[0] );
pointId3[1] = cidIndexRaw.Get( cid3[1] );
pointId3[2] = cidIndexRaw.Get( cid3[2] );
}
pointId3[0] = pointId3[1] = pointId3[2] = -1 ; // invalid cell to be removed
} else {
pointId3[0] = this->CidIndexRaw.Get( cid3[0] );
pointId3[1] = this->CidIndexRaw.Get( cid3[1] );
pointId3[2] = this->CidIndexRaw.Get( cid3[2] );
}
}
};
@ -215,33 +211,41 @@ public:
/// \param ds : dataset
/// \param bounds: dataset bounds
/// \param nDivisions : number of max divisions per dimension
template <class StorageT, class StorageU, class StorageV>
void run(const vtkm::cont::ArrayHandle<PointType, StorageT> pointArray,
template <typename FloatType,
typename BoundsType,
typename StorageT,
typename StorageU,
typename StorageV>
void run(const vtkm::cont::ArrayHandle<vtkm::Vec<FloatType,3>, StorageT> pointArray,
const vtkm::cont::ArrayHandle<vtkm::Id, StorageU> pointIdArray,
const vtkm::cont::ArrayHandle<vtkm::Id, StorageV> cellToConnectivityIndexArray,
const vtkm::Float64 bounds[6], vtkm::Id nDivisions,
vtkm::cont::ArrayHandle<PointType> &output_pointArray,
const BoundsType bounds[6], vtkm::Id nDivisions,
vtkm::cont::ArrayHandle<vtkm::Vec<FloatType,3> > &output_pointArray,
vtkm::cont::ArrayHandle<vtkm::Id3> &output_pointId3Array)
{
/// determine grid resolution for clustering
GridInfo gridInfo;
{
vtkm::Float64 res[3];
for (int i=0; i<3; i++)
res[i] = (bounds[i*2+1]-bounds[i*2])/nDivisions;
gridInfo.grid_width = std::max(res[0], std::max(res[1], res[2]));
typedef vtkm::Vec<FloatType,3> PointType;
vtkm::Float64 inv_grid_width = gridInfo.inv_grid_width = 1. / gridInfo.grid_width;
/// determine grid resolution for clustering
GridInfo<PointType> gridInfo;
{
FloatType res[3];
for (vtkm::IdComponent i=0; i<3; i++)
{
res[i] = static_cast<FloatType>((bounds[i*2+1]-bounds[i*2])/nDivisions);
}
gridInfo.grid_width = vtkm::Max(res[0], vtkm::Max(res[1], res[2]));
FloatType inv_grid_width = gridInfo.inv_grid_width = FloatType(1) / gridInfo.grid_width;
//printf("Bounds: %lf, %lf, %lf, %lf, %lf, %lf\n", bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]);
gridInfo.dim[0] = (int)ceil((bounds[1]-bounds[0])*inv_grid_width);
gridInfo.dim[1] = (int)ceil((bounds[3]-bounds[2])*inv_grid_width);
gridInfo.dim[2] = (int)ceil((bounds[5]-bounds[4])*inv_grid_width);
gridInfo.dim[0] = (vtkm::Id)vtkm::Ceil((bounds[1]-bounds[0])*inv_grid_width);
gridInfo.dim[1] = (vtkm::Id)vtkm::Ceil((bounds[3]-bounds[2])*inv_grid_width);
gridInfo.dim[2] = (vtkm::Id)vtkm::Ceil((bounds[5]-bounds[4])*inv_grid_width);
// center the mesh in the grids
gridInfo.origin[0] = (vtkm::Float32) ((bounds[1]+bounds[0])*0.5 - gridInfo.grid_width*(gridInfo.dim[0])*.5);
gridInfo.origin[1] = (vtkm::Float32) ((bounds[3]+bounds[2])*0.5 - gridInfo.grid_width*(gridInfo.dim[1])*.5);
gridInfo.origin[2] = (vtkm::Float32) ((bounds[5]+bounds[4])*0.5 - gridInfo.grid_width*(gridInfo.dim[2])*.5);
gridInfo.origin[0] = static_cast<FloatType>((bounds[1]+bounds[0])*0.5 - gridInfo.grid_width*(gridInfo.dim[0])*.5);
gridInfo.origin[1] = static_cast<FloatType>((bounds[3]+bounds[2])*0.5 - gridInfo.grid_width*(gridInfo.dim[1])*.5);
gridInfo.origin[2] = static_cast<FloatType>((bounds[5]+bounds[4])*0.5 - gridInfo.grid_width*(gridInfo.dim[2])*.5);
}
//construct the scheduler that will execute all the worklets
@ -257,7 +261,8 @@ public:
/// map points
vtkm::cont::ArrayHandle<vtkm::Id> pointCidArray;
vtkm::worklet::DispatcherMapField<MapPointsWorklet>(MapPointsWorklet(gridInfo))
vtkm::worklet::DispatcherMapField<MapPointsWorklet<PointType> >(
MapPointsWorklet<PointType>(gridInfo))
.Invoke(pointArray, pointCidArray );
#ifdef __VTKM_VERTEX_CLUSTERING_BENCHMARK
@ -269,7 +274,7 @@ public:
/// using pointCidArray as the key
///
vtkm::cont::ArrayHandle<vtkm::Id> pointCidArrayReduced;
vtkm::cont::ArrayHandle<Vector3> repPointArray; // representative point
vtkm::cont::ArrayHandle<PointType> repPointArray; // representative point
vtkm::worklet::
AverageByKey( pointCidArray, pointArray, pointCidArrayReduced, repPointArray );
@ -306,8 +311,9 @@ public:
///
vtkm::cont::ArrayHandle<vtkm::Id3> pointId3Array;
vtkm::worklet::DispatcherMapField<Cid2PointIdWorklet> ( Cid2PointIdWorklet( worklet3.getOutput() ) )
.Invoke(cid3Array, pointId3Array);
vtkm::worklet::DispatcherMapField<Cid2PointIdWorklet>(
Cid2PointIdWorklet( worklet3.GetOutput() ) )
.Invoke(cid3Array, pointId3Array);
#ifdef __VTKM_VERTEX_CLUSTERING_BENCHMARK

@ -31,7 +31,7 @@
#include <vtkm/worklet/VertexClustering.h>
template<typename T, int N>
template<typename T, vtkm::IdComponent N>
vtkm::cont::ArrayHandle<T> copyFromVec( vtkm::cont::ArrayHandle< vtkm::Vec<T, N> > const& other)
{
const T *vmem = reinterpret_cast< const T *>(& *other.GetPortalConstControl().GetIteratorBegin());
@ -49,7 +49,9 @@ vtkm::cont::ArrayHandle<T> copyFromImplicit( vtkm::cont::ArrayHandle<T, StorageT
return result;
}
vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &ds, const vtkm::Float64 bounds[6], int nDivisions)
vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &ds,
const vtkm::Float64 bounds[6],
vtkm::Id nDivisions)
{
typedef vtkm::Vec<vtkm::Float32,3> PointType;
@ -65,16 +67,21 @@ vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &ds, const vtkm::Flo
vtkm::cont::ArrayHandle<vtkm::Id3> output_pointId3Array ;
// run
vtkm::worklet::VertexClustering<VTKM_DEFAULT_DEVICE_ADAPTER_TAG>().run(pointArray, pointIdArray, cellToConnectivityIndexArray,
bounds, nDivisions,
output_pointArray, output_pointId3Array);
vtkm::worklet::VertexClustering<VTKM_DEFAULT_DEVICE_ADAPTER_TAG>().run(
pointArray,
pointIdArray,
cellToConnectivityIndexArray,
bounds,
nDivisions,
output_pointArray,
output_pointId3Array);
vtkm::cont::DataSet new_ds;
new_ds.AddField(vtkm::cont::Field("xyz", 0, vtkm::cont::Field::ASSOC_POINTS, output_pointArray));
new_ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("xyz"));
int cells = output_pointId3Array.GetNumberOfValues();
vtkm::Id cells = output_pointId3Array.GetNumberOfValues();
if (cells > 0)
{
//typedef typename vtkm::cont::ArrayHandleConstant<vtkm::Id>::StorageTag ConstantStorage;
@ -98,8 +105,8 @@ vtkm::cont::DataSet RunVertexClustering(vtkm::cont::DataSet &ds, const vtkm::Flo
void TestVertexClustering()
{
double bounds[6];
const int divisions = 3;
vtkm::Float64 bounds[6];
const vtkm::Id divisions = 3;
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::DataSet ds = maker.Make3DExplicitDataSetCowNose(bounds);
@ -107,18 +114,31 @@ void TestVertexClustering()
vtkm::cont::DataSet ds_out = RunVertexClustering(ds, bounds, divisions);
// test
const int output_pointIds = 9;
int output_pointId[output_pointIds] = {1,2,5, 1,3,0, 1,5,4};
const int output_points = 6;
double output_point[output_points][3] = {{0.0174716003,0.0501927994,0.0930275023}, {0.0320714004,0.14704667,0.0952706337}, {0.0268670674,0.246195346,0.119720004}, {0.00215422804,0.0340906903,0.180881709}, {0.0108188,0.152774006,0.167914003}, {0.0202241503,0.225427493,0.140208006}};
const vtkm::Id output_pointIds = 12;
vtkm::Id output_pointId[output_pointIds] = {
1,2,5,
1,3,0,
4,3,1,
6,5,2
};
const vtkm::Id output_points = 7;
// double output_point[output_points][3] = {{0.0174716003,0.0501927994,0.0930275023}, {0.0320714004,0.14704667,0.0952706337}, {0.0268670674,0.246195346,0.119720004}, {0.00215422804,0.0340906903,0.180881709}, {0.0108188,0.152774006,0.167914003}, {0.0202241503,0.225427493,0.140208006}};
double output_point[output_points][3] = {
{0.0174716,0.0501928,0.0930275},
{0.0320714,0.147047,0.0952706},
{0.0268671,0.246195,0.11972},
{0.000631619,0.00311701,0.173352},
{0.00418437,0.0753889,0.190921},
{0.0144137,0.178567,0.156615},
{0.0224398,0.246495,0.1351}
};
vtkm::Id i;
VTKM_TEST_ASSERT(ds_out.GetNumberOfFields() == 1, "Number of output fields mismatch");
typedef vtkm::Vec<vtkm::Float32, 3> PointType;
typedef vtkm::cont::ArrayHandle<PointType > PointArray;
PointArray pointArray = ds_out.GetField(0).GetData().CastToArrayHandle<PointArray::ValueType, PointArray::StorageTag>();
VTKM_TEST_ASSERT(pointArray.GetNumberOfValues() == output_points, "Number of output points mismatch" );
for (i = 0; i < pointArray.GetNumberOfValues(); ++i)
for (vtkm::Id i = 0; i < pointArray.GetNumberOfValues(); ++i)
{
const PointType &p1 = pointArray.GetPortalConstControl().Get(i);
PointType p2 = vtkm::make_Vec<vtkm::Float32>((vtkm::Float32)output_point[i][0], (vtkm::Float32)output_point[i][1], (vtkm::Float32)output_point[i][2]) ;
@ -131,7 +151,7 @@ void TestVertexClustering()
VTKM_TEST_ASSERT(cellset, "CellSet Cast fail");
vtkm::cont::ExplicitConnectivity<> &conn = cellset->GetNodeToCellConnectivity();
VTKM_TEST_ASSERT(conn.GetConnectivityArray().GetNumberOfValues() == output_pointIds, "Number of connectivity array elements mismatch");
for (i=0; i<conn.GetConnectivityArray().GetNumberOfValues(); i++)
for (vtkm::Id i=0; i<conn.GetConnectivityArray().GetNumberOfValues(); i++)
{
vtkm::Id id1 = conn.GetConnectivityArray().GetPortalConstControl().Get(i) ;
vtkm::Id id2 = output_pointId[i] ;