Add a test for the WholeCellSetIn argument

All types of cell sets should have a consistent interface. This is
tested (and fixed) for explicit and permutation cell sets. However, an
unfixed bug that has been identified is that permutation cell sets only
work for point to cell topologies. All others are not supported
correctly.
This commit is contained in:
Kenneth Moreland 2017-07-28 13:40:31 -06:00
parent 938db09ad5
commit 03b6f62d05
6 changed files with 338 additions and 3 deletions

@ -103,10 +103,32 @@ public:
template <typename Device, typename FromTopology, typename ToTopology>
typename ExecutionTypes<Device, FromTopology, ToTopology>::ExecObjectType
PrepareForInput(Device d, FromTopology f, ToTopology t) const
PrepareForInput(Device, FromTopology, ToTopology) const
{
typedef
typename ExecutionTypes<Device, FromTopology, ToTopology>::ExecObjectType ConnectivityType;
// Developer's note: I looked into supporting cell to point connectivity in a permutation cell
// set and found it to be complex. It is not straightforward to implement this on top of the
// original cell set's cell to point because points could be attached to cells that do not
// exist in the permuted topology. Ultimately, you will probably have to rebuild these
// connections in a way very similar to how CellSetExplicit already does it. In fact, the
// easiest implementation will probably be to just convert to a CellSetExplicit and use that.
// In fact, it may be possible to change this whole implementation to just be a subclass of
// CellSetExplicit with some fancy arrays for its point to cell arrays.
throw vtkm::cont::ErrorBadType(
"CellSetPermutation currently only supports point to cell connectivity. "
"To support other connectivity, convert to an explicit grid with the CellDeepCopy "
"worklet or the CleanGrid filter.");
}
template <typename Device>
typename ExecutionTypes<Device,
vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell>::ExecObjectType
PrepareForInput(Device d, vtkm::TopologyElementTagPoint f, vtkm::TopologyElementTagCell t) const
{
using FromTopology = vtkm::TopologyElementTagPoint;
using ToTopology = vtkm::TopologyElementTagCell;
using ConnectivityType =
typename ExecutionTypes<Device, FromTopology, ToTopology>::ExecObjectType;
return ConnectivityType(this->ValidCellIds.PrepareForInput(d),
this->FullCellSet.PrepareForInput(d, f, t));
}

@ -60,6 +60,9 @@ public:
VTKM_EXEC
CellShapeTag GetCellShape(vtkm::Id index) const { return CellShapeTag(this->Shapes.Get(index)); }
VTKM_EXEC
vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const { return this->NumIndices.Get(index); }
using IndicesType = vtkm::VecFromPortal<ConnectivityPortalType>;
/// Returns a Vec-like object containing the indices for the given index.

@ -58,6 +58,9 @@ public:
{
}
VTKM_EXEC
vtkm::Id GetNumberOfElements() const { return this->Portal.GetNumberOfValues(); }
typedef typename OriginalConnectivity::CellShapeTag CellShapeTag;
VTKM_EXEC
@ -67,6 +70,12 @@ public:
return this->Connectivity.GetCellShape(pIndex);
}
VTKM_EXEC
vtkm::IdComponent GetNumberOfIndices(vtkm::Id index) const
{
return this->Connectivity.GetNumberOfIndices(this->Portal.Get(index));
}
typedef typename OriginalConnectivity::IndicesType IndicesType;
template <typename IndexType>

@ -592,4 +592,26 @@ static inline VTKM_CONT void SetPortal(const PortalType& portal)
}
}
/// Verifies that the contents of the two portals are the same.
///
template <typename PortalType1, typename PortalType2>
static inline VTKM_CONT bool test_equal_portals(const PortalType1& portal1,
const PortalType2& portal2)
{
if (portal1.GetNumberOfValues() != portal2.GetNumberOfValues())
{
return false;
}
for (vtkm::Id index = 0; index < portal1.GetNumberOfValues(); index++)
{
if (!test_equal(portal1.Get(index), portal2.Get(index)))
{
return false;
}
}
return true;
}
#endif //vtk_m_testing_Testing_h

@ -50,6 +50,7 @@ set(unit_tests
UnitTestThreshold.cxx
UnitTestThresholdPoints.cxx
UnitTestTriangulate.cxx
UnitTestWholeCellSetIn.cxx
UnitTestWorkletMapField.cxx
UnitTestWorkletMapFieldExecArg.cxx
UnitTestWorkletMapFieldWholeArray.cxx

@ -0,0 +1,278 @@
//============================================================================
// 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 2017 Sandia Corporation.
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 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.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
struct TestWholeCellSetIn
{
template <typename FromTopology, typename ToTopology>
struct WholeCellSetWorklet : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn<> indices,
WholeCellSetIn<FromTopology, ToTopology>,
FieldOut<> numberOfElements,
FieldOut<> shapes,
FieldOut<> numberOfindices,
FieldOut<> connectionSum);
using ExecutionSignature = void(_1, _2, _3, _4, _5, _6);
using InputDomain = _1;
template <typename ConnectivityType>
VTKM_EXEC void operator()(vtkm::Id index,
const ConnectivityType& connectivity,
vtkm::Id& numberOfElements,
vtkm::UInt8& shape,
vtkm::IdComponent& numberOfIndices,
vtkm::Id& connectionSum) const
{
numberOfElements = connectivity.GetNumberOfElements();
shape = connectivity.GetCellShape(index).Id;
numberOfIndices = connectivity.GetNumberOfIndices(index);
typename ConnectivityType::IndicesType indices = connectivity.GetIndices(index);
if (numberOfIndices != indices.GetNumberOfComponents())
{
this->RaiseError("Got wrong number of connections.");
}
connectionSum = 0;
for (vtkm::IdComponent componentIndex = 0; componentIndex < indices.GetNumberOfComponents();
componentIndex++)
{
connectionSum += indices[componentIndex];
}
}
};
template <typename CellSetType>
VTKM_CONT static void RunCells(const CellSetType& cellSet,
vtkm::cont::ArrayHandle<vtkm::Id> numberOfElements,
vtkm::cont::ArrayHandle<vtkm::UInt8> shapeIds,
vtkm::cont::ArrayHandle<vtkm::IdComponent> numberOfIndices,
vtkm::cont::ArrayHandle<vtkm::Id> connectionSum)
{
using WorkletType =
WholeCellSetWorklet<vtkm::TopologyElementTagPoint, vtkm::TopologyElementTagCell>;
vtkm::worklet::DispatcherMapField<WorkletType> dispatcher;
dispatcher.Invoke(vtkm::cont::ArrayHandleIndex(cellSet.GetNumberOfCells()),
cellSet,
numberOfElements,
shapeIds,
numberOfIndices,
connectionSum);
}
template <typename CellSetType>
VTKM_CONT static void RunPoints(const CellSetType& cellSet,
vtkm::cont::ArrayHandle<vtkm::Id> numberOfElements,
vtkm::cont::ArrayHandle<vtkm::UInt8> shapeIds,
vtkm::cont::ArrayHandle<vtkm::IdComponent> numberOfIndices,
vtkm::cont::ArrayHandle<vtkm::Id> connectionSum)
{
using WorkletType =
WholeCellSetWorklet<vtkm::TopologyElementTagCell, vtkm::TopologyElementTagPoint>;
vtkm::worklet::DispatcherMapField<WorkletType> dispatcher;
dispatcher.Invoke(vtkm::cont::ArrayHandleIndex(cellSet.GetNumberOfPoints()),
cellSet,
numberOfElements,
shapeIds,
numberOfIndices,
connectionSum);
}
};
template <typename CellSetType,
typename ShapeArrayType,
typename NumIndicesArrayType,
typename ConnectionSumArrayType>
VTKM_CONT void TryCellConnectivity(const CellSetType& cellSet,
const ShapeArrayType& expectedShapeIds,
const NumIndicesArrayType& expectedNumberOfIndices,
const ConnectionSumArrayType& expectedSum)
{
std::cout << " trying point to cell connectivity" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Id> numberOfElements;
vtkm::cont::ArrayHandle<vtkm::UInt8> shapeIds;
vtkm::cont::ArrayHandle<vtkm::IdComponent> numberOfIndices;
vtkm::cont::ArrayHandle<vtkm::Id> connectionSum;
TestWholeCellSetIn::RunCells(cellSet, numberOfElements, shapeIds, numberOfIndices, connectionSum);
std::cout << " Number of elements: " << numberOfElements.GetPortalConstControl().Get(0)
<< std::endl;
VTKM_TEST_ASSERT(test_equal_portals(numberOfElements.GetPortalConstControl(),
vtkm::cont::make_ArrayHandleConstant(
cellSet.GetNumberOfCells(), cellSet.GetNumberOfCells())
.GetPortalConstControl()),
"Incorrect number of elements.");
std::cout << " Shape Ids: ";
vtkm::cont::printSummary_ArrayHandle(shapeIds, std::cout, true);
VTKM_TEST_ASSERT(
test_equal_portals(shapeIds.GetPortalConstControl(), expectedShapeIds.GetPortalConstControl()),
"Incorrect shape Ids.");
std::cout << " Number of indices: ";
vtkm::cont::printSummary_ArrayHandle(numberOfIndices, std::cout, true);
VTKM_TEST_ASSERT(test_equal_portals(numberOfIndices.GetPortalConstControl(),
expectedNumberOfIndices.GetPortalConstControl()),
"Incorrect number of indices.");
std::cout << " Sum of indices: ";
vtkm::cont::printSummary_ArrayHandle(connectionSum, std::cout, true);
VTKM_TEST_ASSERT(
test_equal_portals(connectionSum.GetPortalConstControl(), expectedSum.GetPortalConstControl()),
"Incorrect sum of indices.");
}
template <typename CellSetType,
typename ShapeArrayType,
typename NumIndicesArrayType,
typename ConnectionSumArrayType>
VTKM_CONT void TryPointConnectivity(const CellSetType& cellSet,
const ShapeArrayType& expectedShapeIds,
const NumIndicesArrayType& expectedNumberOfIndices,
const ConnectionSumArrayType& expectedSum)
{
std::cout << " trying cell to point connectivity" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Id> numberOfElements;
vtkm::cont::ArrayHandle<vtkm::UInt8> shapeIds;
vtkm::cont::ArrayHandle<vtkm::IdComponent> numberOfIndices;
vtkm::cont::ArrayHandle<vtkm::Id> connectionSum;
TestWholeCellSetIn::RunPoints(
cellSet, numberOfElements, shapeIds, numberOfIndices, connectionSum);
std::cout << " Number of elements: " << numberOfElements.GetPortalConstControl().Get(0)
<< std::endl;
VTKM_TEST_ASSERT(test_equal_portals(numberOfElements.GetPortalConstControl(),
vtkm::cont::make_ArrayHandleConstant(
cellSet.GetNumberOfPoints(), cellSet.GetNumberOfPoints())
.GetPortalConstControl()),
"Incorrect number of elements.");
std::cout << " Shape Ids: ";
vtkm::cont::printSummary_ArrayHandle(shapeIds, std::cout, true);
VTKM_TEST_ASSERT(
test_equal_portals(shapeIds.GetPortalConstControl(), expectedShapeIds.GetPortalConstControl()),
"Incorrect shape Ids.");
std::cout << " Number of indices: ";
vtkm::cont::printSummary_ArrayHandle(numberOfIndices, std::cout, true);
VTKM_TEST_ASSERT(test_equal_portals(numberOfIndices.GetPortalConstControl(),
expectedNumberOfIndices.GetPortalConstControl()),
"Incorrect number of indices.");
std::cout << " Sum of indices: ";
vtkm::cont::printSummary_ArrayHandle(connectionSum, std::cout, true);
VTKM_TEST_ASSERT(
test_equal_portals(connectionSum.GetPortalConstControl(), expectedSum.GetPortalConstControl()),
"Incorrect sum of indices.");
}
VTKM_CONT
void TryExplicitGrid()
{
std::cout << "Testing explicit grid." << std::endl;
vtkm::cont::DataSet dataSet = vtkm::cont::testing::MakeTestDataSet().Make3DExplicitDataSet5();
vtkm::cont::CellSetExplicit<> cellSet;
dataSet.GetCellSet().CopyTo(cellSet);
vtkm::UInt8 expectedCellShapes[] = { vtkm::CELL_SHAPE_HEXAHEDRON,
vtkm::CELL_SHAPE_PYRAMID,
vtkm::CELL_SHAPE_TETRA,
vtkm::CELL_SHAPE_WEDGE };
vtkm::IdComponent expectedCellNumIndices[] = { 8, 5, 4, 6 };
vtkm::Id expectedCellIndexSum[] = { 28, 22, 29, 41 };
vtkm::Id numCells = cellSet.GetNumberOfCells();
TryCellConnectivity(cellSet,
vtkm::cont::make_ArrayHandle(expectedCellShapes, numCells),
vtkm::cont::make_ArrayHandle(expectedCellNumIndices, numCells),
vtkm::cont::make_ArrayHandle(expectedCellIndexSum, numCells));
vtkm::IdComponent expectedPointNumIndices[] = { 1, 2, 2, 1, 2, 4, 4, 2, 2, 1, 2 };
vtkm::Id expectedPointIndexSum[] = { 0, 1, 1, 0, 3, 6, 6, 3, 3, 3, 5 };
vtkm::Id numPoints = cellSet.GetNumberOfPoints();
TryPointConnectivity(
cellSet,
vtkm::cont::make_ArrayHandleConstant(vtkm::CellShapeTagVertex::Id, numPoints),
vtkm::cont::make_ArrayHandle(expectedPointNumIndices, numPoints),
vtkm::cont::make_ArrayHandle(expectedPointIndexSum, numPoints));
}
VTKM_CONT
void TryCellSetPermutation()
{
std::cout << "Testing permutation grid." << std::endl;
vtkm::cont::DataSet dataSet = vtkm::cont::testing::MakeTestDataSet().Make3DExplicitDataSet5();
vtkm::cont::CellSetExplicit<> originalCellSet;
dataSet.GetCellSet().CopyTo(originalCellSet);
vtkm::Id permutationArray[] = { 2, 0, 1 };
vtkm::cont::CellSetPermutation<vtkm::cont::CellSetExplicit<>, vtkm::cont::ArrayHandle<vtkm::Id>>
cellSet(vtkm::cont::make_ArrayHandle(permutationArray, 3),
originalCellSet,
originalCellSet.GetName());
vtkm::UInt8 expectedCellShapes[] = { vtkm::CELL_SHAPE_TETRA,
vtkm::CELL_SHAPE_HEXAHEDRON,
vtkm::CELL_SHAPE_PYRAMID };
vtkm::IdComponent expectedCellNumIndices[] = { 4, 8, 5 };
vtkm::Id expectedCellIndexSum[] = { 29, 28, 22 };
vtkm::Id numCells = cellSet.GetNumberOfCells();
TryCellConnectivity(cellSet,
vtkm::cont::make_ArrayHandle(expectedCellShapes, numCells),
vtkm::cont::make_ArrayHandle(expectedCellNumIndices, numCells),
vtkm::cont::make_ArrayHandle(expectedCellIndexSum, numCells));
// Permutation cell set does not support cell to point connectivity.
}
VTKM_CONT
void RunWholeCellSetInTests()
{
TryExplicitGrid();
TryCellSetPermutation();
}
int UnitTestWholeCellSetIn(int, char* [])
{
return vtkm::cont::testing::Testing::Run(RunWholeCellSetInTests);
}