Merge branch 'master' into extract-subset

This commit is contained in:
Patricia Kroll Fasel - 090207 2017-03-30 16:34:50 -06:00
commit 5b651172cf
38 changed files with 358 additions and 308 deletions

@ -31,6 +31,7 @@ add_subdirectory(hello_world)
add_subdirectory(isosurface) add_subdirectory(isosurface)
add_subdirectory(multi_backend) add_subdirectory(multi_backend)
add_subdirectory(streamline) add_subdirectory(streamline)
add_subdirectory(tetrahedra)
if(VTKm_ENABLE_RENDERING) if(VTKm_ENABLE_RENDERING)
add_subdirectory(rendering) add_subdirectory(rendering)
endif() endif()

@ -47,11 +47,6 @@ if(VTKm_OpenGL_FOUND AND VTKm_GLUT_FOUND)
target_link_libraries(TriangulateUniformGrid_SERIAL PRIVATE ${VTKm_LIBRARIES}) target_link_libraries(TriangulateUniformGrid_SERIAL PRIVATE ${VTKm_LIBRARIES})
target_compile_options(TriangulateUniformGrid_SERIAL PRIVATE ${VTKm_COMPILE_OPTIONS}) target_compile_options(TriangulateUniformGrid_SERIAL PRIVATE ${VTKm_COMPILE_OPTIONS})
add_executable(TriangulateStructured_SERIAL TriangulateStructured.cxx)
target_include_directories(TriangulateStructured_SERIAL PRIVATE ${VTKm_INCLUDE_DIRS})
target_link_libraries(TriangulateStructured_SERIAL PRIVATE ${VTKm_LIBRARIES})
target_compile_options(TriangulateStructured_SERIAL PRIVATE ${VTKm_COMPILE_OPTIONS})
if(VTKm_CUDA_FOUND) if(VTKm_CUDA_FOUND)
# Cuda compiles do not respect target_include_directories # Cuda compiles do not respect target_include_directories
cuda_include_directories(${VTKm_INCLUDE_DIRS}) cuda_include_directories(${VTKm_INCLUDE_DIRS})

@ -22,7 +22,7 @@
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL #define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif #endif
#include <vtkm/worklet/TetrahedralizeExplicitGrid.h> #include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/Math.h> #include <vtkm/Math.h>
#include <vtkm/cont/DataSet.h> #include <vtkm/cont/DataSet.h>
@ -50,7 +50,6 @@ namespace {
// Takes input uniform grid and outputs unstructured grid of tets // Takes input uniform grid and outputs unstructured grid of tets
static vtkm::cont::DataSet outDataSet; static vtkm::cont::DataSet outDataSet;
vtkm::Id numberOfInPoints;
// Point location of vertices from a CastAndCall but needs a static cast eventually // Point location of vertices from a CastAndCall but needs a static cast eventually
static vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float64, 3> > vertexArray; static vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float64, 3> > vertexArray;
@ -206,7 +205,7 @@ void displayCall()
// Need the actual vertex points from a static cast of the dynamic array but can't get it right // Need the actual vertex points from a static cast of the dynamic array but can't get it right
// So use cast and call on a functor that stores that dynamic array into static array we created // So use cast and call on a functor that stores that dynamic array into static array we created
vertexArray.Allocate(numberOfInPoints); vertexArray.Allocate(cellSet.GetNumberOfPoints());
vtkm::cont::CastAndCall(outDataSet.GetCoordinateSystem(), GetVertexArray()); vtkm::cont::CastAndCall(outDataSet.GetCoordinateSystem(), GetVertexArray());
// Draw the five tetrahedra belonging to each hexadron // Draw the five tetrahedra belonging to each hexadron
@ -302,17 +301,11 @@ int main(int argc, char* argv[])
vtkm::cont::CellSetExplicit<> inCellSet; vtkm::cont::CellSetExplicit<> inCellSet;
inDataSet.GetCellSet(0).CopyTo(inCellSet); inDataSet.GetCellSet(0).CopyTo(inCellSet);
numberOfInPoints = inCellSet.GetNumberOfPoints();
// Create the output dataset explicit cell set with same coordinate system
vtkm::cont::CellSetSingleType<> cellSet("cells");
outDataSet.AddCellSet(cellSet);
outDataSet.AddCoordinateSystem(inDataSet.GetCoordinateSystem(0));
// Convert cells to tetrahedra // Convert cells to tetrahedra
vtkm::worklet::TetrahedralizeFilterExplicitGrid<DeviceAdapter> vtkm::filter::Tetrahedralize tetrahedralize;
tetrahedralizeFilter(inDataSet, outDataSet); vtkm::filter::ResultDataSet result = tetrahedralize.Execute(inDataSet);
tetrahedralizeFilter.Run();
outDataSet = result.GetDataSet();
// Render the output dataset of tets // Render the output dataset of tets
lastx = lasty = 0; lastx = lasty = 0;

@ -22,7 +22,7 @@
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL #define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif #endif
#include <vtkm/worklet/TetrahedralizeUniformGrid.h> #include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/Math.h> #include <vtkm/Math.h>
#include <vtkm/cont/DataSet.h> #include <vtkm/cont/DataSet.h>
@ -48,10 +48,8 @@ typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
// Default size of the example // Default size of the example
static vtkm::Id3 dims(4,4,4); static vtkm::Id3 dims(4,4,4);
static vtkm::Id cellsToDisplay = 64; static vtkm::Id cellsToDisplay = 64;
static vtkm::Id numberOfInPoints;
// Takes input uniform grid and outputs unstructured grid of tets // Takes input uniform grid and outputs unstructured grid of tets
static vtkm::worklet::TetrahedralizeFilterUniformGrid<DeviceAdapter> *tetrahedralizeFilter;
static vtkm::cont::DataSet tetDataSet; static vtkm::cont::DataSet tetDataSet;
// Point location of vertices from a CastAndCall but needs a static cast eventually // Point location of vertices from a CastAndCall but needs a static cast eventually
@ -173,7 +171,7 @@ void displayCall()
// Need the actual vertex points from a static cast of the dynamic array but can't get it right // Need the actual vertex points from a static cast of the dynamic array but can't get it right
// So use cast and call on a functor that stores that dynamic array into static array we created // So use cast and call on a functor that stores that dynamic array into static array we created
vertexArray.Allocate(numberOfInPoints); vertexArray.Allocate(cellSet.GetNumberOfPoints());
vtkm::cont::CastAndCall(tetDataSet.GetCoordinateSystem(), GetVertexArray()); vtkm::cont::CastAndCall(tetDataSet.GetCoordinateSystem(), GetVertexArray());
// Draw the five tetrahedra belonging to each hexadron // Draw the five tetrahedra belonging to each hexadron
@ -289,18 +287,10 @@ int main(int argc, char* argv[])
// Create the input uniform cell set // Create the input uniform cell set
vtkm::cont::DataSet inDataSet = MakeTetrahedralizeTestDataSet(dims); vtkm::cont::DataSet inDataSet = MakeTetrahedralizeTestDataSet(dims);
// Set number of cells and vertices in input dataset vtkm::filter::Tetrahedralize tetrahedralize;
numberOfInPoints = (dims[0] + 1) * (dims[1] + 1) * (dims[2] + 1); vtkm::filter::ResultDataSet result = tetrahedralize.Execute(inDataSet);
// Create the output dataset explicit cell set with same coordinate system tetDataSet = result.GetDataSet();
vtkm::cont::CellSetSingleType<> cellSet("cells");
tetDataSet.AddCellSet(cellSet);
tetDataSet.AddCoordinateSystem(inDataSet.GetCoordinateSystem(0));
// Convert uniform hexahedra to tetrahedra
tetrahedralizeFilter = new vtkm::worklet::TetrahedralizeFilterUniformGrid<DeviceAdapter>
(inDataSet, tetDataSet);
tetrahedralizeFilter->Run();
// Render the output dataset of tets // Render the output dataset of tets
lastx = lasty = 0; lastx = lasty = 0;
@ -318,7 +308,6 @@ int main(int argc, char* argv[])
glutMouseFunc(mouseCall); glutMouseFunc(mouseCall);
glutMainLoop(); glutMainLoop();
delete tetrahedralizeFilter;
tetDataSet.Clear(); tetDataSet.Clear();
vertexArray.ReleaseResources(); vertexArray.ReleaseResources();
return 0; return 0;

@ -22,7 +22,7 @@
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL #define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif #endif
#include <vtkm/worklet/TetrahedralizeExplicitGrid.h> #include <vtkm/filter/Triangulate.h>
#include <vtkm/cont/CellSetExplicit.h> #include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/DataSet.h> #include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderExplicit.h> #include <vtkm/cont/DataSetBuilderExplicit.h>
@ -46,7 +46,6 @@ typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
namespace { namespace {
// Takes input uniform grid and outputs unstructured grid of triangles // Takes input uniform grid and outputs unstructured grid of triangles
static vtkm::worklet::TetrahedralizeFilterExplicitGrid<DeviceAdapter> *tetrahedralizeFilter;
static vtkm::cont::DataSet outDataSet; static vtkm::cont::DataSet outDataSet;
static vtkm::Id numberOfInPoints; static vtkm::Id numberOfInPoints;
@ -225,15 +224,10 @@ int main(int argc, char* argv[])
numberOfInPoints = inCellSet.GetNumberOfPoints(); numberOfInPoints = inCellSet.GetNumberOfPoints();
// Create the output dataset explicit cell set with same coordinate system
vtkm::cont::CellSetSingleType<> cellSet("cells");;
outDataSet.AddCellSet(cellSet);
outDataSet.AddCoordinateSystem(inDataSet.GetCoordinateSystem(0));
// Convert 2D explicit cells to triangles // Convert 2D explicit cells to triangles
tetrahedralizeFilter = new vtkm::worklet::TetrahedralizeFilterExplicitGrid<DeviceAdapter> vtkm::filter::Triangulate triangulate;
(inDataSet, outDataSet); vtkm::filter::ResultDataSet result = triangulate.Execute(inDataSet);
tetrahedralizeFilter->Run(); outDataSet = result.GetDataSet();
// Render the output dataset of tets // Render the output dataset of tets
glutInit(&argc, argv); glutInit(&argc, argv);
@ -248,7 +242,6 @@ int main(int argc, char* argv[])
glutDisplayFunc(displayCall); glutDisplayFunc(displayCall);
glutMainLoop(); glutMainLoop();
delete tetrahedralizeFilter;
outDataSet.Clear(); outDataSet.Clear();
vertexArray.ReleaseResources(); vertexArray.ReleaseResources();
return 0; return 0;

@ -22,7 +22,7 @@
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL #define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif #endif
#include <vtkm/worklet/TetrahedralizeUniformGrid.h> #include <vtkm/filter/Triangulate.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/Math.h> #include <vtkm/Math.h>
#include <vtkm/cont/DataSet.h> #include <vtkm/cont/DataSet.h>
@ -46,11 +46,9 @@ typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
// Default size of the example // Default size of the example
static vtkm::Id2 dims(4,4); static vtkm::Id2 dims(4,4);
static vtkm::Id cellsToDisplay = 16; static vtkm::Id cellsToDisplay = 16;
static vtkm::Id numberOfInPoints;
// Takes input uniform grid and outputs unstructured grid of triangles // Takes input uniform grid and outputs unstructured grid of triangles
static vtkm::worklet::TetrahedralizeFilterUniformGrid<DeviceAdapter> *tetrahedralizeFilter; static vtkm::cont::DataSet triDataSet;
static vtkm::cont::DataSet tetDataSet;
// Point location of vertices from a CastAndCall but needs a static cast eventually // Point location of vertices from a CastAndCall but needs a static cast eventually
static vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float64, 3> > vertexArray; static vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Float64, 3> > vertexArray;
@ -68,7 +66,7 @@ vtkm::cont::DataSet MakeTriangulateTestDataSet(vtkm::Id2 dim)
const vtkm::Vec<vtkm::Float32, 3> spacing = vtkm::make_Vec( const vtkm::Vec<vtkm::Float32, 3> spacing = vtkm::make_Vec(
1.0f/static_cast<vtkm::Float32>(dim[0]), 1.0f/static_cast<vtkm::Float32>(dim[0]),
1.0f/static_cast<vtkm::Float32>(dim[1]), 1.0f/static_cast<vtkm::Float32>(dim[1]),
1.0f/static_cast<vtkm::Float32>(dim[2])); 0.0f);
// Generate coordinate system // Generate coordinate system
vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(vdims, origin, spacing); vtkm::cont::ArrayHandleUniformPointCoordinates coordinates(vdims, origin, spacing);
@ -131,12 +129,12 @@ void displayCall()
// Get the cellset, coordinate system and coordinate data // Get the cellset, coordinate system and coordinate data
vtkm::cont::CellSetSingleType<> cellSet; vtkm::cont::CellSetSingleType<> cellSet;
tetDataSet.GetCellSet(0).CopyTo(cellSet); triDataSet.GetCellSet(0).CopyTo(cellSet);
// Need the actual vertex points from a static cast of the dynamic array but can't get it right // Need the actual vertex points from a static cast of the dynamic array but can't get it right
// So use cast and call on a functor that stores that dynamic array into static array we created // So use cast and call on a functor that stores that dynamic array into static array we created
vertexArray.Allocate(numberOfInPoints); vertexArray.Allocate(cellSet.GetNumberOfPoints());
vtkm::cont::CastAndCall(tetDataSet.GetCoordinateSystem(), GetVertexArray()); vtkm::cont::CastAndCall(triDataSet.GetCoordinateSystem(), GetVertexArray());
// Draw the two triangles belonging to each quad // Draw the two triangles belonging to each quad
vtkm::Id triangle = 0; vtkm::Id triangle = 0;
@ -178,7 +176,7 @@ void displayCall()
glFlush(); glFlush();
} }
// Tetrahedralize and render uniform grid example // Triangulate and render uniform grid example
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
std::cout << "TrianguleUniformGrid Example" << std::endl; std::cout << "TrianguleUniformGrid Example" << std::endl;
@ -195,20 +193,15 @@ int main(int argc, char* argv[])
{ {
cellsToDisplay = atoi(argv[3]); cellsToDisplay = atoi(argv[3]);
} }
numberOfInPoints = (dims[0] + 1) * (dims[1] + 1);
// Create the input uniform cell set // Create the input uniform cell set
vtkm::cont::DataSet inDataSet = MakeTriangulateTestDataSet(dims); vtkm::cont::DataSet inDataSet = MakeTriangulateTestDataSet(dims);
// Create the output dataset explicit cell set with same coordinate system // Convert uniform quad to triangle
vtkm::cont::CellSetSingleType<> cellSet("cells"); vtkm::filter::Triangulate triangulate;
tetDataSet.AddCellSet(cellSet); vtkm::filter::ResultDataSet result = triangulate.Execute(inDataSet);
tetDataSet.AddCoordinateSystem(inDataSet.GetCoordinateSystem(0));
// Convert uniform hexahedra to tetrahedra triDataSet = result.GetDataSet();
tetrahedralizeFilter = new vtkm::worklet::TetrahedralizeFilterUniformGrid<DeviceAdapter>
(inDataSet, tetDataSet);
tetrahedralizeFilter->Run();
// Render the output dataset of tets // Render the output dataset of tets
glutInit(&argc, argv); glutInit(&argc, argv);
@ -223,8 +216,7 @@ int main(int argc, char* argv[])
glutDisplayFunc(displayCall); glutDisplayFunc(displayCall);
glutMainLoop(); glutMainLoop();
delete tetrahedralizeFilter; triDataSet.Clear();
tetDataSet.Clear();
vertexArray.ReleaseResources(); vertexArray.ReleaseResources();
return 0; return 0;
} }

@ -31,7 +31,6 @@ set(headers
TransportTagKeyedValuesInOut.h TransportTagKeyedValuesInOut.h
TransportTagKeyedValuesOut.h TransportTagKeyedValuesOut.h
TransportTagKeysIn.h TransportTagKeysIn.h
TransportTagReducedValuesIn.h
TransportTagTopologyFieldIn.h TransportTagTopologyFieldIn.h
TransportTagWholeArrayIn.h TransportTagWholeArrayIn.h
TransportTagWholeArrayInOut.h TransportTagWholeArrayInOut.h

@ -48,13 +48,11 @@ struct Transport<vtkm::cont::arg::TransportTagArrayIn, ContObjectType, Device>
template<typename InputDomainType> template<typename InputDomainType>
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const InputDomainType &inputDomain, const InputDomainType &vtkmNotUsed(inputDomain),
vtkm::Id) const vtkm::Id inputRange,
vtkm::Id vtkmNotUsed(outputRange)) const
{ {
// This transport expects the input domain to be an array handle. if (object.GetNumberOfValues() != inputRange)
VTKM_IS_ARRAY_HANDLE(InputDomainType);
if (object.GetNumberOfValues() != inputDomain.GetNumberOfValues())
{ {
throw vtkm::cont::ErrorBadValue( throw vtkm::cont::ErrorBadValue(
"Input array to worklet invocation the wrong size."); "Input array to worklet invocation the wrong size.");

@ -51,13 +51,14 @@ struct Transport<vtkm::cont::arg::TransportTagArrayInOut, ContObjectType, Device
template<typename InputDomainType> template<typename InputDomainType>
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType object, ExecObjectType operator()(ContObjectType object,
const InputDomainType &, const InputDomainType &vtkmNotUsed(inputDomain),
vtkm::Id size) const vtkm::Id vtkmNotUsed(inputRange),
vtkm::Id outputRange) const
{ {
if (object.GetNumberOfValues() != size) if (object.GetNumberOfValues() != outputRange)
{ {
throw vtkm::cont::ErrorBadValue( throw vtkm::cont::ErrorBadValue(
"Input array to worklet invocation the wrong size."); "Input/output array to worklet invocation the wrong size.");
} }
return object.PrepareForInPlace(Device()); return object.PrepareForInPlace(Device());

@ -50,10 +50,11 @@ struct Transport<vtkm::cont::arg::TransportTagArrayOut, ContObjectType, Device>
template<typename InputDomainType> template<typename InputDomainType>
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType object, ExecObjectType operator()(ContObjectType object,
const InputDomainType &, const InputDomainType &vtkmNotUsed(inputDomain),
vtkm::Id size) const vtkm::Id vtkmNotUsed(inputRange),
vtkm::Id outputRange) const
{ {
return object.PrepareForOutput(size, Device()); return object.PrepareForOutput(outputRange, Device());
} }
}; };

@ -56,6 +56,7 @@ struct Transport<
ExecObjectType operator()( ExecObjectType operator()(
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic> array, vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic> array,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
// Note: we ignore the size of the domain because the randomly accessed // Note: we ignore the size of the domain because the randomly accessed

@ -55,6 +55,7 @@ struct Transport<vtkm::cont::arg::TransportTagCellSetIn<FromTopology,ToTopology>
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
return object.PrepareForInput(Device(), return object.PrepareForInput(Device(),

@ -54,6 +54,7 @@ struct Transport<vtkm::cont::arg::TransportTagExecObject,ContObjectType,Device>
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
return object; return object;

@ -1,45 +0,0 @@
//============================================================================
// 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 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 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_arg_TransportTagReducedValuesIn_h
#define vtk_m_cont_arg_TransportTagReducedValuesIn_h
#include <vtkm/cont/arg/Transport.h>
namespace vtkm {
namespace cont {
namespace arg {
/// \brief \c Transport tag for input values in a reduce by key.
///
/// \c TransportTagReducedValuesIn is a tag used with the \c Transport class to
/// transport \c ArrayHandle objects for input values that correspond to arrays
/// of reduced values. The values are passed 1-to-1 to the worklet invocations.
///
struct TransportTagReducedValuesIn { };
// Specialization of Transport class for TransportTagReducedValuesIn is
// implemented in vtkm/worklet/Keys.h. That class is not accessible from here
// due to VTK-m package dependencies.
}
}
}
#endif //vtk_m_cont_arg_TransportTagReducedValuesIn_h

@ -88,6 +88,7 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const vtkm::cont::CellSet &inputDomain, const vtkm::cont::CellSet &inputDomain,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
if (object.GetNumberOfValues() != if (object.GetNumberOfValues() !=

@ -60,6 +60,7 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType array, ExecObjectType operator()(ContObjectType array,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
// Note: we ignore the size of the domain because the randomly accessed // Note: we ignore the size of the domain because the randomly accessed

@ -62,6 +62,7 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType array, ExecObjectType operator()(ContObjectType array,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
// Note: we ignore the size of the domain because the randomly accessed // Note: we ignore the size of the domain because the randomly accessed

@ -62,6 +62,7 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType array, ExecObjectType operator()(ContObjectType array,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
// Note: we ignore the size of the domain because the randomly accessed // Note: we ignore the size of the domain because the randomly accessed

@ -70,7 +70,7 @@ struct TryArrayInType
transport; transport;
TestKernel<PortalType> kernel; TestKernel<PortalType> kernel;
kernel.Portal = transport(handle, handle, ARRAY_SIZE); kernel.Portal = transport(handle, handle, ARRAY_SIZE, ARRAY_SIZE);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE);
} }

@ -68,7 +68,7 @@ struct TryArrayInOutType
transport; transport;
TestKernel<PortalType> kernel; TestKernel<PortalType> kernel;
kernel.Portal = transport(handle, handle, ARRAY_SIZE); kernel.Portal = transport(handle, handle, ARRAY_SIZE, ARRAY_SIZE);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE);

@ -64,6 +64,7 @@ struct TryArrayOutType
TestKernel<PortalType> kernel; TestKernel<PortalType> kernel;
kernel.Portal = transport(handle, kernel.Portal = transport(handle,
vtkm::cont::ArrayHandleIndex(ARRAY_SIZE), vtkm::cont::ArrayHandleIndex(ARRAY_SIZE),
ARRAY_SIZE,
ARRAY_SIZE); ARRAY_SIZE);
VTKM_TEST_ASSERT(handle.GetNumberOfValues() == ARRAY_SIZE, VTKM_TEST_ASSERT(handle.GetNumberOfValues() == ARRAY_SIZE,

@ -84,7 +84,7 @@ void TransportWholeCellSetIn(Device)
transport; transport;
TestKernel<ExecObjectType> kernel; TestKernel<ExecObjectType> kernel;
kernel.CellSet = transport(contObject, nullptr, 1); kernel.CellSet = transport(contObject, nullptr, 1, 1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1);
} }

@ -61,7 +61,7 @@ void TryExecObjectTransport(Device)
transport; transport;
TestKernel kernel; TestKernel kernel;
kernel.Object = transport(contObject, nullptr, 1); kernel.Object = transport(contObject, nullptr, 1, 1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, 1);
} }

@ -131,7 +131,7 @@ struct TryWholeArrayType
std::cout << "Check Transport WholeArrayOut" << std::endl; std::cout << "Check Transport WholeArrayOut" << std::endl;
TestOutKernel<typename OutTransportType::ExecObjectType> outKernel; TestOutKernel<typename OutTransportType::ExecObjectType> outKernel;
outKernel.Portal = OutTransportType()(array, nullptr, -1); outKernel.Portal = OutTransportType()(array, nullptr, -1, -1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(outKernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(outKernel, ARRAY_SIZE);
@ -139,13 +139,13 @@ struct TryWholeArrayType
std::cout << "Check Transport WholeArrayIn" << std::endl; std::cout << "Check Transport WholeArrayIn" << std::endl;
TestInKernel<typename InTransportType::ExecObjectType> inKernel; TestInKernel<typename InTransportType::ExecObjectType> inKernel;
inKernel.Portal = InTransportType()(array, nullptr, -1); inKernel.Portal = InTransportType()(array, nullptr, -1, -1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(inKernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(inKernel, ARRAY_SIZE);
std::cout << "Check Transport WholeArrayInOut" << std::endl; std::cout << "Check Transport WholeArrayInOut" << std::endl;
TestInOutKernel<typename InOutTransportType::ExecObjectType> inOutKernel; TestInOutKernel<typename InOutTransportType::ExecObjectType> inOutKernel;
inOutKernel.Portal = InOutTransportType()(array, nullptr, -1); inOutKernel.Portal = InOutTransportType()(array, nullptr, -1, -1);
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(inOutKernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(inOutKernel, ARRAY_SIZE);
@ -180,7 +180,7 @@ struct TryAtomicArrayType
std::cout << "Check Transport AtomicArray" << std::endl; std::cout << "Check Transport AtomicArray" << std::endl;
TestAtomicKernel<typename TransportType::ExecObjectType> TestAtomicKernel<typename TransportType::ExecObjectType>
kernel(TransportType()(array, nullptr, -1)); kernel(TransportType()(array, nullptr, -1, -1));
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE); vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(kernel, ARRAY_SIZE);

@ -18,9 +18,33 @@
// this software. // this software.
//============================================================================ //============================================================================
#include <vtkm/worklet/ScatterCounting.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
namespace
{
template<typename DeviceAdapter>
class DeduceCellSet
{
mutable vtkm::worklet::Tetrahedralize Worklet;
vtkm::cont::CellSetSingleType<> &OutCellSet;
public:
DeduceCellSet(vtkm::worklet::Tetrahedralize worklet,
vtkm::cont::CellSetSingleType<>& outCellSet) :
Worklet(worklet),
OutCellSet(outCellSet)
{}
template<typename CellSetType>
void operator()(const CellSetType& cellset ) const
{
this->OutCellSet = Worklet.Run(cellset, DeviceAdapter());
}
};
}
namespace vtkm { namespace vtkm {
namespace filter { namespace filter {
@ -38,27 +62,17 @@ template<typename DerivedPolicy,
inline VTKM_CONT inline VTKM_CONT
vtkm::filter::ResultDataSet Tetrahedralize::DoExecute( vtkm::filter::ResultDataSet Tetrahedralize::DoExecute(
const vtkm::cont::DataSet& input, const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&, const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const DeviceAdapter& device) const DeviceAdapter&)
{ {
typedef vtkm::cont::CellSetStructured<3> CellSetStructuredType;
typedef vtkm::cont::CellSetExplicit<> CellSetExplicitType;
const vtkm::cont::DynamicCellSet& cells = const vtkm::cont::DynamicCellSet& cells =
input.GetCellSet(this->GetActiveCellSetIndex()); input.GetCellSet(this->GetActiveCellSetIndex());
vtkm::cont::CellSetSingleType<> outCellSet; vtkm::cont::CellSetSingleType<> outCellSet;
DeduceCellSet<DeviceAdapter> tetrahedralize(this->Worklet, outCellSet);
if (cells.IsType<CellSetStructuredType>()) vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(cells, policy),
{ tetrahedralize);
outCellSet = this->Worklet.Run(cells.Cast<CellSetStructuredType>(),
device);
}
else
{
outCellSet = this->Worklet.Run(cells.Cast<CellSetExplicitType>(),
device);
}
// create the output dataset // create the output dataset
vtkm::cont::DataSet output; vtkm::cont::DataSet output;

@ -18,9 +18,33 @@
// this software. // this software.
//============================================================================ //============================================================================
#include <vtkm/worklet/ScatterCounting.h>
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
namespace
{
template<typename DeviceAdapter>
class DeduceCellSet
{
mutable vtkm::worklet::Triangulate Worklet;
vtkm::cont::CellSetSingleType<> &OutCellSet;
public:
DeduceCellSet(vtkm::worklet::Triangulate worklet,
vtkm::cont::CellSetSingleType<>& outCellSet) :
Worklet(worklet),
OutCellSet(outCellSet)
{}
template<typename CellSetType>
void operator()(const CellSetType& cellset ) const
{
this->OutCellSet = Worklet.Run(cellset, DeviceAdapter());
}
};
}
namespace vtkm { namespace vtkm {
namespace filter { namespace filter {
@ -38,27 +62,18 @@ template<typename DerivedPolicy,
inline VTKM_CONT inline VTKM_CONT
vtkm::filter::ResultDataSet Triangulate::DoExecute( vtkm::filter::ResultDataSet Triangulate::DoExecute(
const vtkm::cont::DataSet& input, const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&, const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const DeviceAdapter& device) const DeviceAdapter&)
{ {
typedef vtkm::cont::CellSetStructured<2> CellSetStructuredType;
typedef vtkm::cont::CellSetExplicit<> CellSetExplicitType;
const vtkm::cont::DynamicCellSet& cells = const vtkm::cont::DynamicCellSet& cells =
input.GetCellSet(this->GetActiveCellSetIndex()); input.GetCellSet(this->GetActiveCellSetIndex());
vtkm::cont::CellSetSingleType<> outCellSet; vtkm::cont::CellSetSingleType<> outCellSet;
DeduceCellSet<DeviceAdapter> triangulate(this->Worklet, outCellSet);
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicy(cells, policy),
triangulate);
if (cells.IsType<CellSetStructuredType>())
{
outCellSet = this->Worklet.Run(cells.Cast<CellSetStructuredType>(),
device);
}
else
{
outCellSet = this->Worklet.Run(cells.Cast<CellSetExplicitType>(),
device);
}
// create the output dataset // create the output dataset
vtkm::cont::DataSet output; vtkm::cont::DataSet output;

@ -364,7 +364,7 @@ void TestMarchingCubesCustomPolicy()
vtkm::cont::CoordinateSystem coords = outputData.GetCoordinateSystem(); vtkm::cont::CoordinateSystem coords = outputData.GetCoordinateSystem();
VTKM_TEST_ASSERT(coords.GetData().GetNumberOfValues() == 414, VTKM_TEST_ASSERT(coords.GetData().GetNumberOfValues() == (414*4),
"Should have some coordinates"); "Should have some coordinates");
} }

@ -48,6 +48,15 @@ public:
"Wrong result for Tetrahedralize"); "Wrong result for Tetrahedralize");
VTKM_TEST_ASSERT(test_equal(output.GetField("pointvar").GetData().GetNumberOfValues(), 18), VTKM_TEST_ASSERT(test_equal(output.GetField("pointvar").GetData().GetNumberOfValues(), 18),
"Wrong number of points for Tetrahedralize"); "Wrong number of points for Tetrahedralize");
vtkm::cont::ArrayHandle<vtkm::Float32> outData =
output.GetField("cellvar").GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Float32> >();
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(5) == 100.2f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(6) == 100.2f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(7) == 100.2f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(8) == 100.2f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(9) == 100.2f, "Wrong cell field data");
} }
void TestExplicit() const void TestExplicit() const
@ -68,6 +77,15 @@ public:
"Wrong result for Tetrahedralize"); "Wrong result for Tetrahedralize");
VTKM_TEST_ASSERT(test_equal(output.GetField("pointvar").GetData().GetNumberOfValues(), 11), VTKM_TEST_ASSERT(test_equal(output.GetField("pointvar").GetData().GetNumberOfValues(), 11),
"Wrong number of points for Tetrahedralize"); "Wrong number of points for Tetrahedralize");
vtkm::cont::ArrayHandle<vtkm::Float32> outData =
output.GetField("cellvar").GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Float32> >();
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(5) == 110.f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(6) == 110.f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(8) == 130.5f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(9) == 130.5f, "Wrong cell field data");
VTKM_TEST_ASSERT(outData.GetPortalConstControl().Get(10) == 130.5f, "Wrong cell field data");
} }
void operator()() const void operator()() const

@ -274,6 +274,7 @@ private:
ExecObjectParameters execObjectParameters = ExecObjectParameters execObjectParameters =
parameters.StaticTransformCont(TransportFunctorType( parameters.StaticTransformCont(TransportFunctorType(
invocation.GetInputDomain(), invocation.GetInputDomain(),
inputRange,
outputRange)); outputRange));
// Get the arrays used for scattering input to output. // Get the arrays used for scattering input to output.

@ -34,7 +34,6 @@
#include <vtkm/cont/arg/TransportTagKeyedValuesInOut.h> #include <vtkm/cont/arg/TransportTagKeyedValuesInOut.h>
#include <vtkm/cont/arg/TransportTagKeyedValuesOut.h> #include <vtkm/cont/arg/TransportTagKeyedValuesOut.h>
#include <vtkm/cont/arg/TransportTagKeysIn.h> #include <vtkm/cont/arg/TransportTagKeysIn.h>
#include <vtkm/cont/arg/TransportTagReducedValuesIn.h>
#include <vtkm/cont/arg/TypeCheckTagKeys.h> #include <vtkm/cont/arg/TypeCheckTagKeys.h>
#include <vtkm/BinaryOperators.h> #include <vtkm/BinaryOperators.h>
@ -152,6 +151,12 @@ public:
(this->Counts == other.Counts)); (this->Counts == other.Counts));
} }
VTKM_CONT
bool operator!=(const vtkm::worklet::Keys<KeyType> &other) const
{
return !(*this == other);
}
private: private:
KeyArrayHandleType UniqueKeys; KeyArrayHandleType UniqueKeys;
vtkm::cont::ArrayHandle<vtkm::Id> SortedValuesMap; vtkm::cont::ArrayHandle<vtkm::Id> SortedValuesMap;
@ -221,9 +226,14 @@ struct Transport<vtkm::cont::arg::TransportTagKeysIn,
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const ContObjectType &inputDomain, const ContObjectType &inputDomain,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
VTKM_ASSERT(object == inputDomain); if (object != inputDomain)
{
throw vtkm::cont::ErrorBadValue(
"A Keys object must be the input domain.");
}
return object.PrepareForInput(Device()); return object.PrepareForInput(Device());
} }
@ -234,6 +244,7 @@ struct Transport<vtkm::cont::arg::TransportTagKeysIn,
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &, ExecObjectType operator()(const ContObjectType &,
const InputDomainType &, const InputDomainType &,
vtkm::Id,
vtkm::Id) const = delete; vtkm::Id) const = delete;
}; };
@ -258,9 +269,13 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(const ContObjectType &object, ExecObjectType operator()(const ContObjectType &object,
const vtkm::worklet::Keys<KeyType> &keys, const vtkm::worklet::Keys<KeyType> &keys,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
VTKM_ASSERT(object.GetNumberOfValues() == keys.GetNumberOfValues()); if (object.GetNumberOfValues() != keys.GetNumberOfValues())
{
throw vtkm::cont::ErrorBadValue("Input values array is wrong size.");
}
PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object); PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
GroupedArrayType groupedArray(permutedArray, keys.GetOffsets()); GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
@ -294,9 +309,14 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType object, ExecObjectType operator()(ContObjectType object,
const vtkm::worklet::Keys<KeyType> &keys, const vtkm::worklet::Keys<KeyType> &keys,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
VTKM_ASSERT(object.GetNumberOfValues() == keys.GetNumberOfValues()); if (object.GetNumberOfValues() != keys.GetNumberOfValues())
{
throw vtkm::cont::ErrorBadValue(
"Input/output values array is wrong size.");
}
PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object); PermutedArrayType permutedArray(keys.GetSortedValuesMap(), object);
GroupedArrayType groupedArray(permutedArray, keys.GetOffsets()); GroupedArrayType groupedArray(permutedArray, keys.GetOffsets());
@ -330,6 +350,7 @@ struct Transport<
VTKM_CONT VTKM_CONT
ExecObjectType operator()(ContObjectType object, ExecObjectType operator()(ContObjectType object,
const vtkm::worklet::Keys<KeyType> &keys, const vtkm::worklet::Keys<KeyType> &keys,
vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
// The PrepareForOutput for ArrayHandleGroupVecVariable and // The PrepareForOutput for ArrayHandleGroupVecVariable and
@ -348,31 +369,6 @@ struct Transport<
} }
}; };
template<typename ContObjectType, typename Device>
struct Transport<
vtkm::cont::arg::TransportTagReducedValuesIn, ContObjectType, Device>
{
VTKM_IS_ARRAY_HANDLE(ContObjectType);
typedef typename ContObjectType::template ExecutionTypes<Device>::PortalConst
ExecObjectType;
template<typename KeyType>
VTKM_CONT
ExecObjectType operator()(const ContObjectType &object,
const vtkm::worklet::Keys<KeyType> &inputDomain,
vtkm::Id) const
{
if (object.GetNumberOfValues() != inputDomain.GetInputRange())
{
throw vtkm::cont::ErrorBadValue(
"Input array to worklet invocation the wrong size.");
}
return object.PrepareForInput(Device());
}
};
} }
} }
} // namespace vtkm::cont::arg } // namespace vtkm::cont::arg

@ -22,6 +22,7 @@
#define vtk_m_worklet_MarchingCubes_h #define vtk_m_worklet_MarchingCubes_h
#include <vtkm/VectorAnalysis.h> #include <vtkm/VectorAnalysis.h>
#include <vtkm/BinaryPredicates.h>
#include <vtkm/exec/CellDerivative.h> #include <vtkm/exec/CellDerivative.h>
#include <vtkm/exec/ParametricCoordinates.h> #include <vtkm/exec/ParametricCoordinates.h>
@ -437,6 +438,71 @@ struct FirstValueSame
} }
}; };
// ---------------------------------------------------------------------------
struct MultiContourLess
{
template<typename T>
VTKM_EXEC_CONT bool operator()(const T& a, const T& b) const
{
return a < b;
}
template<typename T, typename U>
VTKM_EXEC_CONT bool operator()(const vtkm::Pair<T,U>& a,
const vtkm::Pair<T,U>& b) const
{
return (a.first < b.first) || (!(b.first < a.first) && (a.second < b.second));
}
template<typename T, typename U>
VTKM_EXEC_CONT bool operator()(const vtkm::internal::ArrayPortalValueReference<T>& a,
const U& b) const
{
U&& t = static_cast<U>(a);
return t < b;
}
};
// ---------------------------------------------------------------------------
template<typename KeyType, typename KeyStorage,
typename ValueType, typename ValueStorage,
typename DeviceAdapterTag>
vtkm::cont::ArrayHandle<KeyType, KeyStorage>
MergeDuplicates(const vtkm::cont::ArrayHandle<KeyType, KeyStorage>& input_keys,
vtkm::cont::ArrayHandle<ValueType, ValueStorage> values,
vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
DeviceAdapterTag)
{
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>;
//1. Copy the input keys as we need both a sorted & unique version and
// the original version to
vtkm::cont::ArrayHandle<KeyType, KeyStorage> keys;
Algorithm::Copy(input_keys, keys);
//2. Sort by key, making duplicate ids be adjacent so they are eligable
// to be removed by unique
Algorithm::SortByKey(keys, values, marchingcubes::MultiContourLess());
//3. lastly we need to do a unique by key, but since vtkm doesn't
// offer that feature, we use a zip handle.
// We use a custom comparison operator as we only want to compare
// the keys
auto zipped_kv = vtkm::cont::make_ArrayHandleZip(keys, values);
Algorithm::Unique( zipped_kv, marchingcubes::FirstValueSame());
//4. LowerBounds generates the output cell connections. It does this by
// finding for each interpolationId where it would be inserted in the
// sorted & unique subset, which generates an index value aka the lookup
// value.
//
Algorithm::LowerBounds(keys, input_keys, connectivity, marchingcubes::MultiContourLess());
//5. We need to return the sorted-unique keys as the caller will need
// to hold onto it for interpolation of other fields
return keys;
}
} }
/// \brief Compute the isosurface for a uniform grid data set /// \brief Compute the isosurface for a uniform grid data set
@ -570,19 +636,19 @@ vtkm::cont::CellSetSingleType< >
using vtkm::worklet::marchingcubes::ClassifyCell; using vtkm::worklet::marchingcubes::ClassifyCell;
// Setup the Dispatcher Typedefs // Setup the Dispatcher Typedefs
typedef typename vtkm::worklet::DispatcherMapTopology< using ClassifyDispatcher = typename vtkm::worklet::DispatcherMapTopology<
ClassifyCell<ValueType>, ClassifyCell<ValueType>,
DeviceAdapter DeviceAdapter
> ClassifyDispatcher; >;
typedef typename vtkm::worklet::DispatcherMapTopology< using GenerateDispatcher = typename vtkm::worklet::DispatcherMapTopology<
EdgeWeightGenerate<ValueType, EdgeWeightGenerate<ValueType,
NormalType, NormalType,
StorageTagNormals, StorageTagNormals,
DeviceAdapter DeviceAdapter
>, >,
DeviceAdapter DeviceAdapter
> GenerateDispatcher; >;
vtkm::cont::ArrayHandle<ValueType> isoValuesHandle = vtkm::cont::ArrayHandle<ValueType> isoValuesHandle =
vtkm::cont::make_ArrayHandle(isovalues, numIsoValues); vtkm::cont::make_ArrayHandle(isovalues, numIsoValues);
@ -632,106 +698,84 @@ vtkm::cont::CellSetSingleType< >
coordinateSystem coordinateSystem
); );
if(numIsoValues <= 1) if(numIsoValues <= 1 || !this->MergeDuplicatePoints)
{ //release memory early that we are not going to need again { //release memory early that we are not going to need again
contourIds.ReleaseResources(); contourIds.ReleaseResources();
} }
// Now that we have the edge interpolation finished we can generate the // Now that we have the edge interpolation finished we can generate the
//following: // coordinates, connectivity and resolve duplicate points.
//1. Coordinates ( with option to do point merging ) // Given that normals, and point merging are optional it generates the
// following permutations that we need to support
// //
//[0] 1 iso-contour
//[1] 1 iso-contour + point merging
//[2] 1 iso-contour + point merging + normals
//[3] 1 iso-contour + normals
//[4] 2+ iso-contour
//[5] 2+ iso-contour + point merging
//[6] 2+ iso-contour + point merging + normals
//[7] 2+ iso-contour + normals
// //
typedef vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter> Algorithm; // [0], [3], [4], and [7] are easy to implement as they require zero logic
// other than simple connectivity generation. The challenge is the other
// 4 options
vtkm::cont::DataSet output; vtkm::cont::DataSet output;
vtkm::cont::ArrayHandle< vtkm::Id > connectivity; vtkm::cont::ArrayHandle< vtkm::Id > connectivity;
typedef vtkm::cont::ArrayHandle< vtkm::Id2 > Id2HandleType;
typedef vtkm::cont::ArrayHandle< vtkm::UInt8 > ContourIdHandleType;
typedef vtkm::cont::ArrayHandle<vtkm::FloatDefault> WeightHandleType;
if(this->MergeDuplicatePoints) if(this->MergeDuplicatePoints)
{ {
//Do merge duplicate points we need to do the following: // In all the below cases you will notice that only interpolation ids
//1. Copy the interpolation Ids // are updated. That is because MergeDuplicates will internally update
Id2HandleType uniqueIds; // the InterpolationWeights and normals arrays to be the correct for the
Algorithm::Copy(this->InterpolationIds, uniqueIds); // output. But for InterpolationIds we need to do it manually once done
if(withNormals && numIsoValues == 1)
if(withNormals)
{ {
typedef vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3>, StorageTagNormals > NormalHandlType; auto&& result = marchingcubes::MergeDuplicates(
typedef vtkm::cont::ArrayHandleZip<WeightHandleType, NormalHandlType> KeyType; this->InterpolationIds, //keys
KeyType keys = vtkm::cont::make_ArrayHandleZip(this->InterpolationWeights, normals); vtkm::cont::make_ArrayHandleZip(this->InterpolationWeights, normals), //values
connectivity,
//2. now we need to do a sort by key, making duplicate ids be adjacent DeviceAdapter() );
if(numIsoValues > 1) this->InterpolationIds = result;
}
else if(withNormals && numIsoValues > 1)
{ {
vtkm::cont::ArrayHandleZip< auto&& result = marchingcubes::MergeDuplicates(
Id2HandleType, ContourIdHandleType> uniqueIdsWithContourId = vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationIds), //keys
vtkm::cont::make_ArrayHandleZip(uniqueIds, contourIds); vtkm::cont::make_ArrayHandleZip(this->InterpolationWeights, normals), //values
Algorithm::SortByKey(uniqueIdsWithContourId, keys); connectivity,
DeviceAdapter() );
this->InterpolationIds = result.GetStorage().GetSecondArray();
} }
else else if(!withNormals && numIsoValues == 1)
{ {
Algorithm::SortByKey(uniqueIds, keys); auto&& result = marchingcubes::MergeDuplicates(
this->InterpolationIds, //keys
this->InterpolationWeights, //values
connectivity,
DeviceAdapter() );
this->InterpolationIds = result;
} }
else if(!withNormals && numIsoValues >= 1)
//3. lastly we need to do a unique by key, but since vtkm doesn't
// offer that feature, we use a zip handle.
// We need to use a custom comparison operator as we only want to compare
// the id2 which is the first entry in the zip pair
vtkm::cont::ArrayHandleZip<Id2HandleType, KeyType> zipped =
vtkm::cont::make_ArrayHandleZip(uniqueIds,keys);
Algorithm::Unique( zipped, marchingcubes::FirstValueSame());
}
else
{ {
//2. now we need to do a sort by key, making duplicate ids be adjacent auto&& result = marchingcubes::MergeDuplicates(
if(numIsoValues > 1) vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationIds), //keys
{ this->InterpolationWeights, //values
vtkm::cont::ArrayHandleZip< connectivity,
Id2HandleType, ContourIdHandleType> uniqueIdsWithContourId = DeviceAdapter() );
vtkm::cont::make_ArrayHandleZip(uniqueIds, contourIds); this->InterpolationIds = result.GetStorage().GetSecondArray();
Algorithm::SortByKey(uniqueIdsWithContourId, this->InterpolationWeights);
} }
else
{
Algorithm::SortByKey(uniqueIds, this->InterpolationWeights);
}
//3. lastly we need to do a unique by key, but since vtkm doesn't
// offer that feature, we use a zip handle.
// We need to use a custom comparison operator as we only want to compare
// the id2 which is the first entry in the zip pair
vtkm::cont::ArrayHandleZip<Id2HandleType, WeightHandleType> zipped =
vtkm::cont::make_ArrayHandleZip(uniqueIds, this->InterpolationWeights);
Algorithm::Unique( zipped, marchingcubes::FirstValueSame());
}
//4.
//LowerBounds generates the output cell connections. It does this by
//finding for each interpolationId where it would be inserted in the
//sorted & unique subset, which generates an index value aka the lookup
//value.
//
Algorithm::LowerBounds(uniqueIds, this->InterpolationIds, connectivity);
//5.
//We re-assign the shortened version of unique ids back into the
//member variable so that 'DoMapField' will work properly
this->InterpolationIds = uniqueIds;
} }
else else
{ {
//when we don't merge points, the connectivity array can be represented //when we don't merge points, the connectivity array can be represented
//by a counting array. The danger of doing it this way is that the output //by a counting array. The danger of doing it this way is that the output
//type is unknown. That is why we use a CellSetSingleType with explicit //type is unknown. That is why we copy it into an explicit array
//storage; using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
vtkm::cont::ArrayHandleIndex temp(this->InterpolationIds.GetNumberOfValues()); vtkm::cont::ArrayHandleIndex temp(this->InterpolationIds.GetNumberOfValues());
Algorithm::Copy(temp, connectivity); Algorithm::Copy(temp, connectivity);
} }
//generate the vertices's //generate the vertices's
ApplyToField applyToField; ApplyToField applyToField;
vtkm::worklet::DispatcherMapField<ApplyToField, vtkm::worklet::DispatcherMapField<ApplyToField,

@ -63,8 +63,9 @@ public:
Tetrahedralize() : OutCellsPerCell() {} Tetrahedralize() : OutCellsPerCell() {}
// Tetrahedralize explicit data set, save number of tetra cells per input // Tetrahedralize explicit data set, save number of tetra cells per input
template <typename DeviceAdapter> template <typename CellSetType,
vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetExplicit<> &cellSet, typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
const DeviceAdapter&) const DeviceAdapter&)
{ {
TetrahedralizeExplicit<DeviceAdapter> worklet; TetrahedralizeExplicit<DeviceAdapter> worklet;
@ -80,6 +81,14 @@ public:
return worklet.Run(cellSet, this->OutCellsPerCell); return worklet.Run(cellSet, this->OutCellsPerCell);
} }
template <typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetStructured<2>&,
const DeviceAdapter&)
{
throw vtkm::cont::ErrorBadType("CellSetStructured<2> can't be tetrahedralized");
return vtkm::cont::CellSetSingleType<>();
}
// Using the saved input to output cells, expand cell data // Using the saved input to output cells, expand cell data
template <typename T, template <typename T,
typename StorageType, typename StorageType,

@ -63,8 +63,9 @@ public:
Triangulate() : OutCellsPerCell() {} Triangulate() : OutCellsPerCell() {}
// Triangulate explicit data set, save number of triangulated cells per input // Triangulate explicit data set, save number of triangulated cells per input
template <typename DeviceAdapter> template <typename CellSetType,
vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetExplicit<> &cellSet, typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const CellSetType& cellSet,
const DeviceAdapter&) const DeviceAdapter&)
{ {
TriangulateExplicit<DeviceAdapter> worklet; TriangulateExplicit<DeviceAdapter> worklet;
@ -80,6 +81,14 @@ public:
return worklet.Run(cellSet, this->OutCellsPerCell); return worklet.Run(cellSet, this->OutCellsPerCell);
} }
template <typename DeviceAdapter>
vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetStructured<3>&,
const DeviceAdapter&)
{
throw vtkm::cont::ErrorBadType("CellSetStructured<3> can't be triangulated");
return vtkm::cont::CellSetSingleType<>();
}
// Using the saved input to output cells, expand cell data // Using the saved input to output cells, expand cell data
template <typename T, template <typename T,
typename StorageType, typename StorageType,

@ -29,7 +29,6 @@
#include <vtkm/cont/arg/TransportTagKeyedValuesInOut.h> #include <vtkm/cont/arg/TransportTagKeyedValuesInOut.h>
#include <vtkm/cont/arg/TransportTagKeyedValuesOut.h> #include <vtkm/cont/arg/TransportTagKeyedValuesOut.h>
#include <vtkm/cont/arg/TransportTagKeysIn.h> #include <vtkm/cont/arg/TransportTagKeysIn.h>
#include <vtkm/cont/arg/TransportTagReducedValuesIn.h>
#include <vtkm/cont/arg/TypeCheckTagArray.h> #include <vtkm/cont/arg/TypeCheckTagArray.h>
#include <vtkm/cont/arg/TypeCheckTagKeys.h> #include <vtkm/cont/arg/TypeCheckTagKeys.h>
@ -127,7 +126,7 @@ public:
struct ReducedValuesIn : vtkm::cont::arg::ControlSignatureTagBase struct ReducedValuesIn : vtkm::cont::arg::ControlSignatureTagBase
{ {
using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArray<TypeList>; using TypeCheckTag = vtkm::cont::arg::TypeCheckTagArray<TypeList>;
using TransportTag = vtkm::cont::arg::TransportTagReducedValuesIn; using TransportTag = vtkm::cont::arg::TransportTagArrayIn;
using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn; using FetchTag = vtkm::exec::arg::FetchTagArrayDirectIn;
}; };

@ -215,30 +215,41 @@ struct DispatcherBaseTransportInvokeTypes
typedef typename ControlSignatureTag::TransportTag TransportTag; typedef typename ControlSignatureTag::TransportTag TransportTag;
}; };
VTKM_CONT
inline
vtkm::Id FlatRange(vtkm::Id range)
{
return range;
}
VTKM_CONT
inline
vtkm::Id FlatRange(const vtkm::Id3 &range)
{
return range[0]*range[1]*range[2];
}
// A functor used in a StaticCast of a FunctionInterface to transport arguments // A functor used in a StaticCast of a FunctionInterface to transport arguments
// from the control environment to the execution environment. // from the control environment to the execution environment.
template<typename ControlInterface, typename InputDomainType, typename Device> template<typename ControlInterface, typename InputDomainType, typename Device>
struct DispatcherBaseTransportFunctor struct DispatcherBaseTransportFunctor
{ {
const InputDomainType &InputDomain; // Warning: this is a reference const InputDomainType &InputDomain; // Warning: this is a reference
vtkm::Id OutputSize; vtkm::Id InputRange;
vtkm::Id OutputRange;
VTKM_CONT
DispatcherBaseTransportFunctor(const InputDomainType &inputDomain,
vtkm::Id outputSize)
: InputDomain(inputDomain),
OutputSize(outputSize)
{ }
// TODO: We need to think harder about how scheduling on 3D arrays works. // TODO: We need to think harder about how scheduling on 3D arrays works.
// Chances are we need to allow the transport for each argument to manage // Chances are we need to allow the transport for each argument to manage
// 3D indices (for example, allocate a 3D array instead of a 1D array). // 3D indices (for example, allocate a 3D array instead of a 1D array).
// But for now, just treat all transports as 1D arrays. // But for now, just treat all transports as 1D arrays.
template<typename InputRangeType, typename OutputRangeType>
VTKM_CONT VTKM_CONT
DispatcherBaseTransportFunctor(const InputDomainType &inputDomain, DispatcherBaseTransportFunctor(const InputDomainType &inputDomain,
vtkm::Id3 dimensions) const InputRangeType &inputRange,
const OutputRangeType &outputRange)
: InputDomain(inputDomain), : InputDomain(inputDomain),
OutputSize(dimensions[0]*dimensions[1]*dimensions[2]) InputRange(FlatRange(inputRange)),
OutputRange(FlatRange(outputRange))
{ } { }
@ -257,7 +268,10 @@ struct DispatcherBaseTransportFunctor
{ {
using TransportTag = typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag; using TransportTag = typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag;
vtkm::cont::arg::Transport<TransportTag,ControlParameter,Device> transport; vtkm::cont::arg::Transport<TransportTag,ControlParameter,Device> transport;
return transport(invokeData, this->InputDomain, this->OutputSize); return transport(invokeData,
this->InputDomain,
this->InputRange,
this->OutputRange);
} }
private: private:
@ -491,6 +505,7 @@ private:
ExecObjectParameters execObjectParameters = ExecObjectParameters execObjectParameters =
parameters.StaticTransformCont(TransportFunctorType( parameters.StaticTransformCont(TransportFunctorType(
invocation.GetInputDomain(), invocation.GetInputDomain(),
inputRange,
outputRange)); outputRange));
// Get the arrays used for scattering input to output. // Get the arrays used for scattering input to output.

@ -78,9 +78,14 @@ struct Transport<TestTransportTag, vtkm::Id *, Device>
typedef TestExecObject ExecObjectType; typedef TestExecObject ExecObjectType;
VTKM_CONT VTKM_CONT
ExecObjectType operator()(vtkm::Id *contData, vtkm::Id *, vtkm::Id size) const ExecObjectType operator()(vtkm::Id *contData,
vtkm::Id *,
vtkm::Id inputRange,
vtkm::Id outputRange) const
{ {
VTKM_TEST_ASSERT(size == ARRAY_SIZE, VTKM_TEST_ASSERT(inputRange == ARRAY_SIZE,
"Got unexpected size in test transport.");
VTKM_TEST_ASSERT(outputRange == ARRAY_SIZE,
"Got unexpected size in test transport."); "Got unexpected size in test transport.");
return ExecObjectType(contData); return ExecObjectType(contData);
} }

@ -127,10 +127,10 @@ public:
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName()); vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology // Input topology
vtkm::cont::ArrayHandle<vtkm::UInt8> inShapes = auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell()); vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::IdComponent> inNumIndices = auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell()); vtkm::TopologyElementTagCell());

@ -129,10 +129,10 @@ public:
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName()); vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology // Input topology
vtkm::cont::ArrayHandle<vtkm::UInt8> inShapes = auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(), cellSet.GetShapesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell()); vtkm::TopologyElementTagCell());
vtkm::cont::ArrayHandle<vtkm::IdComponent> inNumIndices = auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(), cellSet.GetNumIndicesArray(vtkm::TopologyElementTagPoint(),
vtkm::TopologyElementTagCell()); vtkm::TopologyElementTagCell());