Merge branch 'master' into oruebel/vtk-m-cleanup/contourtreeaugmented

This commit is contained in:
Kenneth Moreland 2020-02-24 20:53:47 -07:00
commit 47249ee3c0
23 changed files with 272 additions and 146 deletions

@ -128,12 +128,17 @@ set(VTKm_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
# and the warnings are too strict for the parent project.
vtkm_option(VTKm_ENABLE_DEVELOPER_FLAGS "Enable compiler flags that are useful while developing VTK-m" ON)
# By default VTK-m would install its README.md and LICENSE.md.
# Some application might need not to install those, hence this option.
vtkm_option(VTKm_NO_INSTALL_README_LICENSE "disable the installation of README and LICENSE files" OFF)
mark_as_advanced(
VTKm_ENABLE_LOGGING
VTKm_NO_ASSERT
VTKm_INSTALL_ONLY_LIBRARIES
VTKm_USE_DEFAULT_SYMBOL_VISIBILITY
VTKm_ENABLE_DEVELOPER_FLAGS
VTKm_NO_INSTALL_README_LICENSE
)
#-----------------------------------------------------------------------------
@ -226,6 +231,18 @@ write_basic_package_version_file(
VERSION ${VTKm_VERSION}
COMPATIBILITY ExactVersion )
# Install the readme and license files.
if (NOT VTKm_NO_INSTALL_README_LICENSE)
install(FILES ${VTKm_SOURCE_DIR}/README.md
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
RENAME VTKmREADME.md
)
install(FILES ${VTKm_SOURCE_DIR}/LICENSE.txt
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
RENAME VTKmLICENSE.txt
)
endif()
if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
install(
FILES
@ -234,16 +251,6 @@ if(NOT VTKm_INSTALL_ONLY_LIBRARIES)
DESTINATION ${VTKm_INSTALL_CONFIG_DIR}
)
# Install the readme and license files.
install(FILES ${VTKm_SOURCE_DIR}/README.md
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
RENAME VTKmREADME.md
)
install(FILES ${VTKm_SOURCE_DIR}/LICENSE.txt
DESTINATION ${VTKm_INSTALL_SHARE_DIR}
RENAME VTKmLICENSE.txt
)
# Install helper configure files.
install(
FILES

@ -28,6 +28,12 @@ You can find out more about the design of VTK-m on the [VTK-m Wiki].
+ "Part 4: Advanced Development" covers topics such as new worklet
types and custom device adapters.
+ A practical [VTK-m Tutorial] based in what users want to accomplish with
VTK-m:
+ Building VTK-m and using existing VTK-m data structures and filters.
+ Algorithm development with VTK-m.
+ Writing new VTK-m filters.
+ Community discussion takes place on the [VTK-m users email list].
+ Doxygen-generated nightly reference documentation is available
@ -149,6 +155,19 @@ Below is a simple example of using VTK-m to load a VTK image file, run the
Marching Cubes algorithm on it, and render the results to an image:
```cpp
#include <vtkm/Bounds.h>
#include <vtkm/Range.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/Color.h>
#include <vtkm/rendering/MapperRayTracer.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
vtkm::io::reader::VTKDataSetReader reader("path/to/vtk_image_file");
vtkm::cont::DataSet inputData = reader.ReadDataSet();
std::string fieldName = "scalars";
@ -165,21 +184,10 @@ vtkm::cont::DataSet outputData = filter.Execute(inputData);
// compute the bounds and extends of the input data
vtkm::Bounds coordsBounds = inputData.GetCoordinateSystem().GetBounds();
vtkm::Vec<vtkm::Float64,3> totalExtent( coordsBounds.X.Length(),
coordsBounds.Y.Length(),
coordsBounds.Z.Length() );
vtkm::Float64 mag = vtkm::Magnitude(totalExtent);
vtkm::Normalize(totalExtent);
// setup a camera and point it to towards the center of the input data
vtkm::rendering::Camera camera;
camera.ResetToBounds(coordsBounds);
camera.SetLookAt(totalExtent*(mag * .5f));
camera.SetViewUp(vtkm::make_Vec(0.f, 1.f, 0.f));
camera.SetClippingRange(1.f, 100.f);
camera.SetFieldOfView(60.f);
camera.SetPosition(totalExtent*(mag * 2.f));
vtkm::cont::ColorTable colorTable("inferno");
// Create a mapper, canvas and view that will be used to render the scene
@ -199,6 +207,19 @@ view.Paint();
view.SaveAs("demo_output.pnm");
```
A minimal CMakeLists.txt such as the following one can be used to build this
example.
```CMake
project(example)
set(VTKm_DIR "/somepath/lib/cmake/vtkm-XYZ")
find_package(VTKm REQUIRED)
add_executable(example example.cxx)
target_link_libraries(example vtkm_cont vtkm_rendering)
```
## License ##
@ -216,4 +237,5 @@ See [LICENSE.txt](LICENSE.txt) for details.
[VTK-m Users Guide]: http://m.vtk.org/images/c/c8/VTKmUsersGuide.pdf
[VTK-m users email list]: http://vtk.org/mailman/listinfo/vtkm
[VTK-m Wiki]: http://m.vtk.org/
[VTK-m Tutorial]: http://m.vtk.org/index.php/Tutorial
[CONTRIBUTING.md]: CONTRIBUTING.md

@ -10,7 +10,7 @@
# Find Google Benchmark. Note that benchmark_DIR must be pointed at an
# installation, not a build directory.
find_package(benchmark)
find_package(benchmark REQUIRED)
function(add_benchmark)
set(options)

24
docs/CODEOWNERS Normal file

@ -0,0 +1,24 @@
# Subsystems have specific owners
CMake/ @robertmaynard
data/ @dpugmire
docs/ @robertmaynard @kmorel
examples/ @kmorel
Utilities/ @kmorel
vtkm/ @robertmaynard @kmorel
vtkm/interop/ @robertmaynard
vtkm/io/ @sujin.philip
vtkm/rendering/ @mclarsen
vtkm/source/ @robertmaynard @ollielo
vtkm/testing/ @sujin.philip
vtkm/thirdparty/ @ben.boeckel
vtkm/worklet/cellmetrics/ @hankchilds
vtkm/worklet/contourtree/ @oruebel @ghweber @sujin.philip
vtkm/worklet/contourtree_augmented/ @oruebel @ghweber @sujin.philip
vtkm/worklet/cosmotools/ @ollielo
vtkm/worklet/lcs/ @ayenpure @dpugmire
vtkm/worklet/moments/ @ollielo @robertmaynard
vtkm/worklet/particleadvection @ayenpure @dpugmire
vtkm/worklet/spatialstructure @ayenpure @kmorel
vtkm/worklet/zfp @mclarsen

@ -462,7 +462,7 @@ int main(int argc, char* argv[])
// Compute the number of vertices, i.e., xdim * ydim * zdim
unsigned short nDims = static_cast<unsigned short>(dims.size());
std::size_t numVertices = static_cast<std::size_t>(
std::accumulate(dims.begin(), dims.end(), 1, std::multiplies<std::size_t>()));
std::accumulate(dims.begin(), dims.end(), std::size_t(1), std::multiplies<std::size_t>()));
// Print the mesh metadata
if (rank == 0)

@ -63,7 +63,11 @@
#if __cplusplus >= 201402L
// C++14 and better supports [[deprecated]]
// Except in these cases:
// - nvcc on visual studio
#if !(defined(VTKM_MSVC) && defined(VTKM_CUDA))
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
#endif
#elif defined(VTKM_GCC)
@ -81,7 +85,7 @@
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED
#endif // __has_cpp_attribute(deprecated)
#elif defined(VTKM_MSVC) && _MSC_VER >= 1900
#elif defined(VTKM_MSVC) && (_MSC_VER >= 1900) && !defined(VTKM_CUDA)
#define VTK_M_DEPRECATED_ATTRIBUTE_SUPPORTED

@ -125,17 +125,31 @@ public:
return this->Storage->GetPortalConst();
}
#if defined(VTKM_GCC) && defined(VTKM_ENABLE_OPENMP) && (__GNUC__ == 6 && __GNUC_MINOR__ == 1)
// When using GCC 6.1 with OpenMP enabled we cause a compiler ICE that is
// an identified compiler regression (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71210)
// The easiest way to work around this is to make sure we aren't building with >= O2
#define NO_OPTIMIZE_FUNC_ATTRIBUTE __attribute__((optimize(1)))
#else // gcc 6.1 openmp compiler ICE workaround
#define NO_OPTIMIZE_FUNC_ATTRIBUTE
#endif
VTKM_CONT
NO_OPTIMIZE_FUNC_ATTRIBUTE
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData))
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be used for output or in place.");
}
VTKM_CONT
NO_OPTIMIZE_FUNC_ATTRIBUTE
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be used for output.");
}
#undef NO_OPTIMIZE_FUNC_ATTRIBUTE
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(controlArray)) const
{

@ -30,14 +30,30 @@ void DeviceAdapterAlgorithm<vtkm::cont::DeviceAdapterTagOpenMP>::ScheduleTask(
vtkm::exec::internal::ErrorMessageBuffer errorMessage(errorString, MESSAGE_SIZE);
functor.SetErrorMessageBuffer(errorMessage);
static constexpr vtkm::Id CHUNK_SIZE = 1024;
// Divide n by chunks and round down to nearest power of two. Result is clamped between
// min and max:
auto computeChunkSize = [](vtkm::Id n, vtkm::Id chunks, vtkm::Id min, vtkm::Id max) -> vtkm::Id {
const vtkm::Id chunkSize = (n + chunks - 1) / chunks;
vtkm::Id result = 1;
while (result < chunkSize)
{
result *= 2;
}
result /= 2; // Round down
return std::min(max, std::max(min, result));
};
// Figure out how to chunk the data:
const vtkm::Id chunkSize = computeChunkSize(size, 256, 1, 1024);
const vtkm::Id numChunks = (size + chunkSize - 1) / chunkSize;
VTKM_OPENMP_DIRECTIVE(parallel for
schedule(guided))
for (vtkm::Id i = 0; i < size; i += CHUNK_SIZE)
for (vtkm::Id i = 0; i < numChunks; ++i)
{
const vtkm::Id end = std::min(i + CHUNK_SIZE, size);
functor(i, end);
const vtkm::Id first = i * chunkSize;
const vtkm::Id last = std::min((i + 1) * chunkSize, size);
functor(first, last);
}
if (errorMessage.IsErrorRaised())

@ -187,9 +187,6 @@ struct TestingBitField
return true;
};
portal.SetBit(i, bit);
DEVICE_ASSERT(testValues("SetBit"));
bit = mod;
portal.SetBitAtomic(i, mod);
DEVICE_ASSERT(testValues("SetBitAtomic"));

@ -33,7 +33,7 @@ class ImageConnectivity : public vtkm::filter::FilterCell<ImageConnectivity>
public:
using SupportedTypes = vtkm::TypeListScalarAll;
VTKM_CONT ImageConnectivity();
VTKM_CONT inline ImageConnectivity() { this->SetOutputFieldName("component"); }
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,

@ -16,11 +16,6 @@ namespace vtkm
namespace filter
{
VTKM_CONT ImageConnectivity::ImageConnectivity()
{
this->SetOutputFieldName("component");
}
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet ImageConnectivity::DoExecute(
const vtkm::cont::DataSet& input,

@ -63,10 +63,13 @@ public:
void UpdateSeedResolution(vtkm::cont::DataSet input);
VTKM_CONT
void WriteDataSet(vtkm::Id cycle, const std::string& filename, vtkm::cont::DataSet dataset);
void InitializeSeedPositions(const vtkm::cont::DataSet& input);
VTKM_CONT
void InitializeUniformSeeds(const vtkm::cont::DataSet& input);
void InitializeCoordinates(const vtkm::cont::DataSet& input,
std::vector<Float64>& xC,
std::vector<Float64>& yC,
std::vector<Float64>& zC);
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(

@ -18,6 +18,8 @@
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetFieldAdd.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/io/writer/VTKDataSetWriter.h>
@ -56,9 +58,7 @@ public:
vtkm::Id steps = end_point.NumSteps;
if (steps > 0 && res == 1)
{
if (end_point.Pos[0] >= bounds.X.Min && end_point.Pos[0] <= bounds.X.Max &&
end_point.Pos[1] >= bounds.Y.Min && end_point.Pos[1] <= bounds.Y.Max &&
end_point.Pos[2] >= bounds.Z.Min && end_point.Pos[2] <= bounds.Z.Max)
if (bounds.Contains(end_point.Pos))
{
res = 1;
}
@ -76,6 +76,24 @@ public:
private:
vtkm::Bounds bounds;
};
class DisplacementCalculation : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn end_point, FieldIn start_point, FieldInOut output);
using ExecutionSignature = void(_1, _2, _3);
using InputDomain = _1;
template <typename DisplacementType>
VTKM_EXEC void operator()(const vtkm::Particle& end_point,
const vtkm::Particle& start_point,
DisplacementType& res) const
{
res[0] = end_point.Pos[0] - start_point.Pos[0];
res[1] = end_point.Pos[1] - start_point.Pos[1];
res[2] = end_point.Pos[2] - start_point.Pos[2];
}
};
}
namespace vtkm
@ -100,17 +118,6 @@ inline VTKM_CONT Lagrangian::Lagrangian()
{
}
//-----------------------------------------------------------------------------
inline void Lagrangian::WriteDataSet(vtkm::Id cycle,
const std::string& filename,
vtkm::cont::DataSet dataset)
{
std::stringstream file_stream;
file_stream << filename << cycle << ".vtk";
vtkm::io::writer::VTKDataSetWriter writer(file_stream.str());
writer.WriteDataSet(dataset);
}
//-----------------------------------------------------------------------------
inline void Lagrangian::UpdateSeedResolution(const vtkm::cont::DataSet input)
{
@ -156,7 +163,7 @@ inline void Lagrangian::UpdateSeedResolution(const vtkm::cont::DataSet input)
//-----------------------------------------------------------------------------
inline void Lagrangian::InitializeUniformSeeds(const vtkm::cont::DataSet& input)
inline void Lagrangian::InitializeSeedPositions(const vtkm::cont::DataSet& input)
{
vtkm::Bounds bounds = input.GetCoordinateSystem().GetBounds();
@ -200,6 +207,39 @@ inline void Lagrangian::InitializeUniformSeeds(const vtkm::cont::DataSet& input)
}
}
//-----------------------------------------------------------------------------
inline void Lagrangian::InitializeCoordinates(const vtkm::cont::DataSet& input,
std::vector<Float64>& xC,
std::vector<Float64>& yC,
std::vector<Float64>& zC)
{
vtkm::Bounds bounds = input.GetCoordinateSystem().GetBounds();
vtkm::Float64 x_spacing = 0.0, y_spacing = 0.0, z_spacing = 0.0;
if (this->SeedRes[0] > 1)
x_spacing = (double)(bounds.X.Max - bounds.X.Min) / (double)(this->SeedRes[0] - 1);
if (this->SeedRes[1] > 1)
y_spacing = (double)(bounds.Y.Max - bounds.Y.Min) / (double)(this->SeedRes[1] - 1);
if (this->SeedRes[2] > 1)
z_spacing = (double)(bounds.Z.Max - bounds.Z.Min) / (double)(this->SeedRes[2] - 1);
// Divide by zero handling for 2D data set. How is this handled
for (int x = 0; x < this->SeedRes[0]; x++)
{
vtkm::FloatDefault xi = static_cast<vtkm::FloatDefault>(x * x_spacing);
xC.push_back(bounds.X.Min + xi);
}
for (int y = 0; y < this->SeedRes[1]; y++)
{
vtkm::FloatDefault yi = static_cast<vtkm::FloatDefault>(y * y_spacing);
yC.push_back(bounds.Y.Min + yi);
}
for (int z = 0; z < this->SeedRes[2]; z++)
{
vtkm::FloatDefault zi = static_cast<vtkm::FloatDefault>(z * z_spacing);
zC.push_back(bounds.Z.Min + zi);
}
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
@ -212,7 +252,7 @@ inline VTKM_CONT vtkm::cont::DataSet Lagrangian::DoExecute(
if (cycle == 0)
{
InitializeUniformSeeds(input);
InitializeSeedPositions(input);
BasisParticlesOriginal.Allocate(this->SeedRes[0] * this->SeedRes[1] * this->SeedRes[2]);
vtkm::cont::ArrayCopy(BasisParticles, BasisParticlesOriginal);
}
@ -246,66 +286,28 @@ inline VTKM_CONT vtkm::cont::DataSet Lagrangian::DoExecute(
RK4Type rk4(gridEval, static_cast<vtkm::Float32>(this->stepSize));
res = particleadvection.Run(rk4, basisParticleArray, 1); // Taking a single step
auto particles = res.Particles;
auto particlePortal = particles.GetPortalControl();
auto start_position = BasisParticlesOriginal.GetPortalControl();
auto portal_validity = BasisParticlesValidity.GetPortalControl();
vtkm::cont::DataSet outputData;
vtkm::cont::DataSetBuilderExplicit dataSetBuilder;
vtkm::cont::DataSetBuilderRectilinear dataSetBuilder;
if (cycle % this->writeFrequency == 0)
{
int connectivity_index = 0;
std::vector<vtkm::Id> connectivity;
std::vector<vtkm::Vec<T, 3>> pointCoordinates;
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numIndices;
/* Steps to create a structured dataset */
vtkm::cont::ArrayHandle<vtkm::Vec3f> BasisParticlesDisplacement;
BasisParticlesDisplacement.Allocate(this->SeedRes[0] * this->SeedRes[1] * this->SeedRes[2]);
DisplacementCalculation displacement;
this->Invoke(displacement, particles, BasisParticlesOriginal, BasisParticlesDisplacement);
std::vector<Float64> xC, yC, zC;
InitializeCoordinates(input, xC, yC, zC);
outputData = dataSetBuilder.Create(xC, yC, zC);
vtkm::cont::DataSetFieldAdd dataSetFieldAdd;
dataSetFieldAdd.AddPointField(outputData, "valid", BasisParticlesValidity);
dataSetFieldAdd.AddPointField(outputData, "displacement", BasisParticlesDisplacement);
for (vtkm::Id index = 0; index < particlePortal.GetNumberOfValues(); index++)
{
auto start_point = start_position.Get(index);
auto end_point = particlePortal.Get(index).Pos;
auto steps = particlePortal.Get(index).NumSteps;
if (steps > 0 && portal_validity.Get(index) == 1)
{
if (bounds.Contains(end_point))
{
connectivity.push_back(connectivity_index);
connectivity.push_back(connectivity_index + 1);
connectivity_index += 2;
pointCoordinates.push_back(
vtkm::Vec3f(static_cast<vtkm::FloatDefault>(start_point.Pos[0]),
static_cast<vtkm::FloatDefault>(start_point.Pos[1]),
static_cast<vtkm::FloatDefault>(start_point.Pos[2])));
pointCoordinates.push_back(vtkm::Vec3f(static_cast<vtkm::FloatDefault>(end_point[0]),
static_cast<vtkm::FloatDefault>(end_point[1]),
static_cast<vtkm::FloatDefault>(end_point[2])));
shapes.push_back(vtkm::CELL_SHAPE_LINE);
numIndices.push_back(2);
}
else
{
portal_validity.Set(index, 0);
}
}
else
{
portal_validity.Set(index, 0);
}
}
outputData = dataSetBuilder.Create(pointCoordinates, shapes, numIndices, connectivity);
std::stringstream file_path;
file_path << "output/basisflows_" << this->rank << "_";
auto f_path = file_path.str();
WriteDataSet(cycle, f_path, outputData);
if (this->resetParticles)
{
InitializeUniformSeeds(input);
InitializeSeedPositions(input);
BasisParticlesOriginal.Allocate(this->SeedRes[0] * this->SeedRes[1] * this->SeedRes[2]);
vtkm::cont::ArrayCopy(BasisParticles, BasisParticlesOriginal);
}

@ -80,15 +80,17 @@ void TestLagrangianFilterMultiStepInterval()
{
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfCoordinateSystems() == 1,
"Wrong number of coordinate systems in the output dataset.");
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfCells() == 3375,
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfPoints() == 4096,
"Wrong number of basis flows extracted.");
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfFields() == 2, "Wrong number of fields.");
}
else
{
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfCells() == 0,
"Output dataset should have no cells.");
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfPoints() == 0,
"Output dataset should have no points.");
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfCoordinateSystems() == 0,
"Wrong number of coordinate systems in the output dataset.");
VTKM_TEST_ASSERT(extractedBasisFlows.GetNumberOfFields() == 0, "Wrong number of fields.");
}
}
}

@ -41,6 +41,8 @@ public:
template <typename Invocation>
VTKM_CONT void DoInvoke(Invocation& invocation) const
{
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
@ -52,7 +54,7 @@ public:
// an VariantArrayHandle that gets cast to one). The size of the domain
// (number of threads/worklet instances) is equal to the size of the
// array.
auto numInstances = internal::scheduling_range(inputDomain);
auto numInstances = SchedulingRange(inputDomain);
// A MapField is a pretty straightforward dispatch. Once we know the number
// of invocations, the superclass can take care of the rest.

@ -44,6 +44,8 @@ public:
template <typename Invocation>
VTKM_CONT void DoInvoke(Invocation& invocation) const
{
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
using SchedulingRangeType = typename WorkletType::VisitTopologyType;
@ -59,7 +61,7 @@ public:
// Now that we have the input domain, we can extract the range of the
// scheduling and call BadicInvoke.
this->BasicInvoke(invocation, internal::scheduling_range(inputDomain, SchedulingRangeType{}));
this->BasicInvoke(invocation, SchedulingRange(inputDomain, SchedulingRangeType{}));
}
};
}

@ -45,6 +45,8 @@ public:
template <typename Invocation>
void DoInvoke(Invocation& invocation) const
{
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
@ -56,7 +58,7 @@ public:
// We can pull the input domain parameter (the data specifying the input
// domain) from the invocation object.
const InputDomainType& inputDomain = invocation.GetInputDomain();
auto inputRange = internal::scheduling_range(inputDomain, vtkm::TopologyElementTagPoint{});
auto inputRange = SchedulingRange(inputDomain, vtkm::TopologyElementTagPoint{});
// This is pretty straightforward dispatch. Once we know the number
// of invocations, the superclass can take care of the rest.

@ -44,6 +44,8 @@ public:
template <typename Invocation>
void DoInvoke(Invocation& invocation) const
{
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
@ -60,7 +62,7 @@ public:
// Now that we have the input domain, we can extract the range of the
// scheduling and call BasicInvoke.
this->BasicInvoke(invocation, internal::scheduling_range(inputDomain));
this->BasicInvoke(invocation, SchedulingRange(inputDomain));
}
};
}

@ -214,6 +214,8 @@ public:
template <typename Invocation>
VTKM_CONT void DoInvoke(Invocation& invocation) const
{
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
@ -225,15 +227,15 @@ public:
// an VariantArrayHandle that gets cast to one). The size of the domain
// (number of threads/worklet instances) is equal to the size of the
// array.
vtkm::Id fullSize = internal::scheduling_range(inputDomain);
vtkm::Id fullSize = SchedulingRange(inputDomain);
vtkm::Id blockSize = fullSize / NumberOfBlocks;
if (fullSize % NumberOfBlocks != 0)
blockSize += 1;
using TransformFunctorType =
detail::DispatcherStreamingMapFieldTransformFunctor<typename Invocation::ControlInterface>;
using TransferFunctorType =
detail::DispatcherStreamingMapFieldTransferFunctor<typename Invocation::ControlInterface>;
using TransformFunctorType = vtkm::worklet::detail::DispatcherStreamingMapFieldTransformFunctor<
typename Invocation::ControlInterface>;
using TransferFunctorType = vtkm::worklet::detail::DispatcherStreamingMapFieldTransferFunctor<
typename Invocation::ControlInterface>;
for (vtkm::Id block = 0; block < NumberOfBlocks; block++)
{

@ -176,6 +176,20 @@ private:
template <typename T>
VTKM_CONT Keys<T>::Keys() = default;
template <typename KeyType>
inline auto SchedulingRange(const vtkm::worklet::Keys<KeyType>& inputDomain)
-> decltype(inputDomain.GetInputRange())
{
return inputDomain.GetInputRange();
}
template <typename KeyType>
inline auto SchedulingRange(const vtkm::worklet::Keys<KeyType>* const inputDomain)
-> decltype(inputDomain->GetInputRange())
{
return inputDomain->GetInputRange();
}
}
} // namespace vtkm::worklet

@ -244,8 +244,10 @@ public:
// Deprecated signatures for legacy support. These will be removed at some
// point.
using WorkletMapCellToPoint = WorkletVisitPointsWithCells;
using WorkletMapPointToCell = WorkletVisitCellsWithPoints;
using WorkletMapCellToPoint VTKM_DEPRECATED(1.5, "Use WorkletVisitPointsWithCells.") =
WorkletVisitPointsWithCells;
using WorkletMapPointToCell VTKM_DEPRECATED(1.5, "Use WorkletVisitCellsWithPoints.") =
WorkletVisitCellsWithPoints;
}
} // namespace vtkm::worklet

@ -48,47 +48,31 @@ namespace vtkm
{
namespace worklet
{
template <typename T>
class Keys;
namespace internal
{
template <typename Domain>
inline auto scheduling_range(const Domain& inputDomain) -> decltype(inputDomain.GetNumberOfValues())
inline auto SchedulingRange(const Domain& inputDomain) -> decltype(inputDomain.GetNumberOfValues())
{
return inputDomain.GetNumberOfValues();
}
template <typename KeyType>
inline auto scheduling_range(const vtkm::worklet::Keys<KeyType>& inputDomain)
-> decltype(inputDomain.GetInputRange())
{
return inputDomain.GetInputRange();
}
template <typename Domain>
inline auto scheduling_range(const Domain* const inputDomain)
inline auto SchedulingRange(const Domain* const inputDomain)
-> decltype(inputDomain->GetNumberOfValues())
{
return inputDomain->GetNumberOfValues();
}
template <typename KeyType>
inline auto scheduling_range(const vtkm::worklet::Keys<KeyType>* const inputDomain)
-> decltype(inputDomain->GetInputRange())
{
return inputDomain->GetInputRange();
}
template <typename Domain, typename SchedulingRangeType>
inline auto scheduling_range(const Domain& inputDomain, SchedulingRangeType type)
inline auto SchedulingRange(const Domain& inputDomain, SchedulingRangeType type)
-> decltype(inputDomain.GetSchedulingRange(type))
{
return inputDomain.GetSchedulingRange(type);
}
template <typename Domain, typename SchedulingRangeType>
inline auto scheduling_range(const Domain* const inputDomain, SchedulingRangeType type)
inline auto SchedulingRange(const Domain* const inputDomain, SchedulingRangeType type)
-> decltype(inputDomain->GetSchedulingRange(type))
{
return inputDomain->GetSchedulingRange(type);

@ -284,6 +284,18 @@ public:
}
};
template <typename T>
inline vtkm::Id SchedulingRange(const std::vector<T>& inputDomain)
{
return static_cast<vtkm::Id>(inputDomain.size());
}
template <typename T>
inline vtkm::Id SchedulingRange(const std::vector<T>* const inputDomain)
{
return static_cast<vtkm::Id>(inputDomain->size());
}
template <typename WorkletType>
class TestDispatcher : public vtkm::worklet::internal::DispatcherBase<TestDispatcher<WorkletType>,
WorkletType,
@ -295,19 +307,37 @@ class TestDispatcher : public vtkm::worklet::internal::DispatcherBase<TestDispat
using ScatterType = typename Superclass::ScatterType;
public:
VTKM_CONT
TestDispatcher(const WorkletType& worklet = WorkletType(),
const ScatterType& scatter = ScatterType())
: Superclass(worklet, scatter)
template <typename... T>
VTKM_CONT TestDispatcher(T&&... args)
: Superclass(std::forward<T>(args)...)
{
}
VTKM_CONT
template <typename Invocation>
void DoInvoke(Invocation&& invocation) const
void DoInvoke(Invocation& invocation) const
{
std::cout << "In TestDispatcher::DoInvoke()" << std::endl;
this->BasicInvoke(invocation, ARRAY_SIZE);
using namespace vtkm::worklet::internal;
// This is the type for the input domain
using InputDomainType = typename Invocation::InputDomainType;
// We can pull the input domain parameter (the data specifying the input
// domain) from the invocation object.
const InputDomainType& inputDomain = invocation.GetInputDomain();
// For a DispatcherMapField, the inputDomain must be an ArrayHandle (or
// an VariantArrayHandle that gets cast to one). The size of the domain
// (number of threads/worklet instances) is equal to the size of the
// array.
//verify the overloads for SchedulingRange work
auto numInstances = SchedulingRange(inputDomain);
// A MapField is a pretty straightforward dispatch. Once we know the number
// of invocations, the superclass can take care of the rest.
this->BasicInvoke(invocation, numInstances);
}
private: