This commit is contained in:
Dave Pugmire 2023-06-23 13:49:59 -04:00
commit 064501214a
129 changed files with 2632 additions and 1761 deletions

@ -62,6 +62,11 @@
extends:
- .docker_image
.opensuse: &opensuse
image: "kitware/vtkm:ci-opensuse-20230619"
extends:
- .docker_image
.run_automatically: &run_automatically
rules:
- if: '$CI_MERGE_REQUEST_ID'
@ -226,6 +231,7 @@ include:
- local: '/.gitlab/ci/centos8.yml'
- local: '/.gitlab/ci/doxygen.yml'
- local: '/.gitlab/ci/macos.yml'
- local: '/.gitlab/ci/opensuse.yml'
- local: '/.gitlab/ci/rhel8.yml'
- local: '/.gitlab/ci/ubuntu1604.yml'
- local: '/.gitlab/ci/ubuntu1804.yml'

@ -1,4 +1,3 @@
#!/bin/bash -ex
git lfs uninstall
git -c http.sslVerify=false push -f "$1" "HEAD:refs/heads/${2}"
git -c http.sslVerify=false push --no-verify -f "$1" "HEAD:refs/heads/${2}"

@ -0,0 +1,24 @@
FROM opensuse/tumbleweed
LABEL maintainer "Vicente Adolfo Bolea Sanchez<vicente.bolea@kitware.com>"
# Base dependencies for building VTK-m projects
RUN zypper refresh && \
zypper update -y && \
zypper install -y --no-recommends \
cmake \
curl \
gcc13-c++ \
git \
git-lfs \
hdf5-devel \
libgomp1 \
mpich \
mpich-devel \
ninja \
python311 \
python311-scipy \
tbb-devel && \
zypper clean --all
# Need to run git-lfs install manually on system packaged version
RUN git-lfs install

32
.gitlab/ci/opensuse.yml Normal file

@ -0,0 +1,32 @@
build:opensuse_gcc13:
tags:
- build
- vtkm
- docker
- linux-x86_64
extends:
- .opensuse
- .cmake_build_linux
- .run_automatically
variables:
CMAKE_BUILD_TYPE: Debug
VTKM_SETTINGS: "benchmarks+tbb+openmp+mpi+shared+hdf5+min_build"
test:opensuse_gcc13:
tags:
- test
- vtkm
- docker
- linux-x86_64
extends:
- .opensuse
- .cmake_test_linux
- .run_automatically
variables:
#Restrict OpenMP number of threads since multiple test stages
#execute on the same hardware concurrently
OMP_NUM_THREADS: 4
dependencies:
- build:opensuse_gcc13
needs:
- build:opensuse_gcc13

@ -1,36 +1,3 @@
build:ubuntu2004_gcc9:
tags:
- build
- vtkm
- docker
- linux-x86_64
extends:
- .ubuntu2004
- .cmake_build_linux
- .run_automatically
variables:
CMAKE_BUILD_TYPE: Debug
VTKM_SETTINGS: "benchmarks+tbb+openmp+mpi+shared+hdf5+min_build"
test:ubuntu2004_gcc9:
tags:
- test
- vtkm
- docker
- linux-x86_64
extends:
- .ubuntu2004
- .cmake_test_linux
- .run_automatically
variables:
#Restrict OpenMP number of threads since multiple test stages
#execute on the same hardware concurrently
OMP_NUM_THREADS: 4
dependencies:
- build:ubuntu2004_gcc9
needs:
- build:ubuntu2004_gcc9
build:ubuntu2004_kokkos:
tags:
- build

@ -658,6 +658,10 @@ function(vtkm_add_instantiations instantiations_list)
set(file_template_source ${instantiations_file})
endif()
set_property(DIRECTORY
APPEND
PROPERTY CMAKE_CONFIGURE_DEPENDS ${instantiations_file})
# Extract explicit instantiations
_vtkm_extract_instantiations(instantiations ${instantiations_file})

@ -39,11 +39,24 @@ function(_vtkm_create_test_executable
set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "")
endif()
#the creation of the test source list needs to occur before the labeling as
#The creation of the test source list needs to occur before the labeling as
#cuda. This is so that we get the correctly named entry points generated
create_test_sourcelist(test_sources ${prog}.cxx ${sources} ${device_sources} ${extraArgs})
#Also, although we usually assume that each source file is a test, we need
#to check for the `NOT_A_TEST` property for support code that should be
#compiled with the executable but is not a test itself.
set(test_sources)
set(extra_sources)
foreach(src IN LISTS sources device_sources)
get_source_file_property(not_a_test ${src} NOT_A_TEST)
if (not_a_test)
list(APPEND extra_sources ${src})
else()
list(APPEND test_sources ${src})
endif()
endforeach()
create_test_sourcelist(test_sources ${prog}.cxx ${test_sources} ${extraArgs})
add_executable(${prog} ${test_sources})
add_executable(${prog} ${test_sources} ${extra_sources})
vtkm_add_drop_unused_function_flags(${prog})
target_compile_definitions(${prog} PRIVATE ${defines})
@ -91,6 +104,14 @@ endfunction()
# function with the same name as the source file. For example, if SOURCES
# contains `UnitTestFoo.cxx`, then `UnitTestFoo.cxx` should contain a
# function named `UnitTestFoo`. A test with this name is also added to ctest.
# If you want to add a source file that should not be treated as a test, then
# you can attach the `NOT_A_TEST` property to those files (using
# `set_source_files_properties`), and that file will be added to the test
# executable without adding an associated test.
#
# DEVICE_SOURCES: The same as SOURCES except that each file will be compiled
# with the device compiler. You can use both SOURCES and DEVICE_SOURCES
# together to specify which compiler to use for each file.
#
# LIBRARIES: Extra libraries that this set of tests need to link to.
#
@ -296,6 +317,10 @@ vtkm_unit_tests but not in its test dependencies. Add test dependencies to \
endif()
foreach (test ${VTKm_UT_SOURCES} ${VTKm_UT_DEVICE_SOURCES})
get_source_file_property(not_a_test ${test} NOT_A_TEST)
if (not_a_test)
continue()
endif()
get_filename_component(tname ${test} NAME_WE)
if(VTKm_UT_MPI)
if (VTKm_ENABLE_MPI)

@ -186,6 +186,11 @@ vtkm_option(VTKm_SKIP_LIBRARY_VERSIONS "Skip versioning VTK-m libraries" OFF)
# through ctest's command-line. Doesn't affect CI unless enabled.
vtkm_option(VTKm_OVERRIDE_CTEST_TIMEOUT "Disable default ctest timeout" OFF)
# VTKm_ENABLE_GPU_MPI makes VTK-m to use DIY routines that enables GPU aware
# MPI. By default, this option is disabled. Also, this option is hidden unless
# VTKm_ENABLE_MPI=ON.
cmake_dependent_option(VTKm_ENABLE_GPU_MPI "Enable GPU AWARE MPI support" OFF "VTKm_ENABLE_MPI" OFF)
mark_as_advanced(
VTKm_ENABLE_LOGGING
VTKm_NO_ASSERT

@ -13,20 +13,17 @@
#include <vtkm/TypeTraits.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/source/Tangle.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/Ray.h>
#include <vtkm/rendering/raytracing/RayTracer.h>
#include <vtkm/rendering/raytracing/SphereIntersector.h>
#include <vtkm/rendering/raytracing/TriangleExtractor.h>
#include <vtkm/exec/FunctorBase.h>
#include <sstream>
#include <string>
#include <vector>

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c077570d0acc5ee81707e1b763e5edbf285af840474d48ab5b051599cb809697
size 81863

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d4979a7c0e46943bd7a2c94581023c7db12a30ee12bda735b0041c64cff52196
size 65438

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cbd7292ca4006866afc2339e39e14a3edf8c5983e04a5ceea80b5d698293fc86
size 94505

@ -0,0 +1,14 @@
# Sped up compilation of ArrayRangeCompute.cxx
The file `ArrayRangeCompute.cxx` was taking a long time to compile with
some device compilers. This is because it precompiles the range computation
for many types of array structures. It thus compiled the same operation
many times over.
The new implementation compiles just as many cases. However, the
compilation is split into many different translation units using the
instantiations feature of VTK-m's configuration. Although this rarely
reduces the overall CPU time spent during compiling, it prevents parallel
compiles from waiting for this one build to complete. It also avoids
potential issues with compilers running out of resources as it tries to
build a monolithic file.

@ -0,0 +1,7 @@
# ComputeMoments filter now operates on any scalar field
Previously, the `ComputeMoments` filter only operated on a finite set of
array types as its input field. This included a prescribed list of `Vec`
sizes for the input. The filter has been updated to use more generic
interfaces to the field's array (and float fallback) to enable the
computation of moments on any type of scalar field.

@ -0,0 +1,15 @@
# Get the 3D index from a BoundaryState in WorkletPointNeighborhood
There are occasions when you need a worklet to opeate on 2D or 3D indices.
Most worklets operate on 1D indices, which requires recomputing the 3D
index in each worklet instance. A workaround is to use a worklet that does
a 3D scheduling and pull the working index from that.
The problem was that there was no easy way to get this 3D index. To provide
this option, a feature was added to the `BoundaryState` class that can be
provided by `WorkletPointNeighborhood`.
Thus, to get a 3D index in a worklet, use the `WorkletPointNeighborhood`,
add `Boundary` as an argument to the `ExecutionSignature`, and then call
`GetCenterIndex` on the `BoundaryState` object passed to the worklet
operator.

@ -78,7 +78,7 @@ int main(int argc, char* argv[])
// from, so we want the scalar range to match that of the previous image.
isoActor.SetScalarRange(actor.GetScalarRange());
vtkm::rendering::Scene isoScene;
isoScene.AddActor(isoActor);
isoScene.AddActor(std::move(isoActor));
// Wireframe surface:
vtkm::rendering::View3D isoView(isoScene, MapperWireframer(), canvas, camera, bg);

@ -35,7 +35,7 @@ int main(int argc, char** argv)
//Creating Scene and adding Actor
vtkm::rendering::Scene scene;
scene.AddActor(actor);
scene.AddActor(std::move(actor));
//Creating and initializing the View using the Canvas, Ray Tracer Mappers, and Scene
vtkm::rendering::MapperRayTracer mapper;

@ -186,6 +186,18 @@ struct GetTypeInParentheses<void(T)>
} \
\
VTKM_CONT \
explicit classname(const std::vector<vtkm::cont::internal::Buffer>& buffers) \
: Superclass(buffers) \
{ \
} \
\
VTKM_CONT \
explicit classname(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept \
: Superclass(std::move(buffers)) \
{ \
} \
\
VTKM_CONT \
Thisclass& operator=(const Thisclass& src) \
{ \
this->Superclass::operator=(src); \
@ -332,12 +344,12 @@ public:
/// Special constructor for subclass specializations that need to set the
/// initial state array. Used when pulling data from other sources.
///
VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
VTKM_CONT explicit ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
: Buffers(buffers)
{
}
VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
VTKM_CONT explicit ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
: Buffers(std::move(buffers))
{
}

@ -230,11 +230,11 @@ public:
static FirstArrayType GetFirstArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return { FirstArrayBuffers(buffers) };
return FirstArrayType(FirstArrayBuffers(buffers));
}
static SecondArrayType GetSecondArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return { SecondArrayBuffers(buffers) };
return SecondArrayType(SecondArrayBuffers(buffers));
}
};
} // namespace internal

@ -16,6 +16,8 @@
#include <vtkm/Deprecated.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/Instantiations.h>
#include <vtkm/cont/Algorithm.h>
#include <limits>
@ -114,7 +116,7 @@ struct ArrayRangeComputeImpl
template <typename ArrayHandleType>
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeTemplate(
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeTemplate(
const ArrayHandleType& input,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{})
{
@ -134,4 +136,156 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
}
} // namespace vtkm::cont
#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(modifiers, ...) \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Int8, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::UInt8, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Int16, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::UInt16, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Int32, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::UInt32, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Int64, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::UInt64, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Float32, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Float64, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<bool, __VA_ARGS__>& input, vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<char, __VA_ARGS__>& input, vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<signed VTKM_UNUSED_INT_TYPE, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<unsigned VTKM_UNUSED_INT_TYPE, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device)
#define VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(modifiers, N, ...) \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Int8, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<UInt8, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<Int16, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<UInt16, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<Int32, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<UInt32, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<Int64, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<UInt64, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<Float32, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<Float64, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<bool, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<char, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<signed VTKM_UNUSED_INT_TYPE, N>, __VA_ARGS__>& input, \
vtkm::cont::DeviceAdapterId device); \
modifiers vtkm::cont::ArrayHandle<vtkm::Range> vtkm::cont::ArrayRangeComputeTemplate( \
const vtkm::cont::ArrayHandle<vtkm::Vec<unsigned VTKM_UNUSED_INT_TYPE, N>, __VA_ARGS__>& \
input, \
vtkm::cont::DeviceAdapterId device)
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT,
vtkm::cont::StorageTagBasic);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
2,
vtkm::cont::StorageTagBasic);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
3,
vtkm::cont::StorageTagBasic);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
4,
vtkm::cont::StorageTagBasic);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
2,
vtkm::cont::StorageTagSOA);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
3,
vtkm::cont::StorageTagSOA);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
4,
vtkm::cont::StorageTagSOA);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(
extern template VTKM_CONT_TEMPLATE_EXPORT,
3,
vtkm::cont::StorageTagCartesianProduct<vtkm::cont::StorageTagBasic,
vtkm::cont::StorageTagBasic,
vtkm::cont::StorageTagBasic>);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_SCALARS(extern template VTKM_CONT_TEMPLATE_EXPORT,
vtkm::cont::StorageTagConstant);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
2,
vtkm::cont::StorageTagConstant);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
3,
vtkm::cont::StorageTagConstant);
VTKM_INSTANTIATION_END
VTKM_INSTANTIATION_BEGIN
VTK_M_ARRAY_RANGE_COMPUTE_ALL_VECN(extern template VTKM_CONT_TEMPLATE_EXPORT,
4,
vtkm::cont::StorageTagConstant);
VTKM_INSTANTIATION_END
#endif //vtk_m_cont_ArrayRangeComputeTemplate_h

@ -86,6 +86,7 @@ set(headers
DeviceAdapterAlgorithm.h
DeviceAdapterList.h
DeviceAdapterTag.h
DIYMemoryManagement.h
EnvironmentTracker.h
Error.h
ErrorBadAllocation.h
@ -154,6 +155,7 @@ set(sources
DataSetBuilderRectilinear.cxx
DataSetBuilderUniform.cxx
DeviceAdapterTag.cxx
DIYMemoryManagement.cxx
EnvironmentTracker.cxx
ErrorBadDevice.cxx
ErrorBadType.cxx
@ -261,6 +263,14 @@ vtkm_install_headers(vtkm/cont
${VTKm_BINARY_INCLUDE_DIR}/${kit_dir}/DefaultTypes.h
)
#-----------------------------------------------------------------------------
# Some operations are pre-compiled for many different types. Improve parallel
# compiles by breaking them up into smaller units.
vtkm_add_instantiations(array_range_instantiations
INSTANTIATIONS_FILE ArrayRangeComputeTemplate.h
)
list(APPEND device_sources ${array_range_instantiations})
#-----------------------------------------------------------------------------
vtkm_library( NAME vtkm_cont
SOURCES ${sources}

@ -0,0 +1,78 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/DIYMemoryManagement.h>
#include <vtkm/cont/DeviceAdapterList.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/cont/RuntimeDeviceInformation.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#ifdef VTKM_ENABLE_GPU_MPI
#include <vtkm/cont/kokkos/DeviceAdapterKokkos.h>
#endif
namespace
{
thread_local vtkm::cont::DeviceAdapterId DIYCurrentDeviceAdaptor =
vtkm::cont::DeviceAdapterTagSerial();
vtkm::cont::internal::DeviceAdapterMemoryManagerBase& GetMemoryManager(
vtkm::cont::DeviceAdapterId device)
{
return vtkm::cont::RuntimeDeviceInformation().GetMemoryManager(device);
}
vtkmdiy::MemoryManagement GetDIYMemoryManagement(vtkm::cont::DeviceAdapterId device)
{
return vtkmdiy::MemoryManagement(
[device](int, size_t n) {
return static_cast<char*>(GetMemoryManager(device).AllocateRawPointer(n));
},
[device](const char* p) { GetMemoryManager(device).DeleteRawPointer(const_cast<char*>(p)); },
[device](char* dest, const char* src, size_t count) {
GetMemoryManager(device).CopyDeviceToDeviceRawPointer(src, dest, count);
});
}
}
namespace vtkm
{
namespace cont
{
vtkm::cont::DeviceAdapterId GetDIYDeviceAdapter()
{
return DIYCurrentDeviceAdaptor;
}
void DIYMasterExchange(vtkmdiy::Master& master, bool remote)
{
#ifdef VTKM_ENABLE_GPU_MPI
try
{
DIYCurrentDeviceAdaptor = vtkm::cont::DeviceAdapterTagKokkos();
master.exchange(remote, GetDIYMemoryManagement(vtkm::cont::DeviceAdapterTagKokkos()));
DIYCurrentDeviceAdaptor = vtkm::cont::DeviceAdapterTagSerial();
}
catch (...)
{
DIYCurrentDeviceAdaptor = vtkm::cont::DeviceAdapterTagSerial();
throw;
}
#else
DIYCurrentDeviceAdaptor = vtkm::cont::DeviceAdapterTagSerial();
master.exchange(remote);
#endif
}
}
}

@ -0,0 +1,30 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_internal_DIYMemoryManagement_h
#define vtk_m_cont_internal_DIYMemoryManagement_h
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/thirdparty/diy/diy.h>
namespace vtkm
{
namespace cont
{
VTKM_CONT_EXPORT vtkm::cont::DeviceAdapterId GetDIYDeviceAdapter();
/// \brief Wraps vtkmdiy::Master::exchange by setting its appropiate vtkmdiy::MemoryManagement.
VTKM_CONT_EXPORT void DIYMasterExchange(vtkmdiy::Master& master, bool remote = false);
}
}
#endif

@ -78,6 +78,11 @@ public:
{
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
}
VTKM_CONT virtual void DeleteRawPointer(void*) const override
{
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
}
};
class RuntimeDeviceConfigurationInvalid final

@ -240,6 +240,11 @@ void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagCuda>::CopyDeviceToD
cudaMemcpyDeviceToDevice,
cudaStreamPerThread));
}
void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagCuda>::DeleteRawPointer(void* mem) const
{
CudaDelete(mem);
};
}
}
} // namespace vtkm::cont::internal

@ -50,6 +50,8 @@ public:
VTKM_CONT virtual void CopyDeviceToDevice(
const vtkm::cont::internal::BufferInfo& src,
const vtkm::cont::internal::BufferInfo& dest) const override;
VTKM_CONT virtual void DeleteRawPointer(void* mem) const override;
};
}
}

@ -10,6 +10,7 @@
#include <vtkm/internal/Assume.h>
#include <vtkm/cont/DIYMemoryManagement.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/ErrorBadDevice.h>
@ -1158,30 +1159,46 @@ void Serialization<vtkm::cont::internal::Buffer>::save(BinaryBuffer& bb,
const vtkm::cont::internal::Buffer& obj)
{
vtkm::BufferSizeType size = obj.GetNumberOfBytes();
vtkmdiy::save(bb, size);
std::unique_ptr<vtkm::cont::Token> token;
const void* ptr = nullptr;
if (size)
if (size > 0)
{
// NOTE: If size == 0, obj.ReadPointerHost will be a nullptr, and saving that via
// vtkmdiy causes test failure on osheim
vtkm::cont::Token token;
const vtkm::UInt8* data = reinterpret_cast<const vtkm::UInt8*>(obj.ReadPointerHost(token));
vtkmdiy::save(bb, data, static_cast<std::size_t>(size));
token.reset(new vtkm::cont::Token);
ptr = obj.ReadPointerDevice(vtkm::cont::GetDIYDeviceAdapter(), *token);
}
// We need to keep the token alive until the data is consumed by DIY,
// otherwise the pointed data could be freed before it is consumed.
// Note that we cannot simply have the unique_ptr captured by the below
// lambda since save_binary_blob 3rd argument is a std::function and
// std::function needs for every parameter to be CopyAsignable, which
// vtkm::cont::Token is not.
bb.save_binary_blob(static_cast<const char*>(ptr),
static_cast<std::size_t>(size),
[token = token.release()](const char[]) {
if (token != nullptr)
{
token->DetachFromAll();
delete token;
}
});
}
void Serialization<vtkm::cont::internal::Buffer>::load(BinaryBuffer& bb,
vtkm::cont::internal::Buffer& obj)
{
vtkm::BufferSizeType size;
vtkmdiy::load(bb, size);
vtkm::cont::Token token;
auto blob = bb.load_binary_blob();
vtkm::BufferSizeType size = blob.size;
obj.SetNumberOfBytes(size, vtkm::CopyFlag::Off, token);
if (size)
{
vtkm::UInt8* data = reinterpret_cast<vtkm::UInt8*>(obj.WritePointerHost(token));
vtkmdiy::load(bb, data, static_cast<std::size_t>(size));
auto device = vtkm::cont::GetDIYDeviceAdapter();
void* ptr = obj.WritePointerDevice(device, token);
vtkm::cont::RuntimeDeviceInformation().GetMemoryManager(device).CopyDeviceToDeviceRawPointer(
blob.pointer.get(), ptr, size);
}
}

@ -42,7 +42,11 @@
#include <cstddef>
#include <cstdlib>
namespace
namespace vtkm
{
namespace cont
{
namespace internal
{
/// A deleter object that can be used with our aligned mallocs
@ -120,15 +124,6 @@ void HostReallocate(void*& memory,
memory = container = newBuffer;
}
} // anonymous namespace
namespace vtkm
{
namespace cont
{
namespace internal
{
VTKM_CONT void InvalidRealloc(void*&, void*&, vtkm::BufferSizeType, vtkm::BufferSizeType)
{
throw vtkm::cont::ErrorBadAllocation("User provided memory does not have a reallocater.");
@ -340,6 +335,28 @@ vtkm::cont::internal::BufferInfo DeviceAdapterMemoryManagerBase::ManageArray(
return vtkm::cont::internal::BufferInfo(
this->GetDevice(), memory, container, size, deleter, reallocater);
}
void* DeviceAdapterMemoryManagerBase::AllocateRawPointer(vtkm::BufferSizeType size) const
{
return this->Allocate(size).TransferOwnership().Memory;
}
void DeviceAdapterMemoryManagerBase::CopyDeviceToDeviceRawPointer(const void* src,
void* dest,
vtkm::BufferSizeType size) const
{
this->CopyDeviceToDevice(
vtkm::cont::internal::BufferInfo(
this->GetDevice(),
const_cast<void*>(src),
const_cast<void*>(src),
size,
[](void*) {},
vtkm::cont::internal::InvalidRealloc),
vtkm::cont::internal::BufferInfo(
this->GetDevice(), dest, dest, size, [](void*) {}, vtkm::cont::internal::InvalidRealloc));
}
}
}
} // namespace vtkm::cont::internal

@ -196,6 +196,37 @@ public:
/// objects were created by a previous call to this object.
VTKM_CONT virtual void CopyDeviceToDevice(const vtkm::cont::internal::BufferInfo& src,
const vtkm::cont::internal::BufferInfo& dest) const = 0;
/// \brief Low-level method to allocate memory on the device.
///
/// This method allocates an array of the given number of bytes on the device and returns
/// a void pointer to the array. The preferred method to allocate memory is to use the
/// `Allocate` method, which returns a `BufferInfo` that manages its own memory. However,
/// for cases where you are interfacing with code outside of VTK-m and need just a raw
/// pointer, this method can be used. The returned memory can be freed with
/// `DeleteRawPointer`.
VTKM_CONT virtual void* AllocateRawPointer(vtkm::BufferSizeType size) const;
/// \brief Low-level method to copy data on the device.
///
/// This method copies data from one raw pointer to another. It performs the same
/// function as `CopyDeviceToDevice`, except that it operates on raw pointers
/// instead of `BufferInfo` objects. This is a useful low-level mechanism to move
/// data on a device in memory locations created externally to VTK-m.
VTKM_CONT virtual void CopyDeviceToDeviceRawPointer(const void* src,
void* dest,
vtkm::BufferSizeType size) const;
/// \brief Low-level method to delete memory on the device.
///
/// This method takes a pointer to memory allocated on the device and frees it.
/// The preferred method to delete memory is to use the deallocation routines in
/// `BufferInfo` objects created with `Allocate`. But for cases where you only
/// have a raw pointer to the data, this method can be used to manage it. This
/// method should only be used on memory allocated with this
/// `DeviceAdaperMemoryManager`.
VTKM_CONT virtual void DeleteRawPointer(void*) const = 0;
};
/// \brief The device adapter memory manager.
@ -207,6 +238,14 @@ public:
template <typename DeviceAdapterTag>
class DeviceAdapterMemoryManager;
VTKM_CONT_EXPORT VTKM_CONT void HostDeleter(void*);
VTKM_CONT_EXPORT VTKM_CONT void* HostAllocate(vtkm::BufferSizeType);
VTKM_CONT_EXPORT VTKM_CONT void HostReallocate(void*&,
void*&,
vtkm::BufferSizeType,
vtkm::BufferSizeType);
VTKM_CONT_EXPORT VTKM_CONT void InvalidRealloc(void*&,
void*&,
vtkm::BufferSizeType,

@ -83,6 +83,12 @@ void DeviceAdapterMemoryManagerShared::CopyDeviceToDevice(
std::memcpy(dest.GetPointer(), src.GetPointer(), static_cast<std::size_t>(src.GetSize()));
}
void DeviceAdapterMemoryManagerShared::DeleteRawPointer(void* mem) const
{
vtkm::cont::internal::HostDeleter(mem);
}
}
}
} // namespace vtkm::cont::internal

@ -50,6 +50,8 @@ public:
VTKM_CONT virtual void CopyDeviceToDevice(
const vtkm::cont::internal::BufferInfo& src,
const vtkm::cont::internal::BufferInfo& dest) const override;
VTKM_CONT virtual void DeleteRawPointer(void* mem) const override;
};
}
}

@ -153,6 +153,32 @@ void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::CopyDeviceT
static_cast<vtkm::UInt8*>(dest.GetPointer()), static_cast<std::size_t>(size));
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), destView, srcView);
}
// Low level memory management methods
void* DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::AllocateRawPointer(
vtkm::BufferSizeType size) const
{
return vtkm::cont::kokkos::internal::Allocate(size);
}
void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::CopyDeviceToDeviceRawPointer(
const void* src,
void* dest,
vtkm::BufferSizeType size) const
{
Kokkos::View<char*, Kokkos::MemoryTraits<Kokkos::Unmanaged>> destView(static_cast<char*>(dest),
size);
Kokkos::View<const char*, Kokkos::MemoryTraits<Kokkos::Unmanaged>> srcView(
static_cast<const char*>(src), size);
Kokkos::deep_copy(vtkm::cont::kokkos::internal::GetExecutionSpaceInstance(), destView, srcView);
}
void DeviceAdapterMemoryManager<vtkm::cont::DeviceAdapterTagKokkos>::DeleteRawPointer(
void* mem) const
{
vtkm::cont::kokkos::internal::Free(mem);
}
}
}
} // vtkm::cont::internal

@ -50,6 +50,12 @@ public:
VTKM_CONT virtual void CopyDeviceToDevice(
const vtkm::cont::internal::BufferInfo& src,
const vtkm::cont::internal::BufferInfo& dest) const override;
VTKM_CONT void* AllocateRawPointer(vtkm::BufferSizeType size) const override;
VTKM_CONT void CopyDeviceToDeviceRawPointer(const void* src,
void* dest,
vtkm::BufferSizeType size) const override;
VTKM_CONT void DeleteRawPointer(void* mem) const override;
};
}
}

@ -13,6 +13,7 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/DIYMemoryManagement.h>
#include <vtkm/thirdparty/diy/serialization.h>
#include <random>
@ -189,7 +190,9 @@ void TestSerialization(const T& obj, const TestEqualFunctor& test)
master.foreach ([](Block<T>* b, const vtkmdiy::Master::ProxyWithLink& cp) {
cp.enqueue(cp.link()->target(0), b->send);
});
master.exchange();
vtkm::cont::DIYMasterExchange(master);
master.foreach ([](Block<T>* b, const vtkmdiy::Master::ProxyWithLink& cp) {
cp.dequeue(cp.link()->target(1).gid, b->received);
});

@ -92,7 +92,7 @@ static void TwoDimRectilinearTest()
vtkm::Id cells[2][4] = { { 0, 1, 4, 3 }, { 1, 2, 5, 4 } };
for (vtkm::Id cellIndex = 0; cellIndex < 2; cellIndex++)
{
vtkm::Id4 pointIds = pointToCell.GetIndices(pointToCell.FlatToLogicalToIndex(cellIndex));
vtkm::Id4 pointIds = pointToCell.GetIndices(pointToCell.FlatToLogicalVisitIndex(cellIndex));
for (vtkm::IdComponent localPointIndex = 0; localPointIndex < 4; localPointIndex++)
{
VTKM_TEST_ASSERT(pointIds[localPointIndex] == cells[cellIndex][localPointIndex],
@ -106,7 +106,7 @@ static void TwoDimRectilinearTest()
for (vtkm::Id pointIndex = 0; pointIndex < 6; pointIndex++)
{
vtkm::VecVariable<vtkm::Id, 4> retrievedCellIds =
cellToPoint.GetIndices(cellToPoint.FlatToLogicalToIndex(pointIndex));
cellToPoint.GetIndices(cellToPoint.FlatToLogicalVisitIndex(pointIndex));
VTKM_TEST_ASSERT(retrievedCellIds.GetNumberOfComponents() <= 4,
"Got wrong number of cell ids.");
for (vtkm::IdComponent cellIndex = 0; cellIndex < retrievedCellIds.GetNumberOfComponents();

@ -94,7 +94,7 @@ static void TwoDimUniformTest()
vtkm::Id cells[2][4] = { { 0, 1, 4, 3 }, { 1, 2, 5, 4 } };
for (vtkm::Id cellIndex = 0; cellIndex < 2; cellIndex++)
{
vtkm::Id4 pointIds = pointToCell.GetIndices(pointToCell.FlatToLogicalToIndex(cellIndex));
vtkm::Id4 pointIds = pointToCell.GetIndices(pointToCell.FlatToLogicalVisitIndex(cellIndex));
for (vtkm::IdComponent localPointIndex = 0; localPointIndex < 4; localPointIndex++)
{
VTKM_TEST_ASSERT(pointIds[localPointIndex] == cells[cellIndex][localPointIndex],
@ -108,7 +108,7 @@ static void TwoDimUniformTest()
for (vtkm::Id pointIndex = 0; pointIndex < 6; pointIndex++)
{
vtkm::VecVariable<vtkm::Id, 4> retrievedCellIds =
cellToPoint.GetIndices(cellToPoint.FlatToLogicalToIndex(pointIndex));
cellToPoint.GetIndices(cellToPoint.FlatToLogicalVisitIndex(pointIndex));
VTKM_TEST_ASSERT(retrievedCellIds.GetNumberOfComponents() <= 4,
"Got wrong number of cell ids.");
for (vtkm::IdComponent cellIndex = 0; cellIndex < retrievedCellIds.GetNumberOfComponents();

@ -37,6 +37,11 @@ struct BoundaryState
{
}
/// Returns the center index of the neighborhood. This is typically the position of the
/// invocation of the worklet given this boundary condition.
///
VTKM_EXEC const vtkm::Id3& GetCenterIndex() const { return this->IJK; }
///@{
/// Returns true if a neighborhood of the given radius is contained within the bounds of the cell
/// set in the X, Y, or Z direction. Returns false if the neighborhood extends outside of the

@ -11,6 +11,7 @@
#ifndef vtk_m_exec_ConnectivityStructured_h
#define vtk_m_exec_ConnectivityStructured_h
#include <vtkm/Deprecated.h>
#include <vtkm/TopologyElementTag.h>
#include <vtkm/Types.h>
#include <vtkm/internal/ConnectivityStructuredInternals.h>
@ -77,28 +78,54 @@ public:
return Helper::GetIndices(this->Internals, index);
}
VTKM_EXEC_CONT SchedulingRangeType FlatToLogicalVisitIndex(vtkm::Id flatVisitIndex) const
{
return Helper::FlatToLogicalVisitIndex(this->Internals, flatVisitIndex);
}
VTKM_EXEC_CONT SchedulingRangeType FlatToLogicalIncidentIndex(vtkm::Id flatIncidentIndex) const
{
return Helper::FlatToLogicalIncidentIndex(this->Internals, flatIncidentIndex);
}
VTKM_EXEC_CONT vtkm::Id LogicalToFlatVisitIndex(
const SchedulingRangeType& logicalVisitIndex) const
{
return Helper::LogicalToFlatVisitIndex(this->Internals, logicalVisitIndex);
}
VTKM_EXEC_CONT vtkm::Id LogicalToFlatIncidentIndex(
const SchedulingRangeType& logicalIncidentIndex) const
{
return Helper::LogicalToFlatIncidentIndex(this->Internals, logicalIncidentIndex);
}
VTKM_EXEC_CONT
VTKM_DEPRECATED(2.1, "Use FlatToLogicalIncidentIndex.")
SchedulingRangeType FlatToLogicalFromIndex(vtkm::Id flatFromIndex) const
{
return Helper::FlatToLogicalFromIndex(this->Internals, flatFromIndex);
return this->FlatToLogicalIncidentIndex(flatFromIndex);
}
VTKM_EXEC_CONT
VTKM_DEPRECATED(2.1, "Use LogicalToFlatIncidentIndex.")
vtkm::Id LogicalToFlatFromIndex(const SchedulingRangeType& logicalFromIndex) const
{
return Helper::LogicalToFlatFromIndex(this->Internals, logicalFromIndex);
return this->LogicalToFlatIncidentIndex(logicalFromIndex);
}
VTKM_EXEC_CONT
VTKM_DEPRECATED(2.1, "Use FlatToLogicalVisitIndex.")
SchedulingRangeType FlatToLogicalToIndex(vtkm::Id flatToIndex) const
{
return Helper::FlatToLogicalToIndex(this->Internals, flatToIndex);
return this->FlatToLogicalVisitIndex(flatToIndex);
}
VTKM_EXEC_CONT
VTKM_DEPRECATED(2.1, "Use LogicalToFlatVisitIndex.")
vtkm::Id LogicalToFlatToIndex(const SchedulingRangeType& logicalToIndex) const
{
return Helper::LogicalToFlatToIndex(this->Internals, logicalToIndex);
return this->LogicalToFlatVisitIndex(logicalToIndex);
}
VTKM_EXEC_CONT

@ -72,7 +72,7 @@ public:
inputIndex,
visitIndex,
outputIndex,
vtkm::exec::BoundaryState{ detail::To3D(connectivity.FlatToLogicalToIndex(inputIndex)),
vtkm::exec::BoundaryState{ detail::To3D(connectivity.FlatToLogicalVisitIndex(inputIndex)),
detail::To3D(connectivity.GetPointDimensions()) })
{
}

@ -181,7 +181,7 @@ public:
this->InputIndex = inputIndex;
this->VisitIndex = visitIndex;
this->OutputIndex = outputIndex;
this->LogicalIndex = connectivity.FlatToLogicalToIndex(this->InputIndex);
this->LogicalIndex = connectivity.FlatToLogicalVisitIndex(this->InputIndex);
this->IndicesIncident = connectivity.GetIndices(this->LogicalIndex);
this->CellShape = connectivity.GetCellShape(this->InputIndex);
}
@ -338,7 +338,7 @@ public:
const ConnectivityType& connectivity)
{
this->ThreadIndex = threadIndex;
this->LogicalIndex = connectivity.FlatToLogicalToIndex(inputIndex);
this->LogicalIndex = connectivity.FlatToLogicalVisitIndex(inputIndex);
this->IndicesIncident = connectivity.GetIndices(this->LogicalIndex);
this->CellShape = connectivity.GetCellShape(inputIndex);
}
@ -503,7 +503,7 @@ public:
this->OutputIndex = outputIndex;
const vtkm::Id permutedIndex = permutation.Portal.Get(this->InputIndex);
this->LogicalIndex = permutation.Connectivity.FlatToLogicalToIndex(permutedIndex);
this->LogicalIndex = permutation.Connectivity.FlatToLogicalVisitIndex(permutedIndex);
this->IndicesIncident = permutation.Connectivity.GetIndices(this->LogicalIndex);
this->CellShape = permutation.Connectivity.GetCellShape(permutedIndex);
}

@ -78,6 +78,14 @@ public:
VTKM_CONT
void SetIncludeBoundary(bool value) { this->IncludeBoundary = value; }
/// Set if VOI is specified in global (rather than in local) point indices
/// (NOTE: Depracted this method since this does not seem to work as
/// expected and there are no tests for it. Furthermore, neither VTK-m nor
/// VTK-h/Ascent seem to use this method. If your are using this method
/// somewhere else and think it should remain, please open a merge request to
/// "de-deprecate" it and add a test and documentation of the expected
/// behavior.)
VTKM_DEPRECATED(2.1)
VTKM_CONT
void SetIncludeOffset(bool value) { this->IncludeOffset = value; }

@ -26,6 +26,14 @@ public:
std::cout << "Testing extract structured uniform" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make2DUniformDataSet1();
// Change point index start from 0, 0 to 10, 14
vtkm::cont::CellSetStructured<2> cellSet;
dataset.GetCellSet().AsCellSet(cellSet);
cellSet.SetGlobalPointDimensions(vtkm::Id2{ 15, 19 });
cellSet.SetGlobalPointIndexStart(vtkm::Id2{ 10, 14 });
dataset.SetCellSet(cellSet);
dataset.PrintSummary(std::cout);
vtkm::RangeId3 range(1, 4, 1, 4, 0, 1);
vtkm::Id3 sample(1, 1, 1);
@ -39,6 +47,17 @@ public:
"Wrong result for ExtractStructured worklet");
VTKM_TEST_ASSERT(test_equal(output.GetNumberOfCells(), 4),
"Wrong result for ExtractStructured worklet");
vtkm::cont::CellSetStructured<2> outputCellSet;
output.GetCellSet().AsCellSet(outputCellSet);
VTKM_TEST_ASSERT(test_equal(outputCellSet.GetGlobalPointIndexStart()[0], 11),
"Wrong result for ExtractStructured PointIndexStart");
VTKM_TEST_ASSERT(test_equal(outputCellSet.GetGlobalPointIndexStart()[1], 15),
"Wrong result for ExtractStructured PointIndexStart");
VTKM_TEST_ASSERT(test_equal(outputCellSet.GetGlobalPointDimensions()[0], 15),
"Wrong result for ExtractStructured GlobalPointDimensions");
VTKM_TEST_ASSERT(test_equal(outputCellSet.GetGlobalPointDimensions()[1], 19),
"Wrong result for ExtractStructured GlobalPointDimensions");
vtkm::cont::ArrayHandle<vtkm::Float32> outPointData;
output.GetField("pointvar").GetData().AsArrayHandle(outPointData);

@ -136,6 +136,7 @@ private:
static UncertainCellSetStructured MakeCellSetStructured(
const vtkm::Id3& inputPointDims,
const vtkm::Id3& inputOffsets,
const vtkm::Id3& inputGlobalPointDims,
vtkm::IdComponent forcedDimensionality = 0)
{
// when the point dimension for a given axis is 1 we
@ -146,12 +147,22 @@ private:
vtkm::IdComponent dimensionality = forcedDimensionality;
vtkm::Id3 dimensions = inputPointDims;
vtkm::Id3 offset = inputOffsets;
vtkm::Id3 globalDimensions = inputGlobalPointDims;
for (int i = 0; i < 3 && (forcedDimensionality == 0); ++i)
{
if (inputPointDims[i] > 1)
{
dimensions[dimensionality] = inputPointDims[i];
offset[dimensionality] = inputOffsets[i];
// TODO/FIXME: This may not be the correct way to handle global point dims.
// E.g., if we preserve the input global point dims (default) then they may
// have a higher dimensionility than the returned data set. In that case,
// the approach here will result in an incorrect value for GlobalPointDimensions.
// This is the simplest approach, which should work in most use cases for this
// filter, but if this choice causes further problems down the way, we may need
// to rethink it.
globalDimensions[dimensionality] = inputGlobalPointDims[i];
++dimensionality;
}
}
@ -163,6 +174,7 @@ private:
vtkm::cont::CellSetStructured<1> outCs;
outCs.SetPointDimensions(dimensions[0]);
outCs.SetGlobalPointIndexStart(offset[0]);
outCs.SetGlobalPointDimensions(globalDimensions[0]);
return outCs;
}
case 2:
@ -170,6 +182,7 @@ private:
vtkm::cont::CellSetStructured<2> outCs;
outCs.SetPointDimensions(vtkm::Id2(dimensions[0], dimensions[1]));
outCs.SetGlobalPointIndexStart(vtkm::Id2(offset[0], offset[1]));
outCs.SetGlobalPointDimensions(vtkm::Id2(globalDimensions[0], globalDimensions[1]));
return outCs;
}
case 3:
@ -177,6 +190,7 @@ private:
vtkm::cont::CellSetStructured<3> outCs;
outCs.SetPointDimensions(dimensions);
outCs.SetGlobalPointIndexStart(offset);
outCs.SetGlobalPointDimensions(globalDimensions);
return outCs;
}
default:
@ -193,9 +207,11 @@ public:
{
vtkm::Id pdims = cellset.GetPointDimensions();
vtkm::Id offsets = cellset.GetGlobalPointIndexStart();
vtkm::Id gpdims = cellset.GetGlobalPointDimensions();
return this->Compute(1,
vtkm::Id3{ pdims, 1, 1 },
vtkm::Id3{ offsets, 0, 0 },
vtkm::Id3{ gpdims, 1, 1 },
voi,
sampleRate,
includeBoundary,
@ -210,9 +226,11 @@ public:
{
vtkm::Id2 pdims = cellset.GetPointDimensions();
vtkm::Id2 offsets = cellset.GetGlobalPointIndexStart();
vtkm::Id2 gpdims = cellset.GetGlobalPointDimensions();
return this->Compute(2,
vtkm::Id3{ pdims[0], pdims[1], 1 },
vtkm::Id3{ offsets[0], offsets[1], 0 },
vtkm::Id3{ gpdims[0], gpdims[1], 1 },
voi,
sampleRate,
includeBoundary,
@ -227,12 +245,15 @@ public:
{
vtkm::Id3 pdims = cellset.GetPointDimensions();
vtkm::Id3 offsets = cellset.GetGlobalPointIndexStart();
return this->Compute(3, pdims, offsets, voi, sampleRate, includeBoundary, includeOffset);
vtkm::Id3 gpdims = cellset.GetGlobalPointDimensions();
return this->Compute(
3, pdims, offsets, gpdims, voi, sampleRate, includeBoundary, includeOffset);
}
UncertainCellSetStructured Compute(const int dimensionality,
const vtkm::Id3& ptdim,
const vtkm::Id3& offsets,
const vtkm::Id3& gpdims,
const vtkm::RangeId3& voi,
const vtkm::Id3& sampleRate,
bool includeBoundary,
@ -241,6 +262,7 @@ public:
// Verify input parameters
vtkm::Id3 offset_vec(0, 0, 0);
vtkm::Id3 globalOffset(0, 0, 0);
vtkm::Id3 globalPointDimensions = gpdims;
this->InputDimensions = ptdim;
this->InputDimensionality = dimensionality;
@ -315,7 +337,7 @@ public:
if (!this->VOI.IsNonEmpty())
{
vtkm::Id3 empty = { 0, 0, 0 };
return MakeCellSetStructured(empty, empty, dimensionality);
return MakeCellSetStructured(empty, empty, globalPointDimensions, dimensionality);
}
if (!includeOffset)
{
@ -354,9 +376,15 @@ public:
MakeAxisIndexArrayCells(vtkm::Max(vtkm::Id(1), this->OutputDimensions[2] - 1),
this->VOI.Z.Min,
this->SampleRate[2]));
// compute global point origin
for (int i = 0; i < dimensionality; ++i)
{
globalOffset[i] = offsets[i] + this->VOI[i].Min;
}
}
return MakeCellSetStructured(this->OutputDimensions, globalOffset);
return MakeCellSetStructured(this->OutputDimensions, globalOffset, globalPointDimensions);
}

@ -37,12 +37,23 @@ vtkm_unit_tests(
#if MPI is enabled.
if (VTKm_ENABLE_MPI)
set(mpi_unit_tests
UnitTestAdvectionAsynchronousMPI.cxx
UnitTestAdvectionSynchronousMPI.cxx
UnitTestParticleMessengerMPI.cxx
UnitTestStreamlineFilterMPI.cxx
)
UnitTestPathlineAsynchronousMPI.cxx
UnitTestPathlineSynchronousMPI.cxx
UnitTestStreamlineAMRMPI.cxx
UnitTestStreamlineAsynchronousMPI.cxx
UnitTestStreamlineSynchronousMPI.cxx
)
set(mpi_helpers
TestingFlow.cxx
TestingFlow.h
)
set_source_files_properties(${mpi_helpers} PROPERTIES NOT_A_TEST TRUE)
vtkm_unit_tests(
MPI
DEVICE_SOURCES ${mpi_unit_tests}
SOURCES ${mpi_unit_tests} ${mpi_helpers}
USE_VTKM_JOB_POOL
)
endif()

@ -0,0 +1,313 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/CellClassification.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/flow/ParticleAdvection.h>
#include <vtkm/filter/flow/Pathline.h>
#include <vtkm/filter/flow/Streamline.h>
#include <vtkm/thirdparty/diy/diy.h>
#include <vtkm/worklet/testing/GenerateTestDataSets.h>
vtkm::cont::ArrayHandle<vtkm::Vec3f> CreateConstantVectorField(vtkm::Id num, const vtkm::Vec3f& vec)
{
vtkm::cont::ArrayHandleConstant<vtkm::Vec3f> vecConst;
vecConst = vtkm::cont::make_ArrayHandleConstant(vec, num);
vtkm::cont::ArrayHandle<vtkm::Vec3f> vecField;
vtkm::cont::ArrayCopy(vecConst, vecField);
return vecField;
}
void AddVectorFields(vtkm::cont::PartitionedDataSet& pds,
const std::string& fieldName,
const vtkm::Vec3f& vec)
{
for (auto& ds : pds)
ds.AddPointField(fieldName, CreateConstantVectorField(ds.GetNumberOfPoints(), vec));
}
std::vector<vtkm::cont::PartitionedDataSet> CreateAllDataSetBounds(vtkm::Id nPerRank, bool useGhost)
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
vtkm::Id totNumBlocks = nPerRank * comm.size();
vtkm::Id numDims = 5;
vtkm::FloatDefault x0 = 0;
vtkm::FloatDefault x1 = x0 + static_cast<vtkm::FloatDefault>(numDims - 1);
vtkm::FloatDefault dx = x1 - x0;
vtkm::FloatDefault y0 = 0, y1 = numDims - 1, z0 = 0, z1 = numDims - 1;
if (useGhost)
{
numDims = numDims + 2; //add 1 extra on each side
x0 = x0 - 1;
x1 = x1 + 1;
dx = x1 - x0 - 2;
y0 = y0 - 1;
y1 = y1 + 1;
z0 = z0 - 1;
z1 = z1 + 1;
}
//Create ALL of the blocks.
std::vector<vtkm::Bounds> bounds;
for (vtkm::Id i = 0; i < totNumBlocks; i++)
{
bounds.push_back(vtkm::Bounds(x0, x1, y0, y1, z0, z1));
x0 += dx;
x1 += dx;
}
const vtkm::Id3 dims(numDims, numDims, numDims);
auto allPDS = vtkm::worklet::testing::CreateAllDataSets(bounds, dims, useGhost);
return allPDS;
}
std::vector<vtkm::Range> ExtractMaxXRanges(const vtkm::cont::PartitionedDataSet& pds, bool useGhost)
{
std::vector<vtkm::Range> xMaxRanges;
for (const auto& ds : pds.GetPartitions())
{
auto bounds = ds.GetCoordinateSystem().GetBounds();
auto xMax = bounds.X.Max;
if (useGhost)
xMax = xMax - 1;
xMaxRanges.push_back(vtkm::Range(xMax, xMax + static_cast<vtkm::FloatDefault>(.5)));
}
return xMaxRanges;
}
void ValidateOutput(const vtkm::cont::DataSet& out,
vtkm::Id numSeeds,
const vtkm::Range& xMaxRange,
FilterType fType,
bool checkEndPoint,
bool blockDuplication)
{
//Validate the result is correct.
VTKM_TEST_ASSERT(out.GetNumberOfCoordinateSystems() == 1,
"Wrong number of coordinate systems in the output dataset");
vtkm::cont::UnknownCellSet dcells = out.GetCellSet();
vtkm::Id numCells = out.GetNumberOfCells();
if (!blockDuplication)
VTKM_TEST_ASSERT(numCells == numSeeds, "Wrong number of cells");
auto coords = out.GetCoordinateSystem().GetDataAsMultiplexer();
auto ptPortal = coords.ReadPortal();
if (fType == STREAMLINE || fType == PATHLINE)
{
vtkm::cont::CellSetExplicit<> explicitCells;
VTKM_TEST_ASSERT(dcells.IsType<vtkm::cont::CellSetExplicit<>>(), "Wrong cell type.");
explicitCells = dcells.AsCellSet<vtkm::cont::CellSetExplicit<>>();
for (vtkm::Id j = 0; j < numCells; j++)
{
vtkm::cont::ArrayHandle<vtkm::Id> indices;
explicitCells.GetIndices(j, indices);
vtkm::Id nPts = indices.GetNumberOfValues();
auto iPortal = indices.ReadPortal();
vtkm::Vec3f lastPt = ptPortal.Get(iPortal.Get(nPts - 1));
if (checkEndPoint)
VTKM_TEST_ASSERT(xMaxRange.Contains(lastPt[0]), "Wrong end point for seed");
}
}
else if (fType == PARTICLE_ADVECTION)
{
if (!blockDuplication)
VTKM_TEST_ASSERT(out.GetNumberOfPoints() == numSeeds, "Wrong number of coordinates");
if (checkEndPoint)
{
for (vtkm::Id i = 0; i < numCells; i++)
VTKM_TEST_ASSERT(xMaxRange.Contains(ptPortal.Get(i)[0]), "Wrong end point for seed");
}
}
}
void TestPartitionedDataSet(vtkm::Id nPerRank,
bool useGhost,
FilterType fType,
bool useThreaded,
bool useAsyncComm,
bool useBlockIds,
bool duplicateBlocks)
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
if (comm.rank() == 0)
{
switch (fType)
{
case PARTICLE_ADVECTION:
std::cout << "Particle advection";
break;
case STREAMLINE:
std::cout << "Streamline";
break;
case PATHLINE:
std::cout << "Pathline";
break;
}
std::cout << " blocksPerRank= " << nPerRank;
if (useGhost)
std::cout << " - using ghost cells";
if (useThreaded)
std::cout << " - using threaded";
if (useAsyncComm)
std::cout << " - usingAsyncComm";
else
std::cout << " - usingSyncComm";
if (useBlockIds)
std::cout << " - using block IDs";
if (duplicateBlocks)
std::cout << " - with duplicate blocks";
std::cout << " - on a partitioned data set" << std::endl;
}
std::vector<vtkm::Id> blockIds;
//Uniform assignment.
for (vtkm::Id i = 0; i < nPerRank; i++)
blockIds.push_back(comm.rank() * nPerRank + i);
//For block duplication, give everyone the 2nd to last block.
//We want to keep the last block on the last rank for validation.
if (duplicateBlocks && blockIds.size() > 1)
{
vtkm::Id totNumBlocks = comm.size() * nPerRank;
vtkm::Id dupBlock = totNumBlocks - 2;
for (int r = 0; r < comm.size(); r++)
{
if (std::find(blockIds.begin(), blockIds.end(), dupBlock) == blockIds.end())
blockIds.push_back(dupBlock);
}
}
std::vector<vtkm::cont::PartitionedDataSet> allPDS, allPDS2;
allPDS = CreateAllDataSetBounds(nPerRank, useGhost);
allPDS2 = CreateAllDataSetBounds(nPerRank, useGhost);
auto xMaxRanges = ExtractMaxXRanges(allPDS[0], useGhost);
vtkm::FloatDefault time0 = 0;
vtkm::FloatDefault time1 = xMaxRanges[xMaxRanges.size() - 1].Max;
vtkm::Vec3f vecX(1, 0, 0);
std::string fieldName = "vec";
vtkm::FloatDefault stepSize = 0.1f;
vtkm::Id numSteps = 100000;
for (std::size_t n = 0; n < allPDS.size(); n++)
{
vtkm::cont::PartitionedDataSet pds;
for (const auto& bid : blockIds)
pds.AppendPartition(allPDS[n].GetPartition(bid));
AddVectorFields(pds, fieldName, vecX);
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray;
seedArray = vtkm::cont::make_ArrayHandle({ vtkm::Particle(vtkm::Vec3f(.2f, 1.0f, .2f), 0),
vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1) });
vtkm::Id numSeeds = seedArray.GetNumberOfValues();
if (fType == STREAMLINE)
{
vtkm::filter::flow::Streamline streamline;
SetFilter(streamline,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
auto out = streamline.Execute(pds);
vtkm::Id numOutputs = out.GetNumberOfPartitions();
bool checkEnds = numOutputs == static_cast<vtkm::Id>(blockIds.size());
for (vtkm::Id i = 0; i < numOutputs; i++)
{
ValidateOutput(out.GetPartition(i),
numSeeds,
xMaxRanges[blockIds[i]],
fType,
checkEnds,
duplicateBlocks);
}
}
else if (fType == PARTICLE_ADVECTION)
{
vtkm::filter::flow::ParticleAdvection particleAdvection;
SetFilter(particleAdvection,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
auto out = particleAdvection.Execute(pds);
//Particles end up in last rank.
if (comm.rank() == comm.size() - 1)
{
bool checkEnds = out.GetNumberOfPartitions() == static_cast<vtkm::Id>(blockIds.size());
VTKM_TEST_ASSERT(out.GetNumberOfPartitions() == 1, "Wrong number of partitions in output");
ValidateOutput(out.GetPartition(0),
numSeeds,
xMaxRanges[xMaxRanges.size() - 1],
fType,
checkEnds,
duplicateBlocks);
}
else
VTKM_TEST_ASSERT(out.GetNumberOfPartitions() == 0, "Wrong number of partitions in output");
}
else if (fType == PATHLINE)
{
vtkm::cont::PartitionedDataSet pds2;
for (const auto& bid : blockIds)
pds2.AppendPartition(allPDS2[n].GetPartition(bid));
AddVectorFields(pds2, fieldName, vecX);
vtkm::filter::flow::Pathline pathline;
SetFilter(pathline,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
pathline.SetPreviousTime(time0);
pathline.SetNextTime(time1);
pathline.SetNextDataSet(pds2);
auto out = pathline.Execute(pds);
vtkm::Id numOutputs = out.GetNumberOfPartitions();
bool checkEnds = numOutputs == static_cast<vtkm::Id>(blockIds.size());
for (vtkm::Id i = 0; i < numOutputs; i++)
ValidateOutput(out.GetPartition(i),
numSeeds,
xMaxRanges[blockIds[i]],
fType,
checkEnds,
duplicateBlocks);
}
}
}

@ -0,0 +1,82 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_filter_flow_testing_TestingFlow_h
#define vtk_m_filter_flow_testing_TestingFlow_h
#include <vtkm/Particle.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vector>
enum FilterType
{
PARTICLE_ADVECTION,
STREAMLINE,
PATHLINE
};
vtkm::cont::ArrayHandle<vtkm::Vec3f> CreateConstantVectorField(vtkm::Id num,
const vtkm::Vec3f& vec);
void AddVectorFields(vtkm::cont::PartitionedDataSet& pds,
const std::string& fieldName,
const vtkm::Vec3f& vec);
std::vector<vtkm::cont::PartitionedDataSet> CreateAllDataSetBounds(vtkm::Id nPerRank,
bool useGhost);
std::vector<vtkm::Range> ExtractMaxXRanges(const vtkm::cont::PartitionedDataSet& pds,
bool useGhost);
template <typename FilterType>
void SetFilter(FilterType& filter,
vtkm::FloatDefault stepSize,
vtkm::Id numSteps,
const std::string& fieldName,
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray,
bool useThreaded,
bool useAsyncComm,
bool useBlockIds,
const std::vector<vtkm::Id>& blockIds)
{
filter.SetStepSize(stepSize);
filter.SetNumberOfSteps(numSteps);
filter.SetSeeds(seedArray);
filter.SetActiveField(fieldName);
filter.SetUseThreadedAlgorithm(useThreaded);
if (useAsyncComm)
filter.SetUseAsynchronousCommunication();
else
filter.SetUseSynchronousCommunication();
if (useBlockIds)
filter.SetBlockIDs(blockIds);
}
void ValidateOutput(const vtkm::cont::DataSet& out,
vtkm::Id numSeeds,
const vtkm::Range& xMaxRange,
FilterType fType,
bool checkEndPoint,
bool blockDuplication);
void TestPartitionedDataSet(vtkm::Id nPerRank,
bool useGhost,
FilterType fType,
bool useThreaded,
bool useAsyncComm,
bool useBlockIds,
bool duplicateBlocks);
#endif // vtk_m_filter_flow_testing_TestingFlow_h

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = PARTICLE_ADVECTION;
bool useAsyncComm = true;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestAdvectionAsynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = PARTICLE_ADVECTION;
bool useAsyncComm = false;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestAdvectionSynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = PATHLINE;
bool useAsyncComm = true;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestPathlineAsynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = PATHLINE;
bool useAsyncComm = false;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestPathlineSynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -45,60 +45,6 @@ void AddVectorFields(vtkm::cont::PartitionedDataSet& pds,
ds.AddPointField(fieldName, CreateConstantVectorField(ds.GetNumberOfPoints(), vec));
}
std::vector<vtkm::cont::PartitionedDataSet> CreateAllDataSetBounds(vtkm::Id nPerRank, bool useGhost)
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
vtkm::Id totNumBlocks = nPerRank * comm.size();
vtkm::Id numDims = 5;
vtkm::FloatDefault x0 = 0;
vtkm::FloatDefault x1 = x0 + static_cast<vtkm::FloatDefault>(numDims - 1);
vtkm::FloatDefault dx = x1 - x0;
vtkm::FloatDefault y0 = 0, y1 = numDims - 1, z0 = 0, z1 = numDims - 1;
if (useGhost)
{
numDims = numDims + 2; //add 1 extra on each side
x0 = x0 - 1;
x1 = x1 + 1;
dx = x1 - x0 - 2;
y0 = y0 - 1;
y1 = y1 + 1;
z0 = z0 - 1;
z1 = z1 + 1;
}
//Create ALL of the blocks.
std::vector<vtkm::Bounds> bounds;
for (vtkm::Id i = 0; i < totNumBlocks; i++)
{
bounds.push_back(vtkm::Bounds(x0, x1, y0, y1, z0, z1));
x0 += dx;
x1 += dx;
}
const vtkm::Id3 dims(numDims, numDims, numDims);
auto allPDS = vtkm::worklet::testing::CreateAllDataSets(bounds, dims, useGhost);
return allPDS;
}
std::vector<vtkm::Range> ExtractMaxXRanges(const vtkm::cont::PartitionedDataSet& pds, bool useGhost)
{
std::vector<vtkm::Range> xMaxRanges;
for (const auto& ds : pds.GetPartitions())
{
auto bounds = ds.GetCoordinateSystem().GetBounds();
auto xMax = bounds.X.Max;
if (useGhost)
xMax = xMax - 1;
xMaxRanges.push_back(vtkm::Range(xMax, xMax + static_cast<vtkm::FloatDefault>(.5)));
}
return xMaxRanges;
}
template <typename FilterType>
void SetFilter(FilterType& filter,
vtkm::FloatDefault stepSize,
@ -356,265 +302,29 @@ void TestAMRStreamline(FilterType fType, bool useThreaded, bool useAsyncComm)
}
}
void ValidateOutput(const vtkm::cont::DataSet& out,
vtkm::Id numSeeds,
const vtkm::Range& xMaxRange,
FilterType fType,
bool checkEndPoint,
bool blockDuplication)
{
//Validate the result is correct.
VTKM_TEST_ASSERT(out.GetNumberOfCoordinateSystems() == 1,
"Wrong number of coordinate systems in the output dataset");
vtkm::cont::UnknownCellSet dcells = out.GetCellSet();
vtkm::Id numCells = out.GetNumberOfCells();
if (!blockDuplication)
VTKM_TEST_ASSERT(numCells == numSeeds, "Wrong number of cells");
auto coords = out.GetCoordinateSystem().GetDataAsMultiplexer();
auto ptPortal = coords.ReadPortal();
if (fType == STREAMLINE || fType == PATHLINE)
{
vtkm::cont::CellSetExplicit<> explicitCells;
VTKM_TEST_ASSERT(dcells.IsType<vtkm::cont::CellSetExplicit<>>(), "Wrong cell type.");
explicitCells = dcells.AsCellSet<vtkm::cont::CellSetExplicit<>>();
for (vtkm::Id j = 0; j < numCells; j++)
{
vtkm::cont::ArrayHandle<vtkm::Id> indices;
explicitCells.GetIndices(j, indices);
vtkm::Id nPts = indices.GetNumberOfValues();
auto iPortal = indices.ReadPortal();
vtkm::Vec3f lastPt = ptPortal.Get(iPortal.Get(nPts - 1));
if (checkEndPoint)
VTKM_TEST_ASSERT(xMaxRange.Contains(lastPt[0]), "Wrong end point for seed");
}
}
else if (fType == PARTICLE_ADVECTION)
{
if (!blockDuplication)
VTKM_TEST_ASSERT(out.GetNumberOfPoints() == numSeeds, "Wrong number of coordinates");
if (checkEndPoint)
{
for (vtkm::Id i = 0; i < numCells; i++)
VTKM_TEST_ASSERT(xMaxRange.Contains(ptPortal.Get(i)[0]), "Wrong end point for seed");
}
}
}
void TestPartitionedDataSet(vtkm::Id nPerRank,
bool useGhost,
FilterType fType,
bool useThreaded,
bool useAsyncComm,
bool useBlockIds,
bool duplicateBlocks)
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
if (comm.rank() == 0)
{
switch (fType)
{
case PARTICLE_ADVECTION:
std::cout << "Particle advection";
break;
case STREAMLINE:
std::cout << "Streamline";
break;
case PATHLINE:
std::cout << "Pathline";
break;
}
std::cout << " blocksPerRank= " << nPerRank;
if (useGhost)
std::cout << " - using ghost cells";
if (useThreaded)
std::cout << " - using threaded";
if (useAsyncComm)
std::cout << " - usingAsyncComm";
else
std::cout << " - usingSyncComm";
if (useBlockIds)
std::cout << " - using block IDs";
if (duplicateBlocks)
std::cout << " - with duplicate blocks";
std::cout << " - on a partitioned data set" << std::endl;
std::cout << std::endl << "*** TestStreamlineAMRMPI" << std::endl;
}
std::vector<vtkm::Id> blockIds;
//Uniform assignment.
for (vtkm::Id i = 0; i < nPerRank; i++)
blockIds.push_back(comm.rank() * nPerRank + i);
//For block duplication, give everyone the 2nd to last block.
//We want to keep the last block on the last rank for validation.
if (duplicateBlocks && blockIds.size() > 1)
for (auto fType : { PARTICLE_ADVECTION, STREAMLINE, PATHLINE })
{
vtkm::Id totNumBlocks = comm.size() * nPerRank;
vtkm::Id dupBlock = totNumBlocks - 2;
for (int r = 0; r < comm.size(); r++)
for (auto useThreaded : { true, false })
{
if (std::find(blockIds.begin(), blockIds.end(), dupBlock) == blockIds.end())
blockIds.push_back(dupBlock);
}
}
std::vector<vtkm::cont::PartitionedDataSet> allPDS, allPDS2;
allPDS = CreateAllDataSetBounds(nPerRank, useGhost);
allPDS2 = CreateAllDataSetBounds(nPerRank, useGhost);
auto xMaxRanges = ExtractMaxXRanges(allPDS[0], useGhost);
vtkm::FloatDefault time0 = 0;
vtkm::FloatDefault time1 = xMaxRanges[xMaxRanges.size() - 1].Max;
vtkm::Vec3f vecX(1, 0, 0);
std::string fieldName = "vec";
vtkm::FloatDefault stepSize = 0.1f;
vtkm::Id numSteps = 100000;
for (std::size_t n = 0; n < allPDS.size(); n++)
{
vtkm::cont::PartitionedDataSet pds;
for (const auto& bid : blockIds)
pds.AppendPartition(allPDS[n].GetPartition(bid));
AddVectorFields(pds, fieldName, vecX);
vtkm::cont::ArrayHandle<vtkm::Particle> seedArray;
seedArray = vtkm::cont::make_ArrayHandle({ vtkm::Particle(vtkm::Vec3f(.2f, 1.0f, .2f), 0),
vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1) });
vtkm::Id numSeeds = seedArray.GetNumberOfValues();
if (fType == STREAMLINE)
{
vtkm::filter::flow::Streamline streamline;
SetFilter(streamline,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
auto out = streamline.Execute(pds);
vtkm::Id numOutputs = out.GetNumberOfPartitions();
bool checkEnds = numOutputs == static_cast<vtkm::Id>(blockIds.size());
for (vtkm::Id i = 0; i < numOutputs; i++)
for (auto useAsyncComm : { true, false })
{
ValidateOutput(out.GetPartition(i),
numSeeds,
xMaxRanges[blockIds[i]],
fType,
checkEnds,
duplicateBlocks);
}
}
else if (fType == PARTICLE_ADVECTION)
{
vtkm::filter::flow::ParticleAdvection particleAdvection;
SetFilter(particleAdvection,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
auto out = particleAdvection.Execute(pds);
//Particles end up in last rank.
if (comm.rank() == comm.size() - 1)
{
bool checkEnds = out.GetNumberOfPartitions() == static_cast<vtkm::Id>(blockIds.size());
VTKM_TEST_ASSERT(out.GetNumberOfPartitions() == 1, "Wrong number of partitions in output");
ValidateOutput(out.GetPartition(0),
numSeeds,
xMaxRanges[xMaxRanges.size() - 1],
fType,
checkEnds,
duplicateBlocks);
}
else
VTKM_TEST_ASSERT(out.GetNumberOfPartitions() == 0, "Wrong number of partitions in output");
}
else if (fType == PATHLINE)
{
vtkm::cont::PartitionedDataSet pds2;
for (const auto& bid : blockIds)
pds2.AppendPartition(allPDS2[n].GetPartition(bid));
AddVectorFields(pds2, fieldName, vecX);
vtkm::filter::flow::Pathline pathline;
SetFilter(pathline,
stepSize,
numSteps,
fieldName,
seedArray,
useThreaded,
useAsyncComm,
useBlockIds,
blockIds);
pathline.SetPreviousTime(time0);
pathline.SetNextTime(time1);
pathline.SetNextDataSet(pds2);
auto out = pathline.Execute(pds);
vtkm::Id numOutputs = out.GetNumberOfPartitions();
bool checkEnds = numOutputs == static_cast<vtkm::Id>(blockIds.size());
for (vtkm::Id i = 0; i < numOutputs; i++)
ValidateOutput(out.GetPartition(i),
numSeeds,
xMaxRanges[blockIds[i]],
fType,
checkEnds,
duplicateBlocks);
}
}
}
void TestStreamlineFiltersMPI()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
if (comm.rank() == 0)
std::cout << std::endl << "*** TestStreamlineFiltersMPI" << std::endl;
std::vector<bool> flags = { true, false };
std::vector<FilterType> filterTypes = { PARTICLE_ADVECTION, STREAMLINE, PATHLINE };
for (int n = 1; n < 3; n++)
for (auto useGhost : flags)
for (auto fType : filterTypes)
for (auto useThreaded : flags)
for (auto useAsyncComm : flags)
for (auto useBlockIds : flags)
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
n, useGhost, fType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
n, useGhost, fType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
TestPartitionedDataSet(
n, useGhost, fType, useThreaded, useAsyncComm, useBlockIds, false);
}
for (auto fType : filterTypes)
for (auto useThreaded : flags)
for (auto useAsyncComm : flags)
TestAMRStreamline(fType, useThreaded, useAsyncComm);
}
}
}
}
}
int UnitTestStreamlineFilterMPI(int argc, char* argv[])
} // anonymous namespace
int UnitTestStreamlineAMRMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestStreamlineFiltersMPI, argc, argv);
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = STREAMLINE;
bool useAsyncComm = true;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestStreamlineAsynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -0,0 +1,59 @@
//============================================================================
// 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.
//============================================================================
#include "TestingFlow.h"
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void DoTest()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
FilterType filterType = STREAMLINE;
bool useAsyncComm = false;
for (vtkm::Id nPerRank = 1; nPerRank < 3; ++nPerRank)
{
for (bool useGhost : { true, false })
{
for (bool useThreaded : { true, false })
{
for (bool useBlockIds : { true, false })
{
//Run blockIds with and without block duplication.
if (useBlockIds && comm.size() > 1)
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, true);
}
else
{
TestPartitionedDataSet(
nPerRank, useGhost, filterType, useThreaded, useAsyncComm, useBlockIds, false);
}
}
}
}
}
}
} // anonymous namespace
int UnitTestStreamlineSynchronousMPI(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -78,15 +78,17 @@ void TestWithExplicitData()
"Wrong point field data");
}
const auto& connectivityArray =
output.GetCellSet().AsCellSet<vtkm::cont::CellSetExplicit<>>().GetConnectivityArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto connectivityArrayPortal = connectivityArray.ReadPortal();
for (vtkm::IdComponent i = 0; i < connectivityArray.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(test_equal(connectivityArrayPortal.Get(i), expectedConnectivityArray[i]),
"Wrong connectivity array value");
const auto connectivityArray =
output.GetCellSet().AsCellSet<vtkm::cont::CellSetExplicit<>>().GetConnectivityArray(
vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto connectivityArrayPortal = connectivityArray.ReadPortal();
for (vtkm::IdComponent i = 0; i < connectivityArray.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(test_equal(connectivityArrayPortal.Get(i), expectedConnectivityArray[i]),
"Wrong connectivity array value");
}
}
auto newCoords = output.GetCoordinateSystem().GetDataAsMultiplexer();

@ -21,18 +21,6 @@ namespace filter
{
namespace image_processing
{
using SupportedTypes = vtkm::List<vtkm::Float32,
vtkm::Float64,
vtkm::Vec<vtkm::Float32, 2>,
vtkm::Vec<vtkm::Float64, 2>,
vtkm::Vec<vtkm::Float32, 3>,
vtkm::Vec<vtkm::Float64, 3>,
vtkm::Vec<vtkm::Float32, 4>,
vtkm::Vec<vtkm::Float64, 4>,
vtkm::Vec<vtkm::Float32, 6>,
vtkm::Vec<vtkm::Float64, 6>,
vtkm::Vec<vtkm::Float32, 9>,
vtkm::Vec<vtkm::Float64, 9>>;
VTKM_CONT ComputeMoments::ComputeMoments()
{
@ -53,8 +41,7 @@ VTKM_CONT vtkm::cont::DataSet ComputeMoments::DoExecute(const vtkm::cont::DataSe
auto resolveType = [&](const auto& concrete) {
worklet.Run(input.GetCellSet(), concrete, this->Order, output);
};
field.GetData().CastAndCallForTypesWithFloatFallback<SupportedTypes, VTKM_DEFAULT_STORAGE_LIST>(
resolveType);
this->CastAndCallVariableVecField(field, resolveType);
return output;
}

@ -9,13 +9,17 @@
##============================================================================
set(unit_tests
RenderTestComputeMoments.cxx
UnitTestImageDifferenceFilter.cxx
UnitTestImageMedianFilter.cxx
)
set(libraries
vtkm_filter_image_processing
vtkm_source)
vtkm_source
vtkm_rendering
vtkm_rendering_testing
)
vtkm_unit_tests(
SOURCES ${unit_tests}

@ -0,0 +1,44 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/filter/image_processing/ComputeMoments.h>
#include <vtkm/source/Wavelet.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>
namespace
{
void TestComputeMoments()
{
vtkm::source::Wavelet source;
vtkm::cont::DataSet data = source.Execute();
vtkm::filter::image_processing::ComputeMoments filter;
filter.SetActiveField("RTData");
filter.SetOrder(2);
filter.SetRadius(2);
vtkm::cont::DataSet result = filter.Execute(data);
vtkm::rendering::testing::RenderTestOptions testOptions;
testOptions.AllowedPixelErrorRatio = 0.001f;
testOptions.ColorTable = vtkm::cont::ColorTable("inferno");
testOptions.EnableAnnotations = false;
vtkm::rendering::testing::RenderTest(result, "index", "filter/moments.png", testOptions);
vtkm::rendering::testing::RenderTest(result, "index0", "filter/moments0.png", testOptions);
vtkm::rendering::testing::RenderTest(result, "index12", "filter/moments12.png", testOptions);
}
} // namespace
int RenderTestComputeMoments(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestComputeMoments, argc, argv);
}

@ -9,3 +9,5 @@ PRIVATE_DEPENDS
vtkm_worklet
TEST_DEPENDS
vtkm_source
vtkm_rendering
vtkm_rendering_testing

@ -15,6 +15,9 @@
#include <vtkm/Math.h>
#include <vtkm/worklet/WorkletPointNeighborhood.h>
#include <vtkm/cont/ArrayHandleRecombineVec.h>
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/UncertainArrayHandle.h>
#include <vtkm/cont/UncertainCellSet.h>
@ -54,13 +57,19 @@ public:
using ExecutionSignature = void(_2, Boundary, _3);
template <typename NeighIn, typename T>
template <typename NeighIn, typename TOut>
VTKM_EXEC void operator()(const NeighIn& image,
const vtkm::exec::BoundaryState& boundary,
T& moment) const
TOut& moment) const
{
// TODO: type safety and numerical precision
auto sum = vtkm::TypeTraits<T>::ZeroInitialization();
using ComponentType = typename TOut::ComponentType;
const vtkm::IdComponent numComponents = moment.GetNumberOfComponents();
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] = vtkm::TypeTraits<ComponentType>::ZeroInitialization();
}
// Clamp the radius to the dataset bounds (discard out-of-bounds points).
const auto minRadius = boundary.ClampNeighborIndex(-this->RadiusDiscrete);
@ -85,13 +94,23 @@ public:
if (vtkm::Dot(radius, radius) <= 1)
{
sum +=
static_cast<T>(vtkm::Pow(radius[0], p) * vtkm::Pow(radius[1], q) * image.Get(i, j, 0));
ComponentType multiplier =
static_cast<ComponentType>(vtkm::Pow(radius[0], p) * vtkm::Pow(radius[1], q));
auto inputField = image.Get(i, j, 0);
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] += multiplier * inputField[componentI];
}
}
}
}
moment = T(sum * this->SpacingProduct);
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] *= static_cast<ComponentType>(this->SpacingProduct);
}
}
private:
@ -126,13 +145,19 @@ public:
using ExecutionSignature = void(_2, Boundary, _3);
template <typename NeighIn, typename T>
template <typename NeighIn, typename TOut>
VTKM_EXEC void operator()(const NeighIn& image,
const vtkm::exec::BoundaryState& boundary,
T& moment) const
TOut& moment) const
{
// TODO: type safety and numerical precision
auto sum = vtkm::TypeTraits<T>::ZeroInitialization();
using ComponentType = typename TOut::ComponentType;
const vtkm::IdComponent numComponents = moment.GetNumberOfComponents();
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] = vtkm::TypeTraits<ComponentType>::ZeroInitialization();
}
// Clamp the radius to the dataset bounds (discard out-of-bounds points).
const auto minRadius = boundary.ClampNeighborIndex(-this->RadiusDiscrete);
@ -165,14 +190,24 @@ public:
if (vtkm::Dot(radius, radius) <= 1)
{
sum += static_cast<T>(vtkm::Pow(radius[0], p) * vtkm::Pow(radius[1], q) *
vtkm::Pow(radius[2], r) * image.Get(i, j, k));
ComponentType multiplier = static_cast<ComponentType>(
vtkm::Pow(radius[0], p) * vtkm::Pow(radius[1], q) * vtkm::Pow(radius[2], r));
auto inputField = image.Get(i, j, k);
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] += multiplier * inputField[componentI];
}
}
}
}
}
moment = T(sum * this->SpacingProduct);
// For variable sized Vecs, need to iterate over each component.
for (vtkm::IdComponent componentI = 0; componentI < numComponents; ++componentI)
{
moment[componentI] *= static_cast<ComponentType>(this->SpacingProduct);
}
}
private:
@ -195,9 +230,9 @@ public:
class ResolveUnknownCellSet
{
public:
template <typename T, typename S>
template <typename T>
void operator()(const vtkm::cont::CellSetStructured<2>& input,
const vtkm::cont::ArrayHandle<T, S>& pixels,
const vtkm::cont::ArrayHandleRecombineVec<T>& pixels,
vtkm::Vec3f spacing,
vtkm::Float64 radius,
int maxOrder,
@ -212,7 +247,7 @@ public:
{
const int q = order - p;
vtkm::cont::ArrayHandle<T> moments;
vtkm::cont::ArrayHandleRuntimeVec<T> moments{ pixels.GetNumberOfComponents() };
DispatcherType dispatcher(WorkletType{ spacing, radius, p, q });
dispatcher.Invoke(input, pixels, moments);
@ -226,9 +261,9 @@ public:
}
}
template <typename T, typename S>
template <typename T>
void operator()(const vtkm::cont::CellSetStructured<3>& input,
const vtkm::cont::ArrayHandle<T, S>& pixels,
const vtkm::cont::ArrayHandleRecombineVec<T>& pixels,
vtkm::Vec3f spacing,
vtkm::Float64 radius,
int maxOrder,
@ -246,7 +281,7 @@ public:
{
const int p = order - r - q;
vtkm::cont::ArrayHandle<T> moments;
vtkm::cont::ArrayHandleRuntimeVec<T> moments{ pixels.GetNumberOfComponents() };
DispatcherType dispatcher(WorkletType{ spacing, radius, p, q, r });
dispatcher.Invoke(input, pixels, moments);
@ -263,9 +298,9 @@ public:
}
};
template <typename T, typename S>
template <typename T>
void Run(const vtkm::cont::UnknownCellSet& input,
const vtkm::cont::ArrayHandle<T, S>& pixels,
const vtkm::cont::ArrayHandleRecombineVec<T>& pixels,
int maxOrder,
vtkm::cont::DataSet& output) const
{

@ -26,6 +26,7 @@ set(VTKM_ENABLE_OPENMP ${VTKm_ENABLE_OPENMP})
set(VTKM_ENABLE_TBB ${VTKm_ENABLE_TBB})
set(VTKM_ENABLE_MPI ${VTKm_ENABLE_MPI})
set(VTKM_ENABLE_GPU_MPI ${VTKm_ENABLE_GPU_MPI})
if(VTKM_ENABLE_CUDA)
string(REGEX REPLACE "([0-9]+)\\.([0-9]+).*" "\\1" VTKM_CUDA_VERSION_MAJOR ${CMAKE_CUDA_COMPILER_VERSION})

@ -308,6 +308,9 @@
//Mark if we are building with MPI enabled.
#cmakedefine VTKM_ENABLE_MPI
//Mark if we are building with GPU AWARE MPI enabled.
#cmakedefine VTKM_ENABLE_GPU_MPI
//Mark what version of the CUDA compiler we have. This is needed to correctly
//choose consistent implementation ( so we don't violate ODR ) when we compile
//with CUDA 7.5

@ -607,29 +607,29 @@ struct ConnectivityStructuredIndexHelper<vtkm::TopologyElementTagCell,
}
VTKM_EXEC_CONT
static LogicalIndexType FlatToLogicalFromIndex(const ConnectivityType& connectivity,
vtkm::Id flatFromIndex)
static LogicalIndexType FlatToLogicalIncidentIndex(const ConnectivityType& connectivity,
vtkm::Id flatFromIndex)
{
return connectivity.FlatToLogicalPointIndex(flatFromIndex);
}
VTKM_EXEC_CONT
static vtkm::Id LogicalToFlatFromIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalFromIndex)
static vtkm::Id LogicalToFlatIncidentIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalFromIndex)
{
return connectivity.LogicalToFlatPointIndex(logicalFromIndex);
}
VTKM_EXEC_CONT
static LogicalIndexType FlatToLogicalToIndex(const ConnectivityType& connectivity,
vtkm::Id flatToIndex)
static LogicalIndexType FlatToLogicalVisitIndex(const ConnectivityType& connectivity,
vtkm::Id flatToIndex)
{
return connectivity.FlatToLogicalCellIndex(flatToIndex);
}
VTKM_EXEC_CONT
static vtkm::Id LogicalToFlatToIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalToIndex)
static vtkm::Id LogicalToFlatVisitIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalToIndex)
{
return connectivity.LogicalToFlatCellIndex(logicalToIndex);
}
@ -667,29 +667,29 @@ struct ConnectivityStructuredIndexHelper<vtkm::TopologyElementTagPoint,
}
VTKM_EXEC_CONT
static LogicalIndexType FlatToLogicalFromIndex(const ConnectivityType& connectivity,
vtkm::Id flatFromIndex)
static LogicalIndexType FlatToLogicalIncidentIndex(const ConnectivityType& connectivity,
vtkm::Id flatFromIndex)
{
return connectivity.FlatToLogicalCellIndex(flatFromIndex);
}
VTKM_EXEC_CONT
static vtkm::Id LogicalToFlatFromIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalFromIndex)
static vtkm::Id LogicalToFlatIncidentIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalFromIndex)
{
return connectivity.LogicalToFlatCellIndex(logicalFromIndex);
}
VTKM_EXEC_CONT
static LogicalIndexType FlatToLogicalToIndex(const ConnectivityType& connectivity,
vtkm::Id flatToIndex)
static LogicalIndexType FlatToLogicalVisitIndex(const ConnectivityType& connectivity,
vtkm::Id flatToIndex)
{
return connectivity.FlatToLogicalPointIndex(flatToIndex);
}
VTKM_EXEC_CONT
static vtkm::Id LogicalToFlatToIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalToIndex)
static vtkm::Id LogicalToFlatVisitIndex(const ConnectivityType& connectivity,
const LogicalIndexType& logicalToIndex)
{
return connectivity.LogicalToFlatPointIndex(logicalToIndex);
}

@ -10,10 +10,11 @@
#include <vtkm/rendering/Actor.h>
#include <vtkm/Assert.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/UnknownCellSet.h>
#include <utility>
namespace vtkm
{
namespace rendering
@ -30,25 +31,25 @@ struct Actor::InternalsType
vtkm::Bounds SpatialBounds;
VTKM_CONT
InternalsType(const vtkm::cont::UnknownCellSet& cells,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField,
InternalsType(vtkm::cont::UnknownCellSet cells,
vtkm::cont::CoordinateSystem coordinates,
vtkm::cont::Field scalarField,
const vtkm::rendering::Color& color)
: Cells(cells)
, Coordinates(coordinates)
, ScalarField(scalarField)
: Cells(std::move(cells))
, Coordinates(std::move(coordinates))
, ScalarField(std::move(scalarField))
, ColorTable(vtkm::Range{ 0, 1 }, color.Components, color.Components)
{
}
VTKM_CONT
InternalsType(const vtkm::cont::UnknownCellSet& cells,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField,
InternalsType(vtkm::cont::UnknownCellSet cells,
vtkm::cont::CoordinateSystem coordinates,
vtkm::cont::Field scalarField,
const vtkm::cont::ColorTable& colorTable = vtkm::cont::ColorTable::Preset::Default)
: Cells(cells)
, Coordinates(coordinates)
, ScalarField(scalarField)
: Cells(std::move(cells))
, Coordinates(std::move(coordinates))
, ScalarField(std::move(scalarField))
, ColorTable(colorTable)
{
}
@ -57,7 +58,7 @@ struct Actor::InternalsType
Actor::Actor(const vtkm::cont::UnknownCellSet& cells,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField)
: Internals(new InternalsType(cells, coordinates, scalarField))
: Internals(std::make_unique<InternalsType>(cells, coordinates, scalarField))
{
this->Init(coordinates, scalarField);
}
@ -66,7 +67,7 @@ Actor::Actor(const vtkm::cont::UnknownCellSet& cells,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField,
const vtkm::rendering::Color& color)
: Internals(new InternalsType(cells, coordinates, scalarField, color))
: Internals(std::make_unique<InternalsType>(cells, coordinates, scalarField, color))
{
this->Init(coordinates, scalarField);
}
@ -75,11 +76,42 @@ Actor::Actor(const vtkm::cont::UnknownCellSet& cells,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField,
const vtkm::cont::ColorTable& colorTable)
: Internals(new InternalsType(cells, coordinates, scalarField, colorTable))
: Internals(std::make_unique<InternalsType>(cells, coordinates, scalarField, colorTable))
{
this->Init(coordinates, scalarField);
}
Actor::Actor(const Actor& rhs)
: Internals(nullptr)
{
// rhs might have been moved, its Internal would be nullptr
if (rhs.Internals)
Internals = std::make_unique<InternalsType>(*rhs.Internals);
}
Actor& Actor::operator=(const Actor& rhs)
{
// both *this and rhs might have been moved.
if (!rhs.Internals)
{
Internals.reset();
}
else if (!Internals)
{
Internals = std::make_unique<InternalsType>(*rhs.Internals);
}
else
{
*Internals = *rhs.Internals;
}
return *this;
}
Actor::Actor(vtkm::rendering::Actor&&) noexcept = default;
Actor& Actor::operator=(Actor&&) noexcept = default;
Actor::~Actor() = default;
void Actor::Init(const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::cont::Field& scalarField)
{

@ -40,6 +40,13 @@ public:
const vtkm::cont::Field& scalarField,
const vtkm::rendering::Color& color);
Actor(const Actor&);
Actor& operator=(const Actor&);
Actor(Actor&&) noexcept;
Actor& operator=(Actor&&) noexcept;
~Actor();
void Render(vtkm::rendering::Mapper& mapper,
vtkm::rendering::Canvas& canvas,
const vtkm::rendering::Camera& camera) const;
@ -60,9 +67,7 @@ public:
private:
struct InternalsType;
std::shared_ptr<InternalsType> Internals;
struct RangeFunctor;
std::unique_ptr<InternalsType> Internals;
void Init(const vtkm::cont::CoordinateSystem& coordinates, const vtkm::cont::Field& scalarField);
};

@ -10,8 +10,6 @@
#include <vtkm/rendering/AxisAnnotation.h>
#include <vtkm/cont/ErrorBadType.h>
namespace vtkm
{
namespace rendering
@ -37,7 +35,7 @@ void AxisAnnotation::CalculateTicks(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions,
int modifyTickQuantity) const
int modifyTickQuantity)
{
positions.clear();
proportions.clear();
@ -144,7 +142,7 @@ void AxisAnnotation::CalculateTicks(const vtkm::Range& range,
void AxisAnnotation::CalculateTicksLogarithmic(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions) const
std::vector<vtkm::Float64>& proportions)
{
positions.clear();
proportions.clear();
@ -167,7 +165,7 @@ void AxisAnnotation::CalculateTicksLogarithmic(const vtkm::Range& range,
last_log = first_log + 1;
}
vtkm::Float64 diff_log = last_log - first_log;
vtkm::Int32 step = vtkm::Int32((diff_log + 9) / 10);
auto step = vtkm::Int32((diff_log + 9) / 10);
if (minor)
{
@ -175,7 +173,7 @@ void AxisAnnotation::CalculateTicksLogarithmic(const vtkm::Range& range,
last_log += step;
}
for (vtkm::Int32 i = vtkm::Int32(first_log); i <= last_log; i += step)
for (auto i = vtkm::Int32(first_log); i <= last_log; i += step)
{
vtkm::Float64 logpos = i;
vtkm::Float64 pos = vtkm::Pow(10, logpos);
@ -229,9 +227,5 @@ void AxisAnnotation::CalculateTicksLogarithmic(const vtkm::Range& range,
}
}
}
AxisAnnotation::AxisAnnotation() {}
AxisAnnotation::~AxisAnnotation() {}
}
} // namespace vtkm::rendering

@ -24,20 +24,20 @@ namespace rendering
class VTKM_RENDERING_EXPORT AxisAnnotation
{
protected:
void CalculateTicks(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions,
int modifyTickQuantity) const;
void CalculateTicksLogarithmic(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions) const;
static void CalculateTicks(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions,
int modifyTickQuantity);
static void CalculateTicksLogarithmic(const vtkm::Range& range,
bool minor,
std::vector<vtkm::Float64>& positions,
std::vector<vtkm::Float64>& proportions);
public:
AxisAnnotation();
AxisAnnotation() = default;
virtual ~AxisAnnotation();
virtual ~AxisAnnotation() = default;
virtual void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,

@ -20,7 +20,6 @@ namespace rendering
{
AxisAnnotation2D::AxisAnnotation2D()
: AxisAnnotation()
{
this->AlignH = TextAnnotation::HCenter;
this->AlignV = TextAnnotation::VCenter;
@ -31,8 +30,6 @@ AxisAnnotation2D::AxisAnnotation2D()
this->MoreOrLessTickAdjustment = 0;
}
AxisAnnotation2D::~AxisAnnotation2D() {}
void AxisAnnotation2D::SetRangeForAutoTicks(const Range& range)
{
this->TickRange = range;
@ -84,12 +81,11 @@ void AxisAnnotation2D::Render(const vtkm::rendering::Camera& camera,
canvas.AddLine(this->PosX0, this->PosY0, this->PosX1, this->PosY1, this->LineWidth, this->Color);
// major ticks
unsigned int nmajor = (unsigned int)this->ProportionsMajor.size();
auto nmajor = (unsigned int)this->ProportionsMajor.size();
while (this->Labels.size() < nmajor)
{
this->Labels.push_back(
std::unique_ptr<TextAnnotation>(new vtkm::rendering::TextAnnotationScreen(
"test", this->Color, this->FontScale, vtkm::Vec2f_32(0, 0), 0)));
this->Labels.push_back(std::make_unique<TextAnnotationScreen>(
"test", this->Color, this->FontScale, vtkm::Vec2f_32(0, 0)));
}
std::stringstream numberToString;
@ -116,8 +112,7 @@ void AxisAnnotation2D::Render(const vtkm::rendering::Camera& camera,
this->Labels[i]->SetText(numberToString.str());
//if (fabs(this->PositionsMajor[i]) < 1e-10)
// this->Labels[i]->SetText("0");
TextAnnotation* tempBase = this->Labels[i].get();
TextAnnotationScreen* tempDerived = static_cast<TextAnnotationScreen*>(tempBase);
auto* tempDerived = dynamic_cast<TextAnnotationScreen*>(this->Labels[i].get());
tempDerived->SetPosition(vtkm::Float32(xs), vtkm::Float32(ys));
this->Labels[i]->SetAlignment(this->AlignH, this->AlignV);
@ -126,7 +121,7 @@ void AxisAnnotation2D::Render(const vtkm::rendering::Camera& camera,
// minor ticks
if (this->MinorTickSizeX != 0 || this->MinorTickSizeY != 0)
{
unsigned int nminor = (unsigned int)this->ProportionsMinor.size();
auto nminor = (unsigned int)this->ProportionsMinor.size();
for (unsigned int i = 0; i < nminor; ++i)
{
vtkm::Float64 xc = this->PosX0 + (this->PosX1 - this->PosX0) * this->ProportionsMinor[i];
@ -140,9 +135,9 @@ void AxisAnnotation2D::Render(const vtkm::rendering::Camera& camera,
}
}
for (unsigned int i = 0; i < nmajor; ++i)
for (auto& label : this->Labels)
{
this->Labels[i]->Render(camera, worldAnnotator, canvas);
label->Render(camera, worldAnnotator, canvas);
}
}
}

@ -41,7 +41,6 @@ protected:
TextAnnotation::HorizontalAlignment AlignH;
TextAnnotation::VerticalAlignment AlignV;
std::vector<std::unique_ptr<TextAnnotation>> Labels;
// std::vector<TextAnnotation*> Labels;
std::vector<vtkm::Float64> PositionsMajor;
std::vector<vtkm::Float64> ProportionsMajor;
@ -54,8 +53,6 @@ protected:
public:
AxisAnnotation2D();
~AxisAnnotation2D();
AxisAnnotation2D(const AxisAnnotation2D&) = delete;
AxisAnnotation2D& operator=(const AxisAnnotation2D&) = delete;
@ -104,8 +101,8 @@ public:
void SetLabelFontScale(vtkm::Float32 s)
{
this->FontScale = s;
for (unsigned int i = 0; i < this->Labels.size(); i++)
this->Labels[i]->SetScale(s);
for (auto& label : this->Labels)
label->SetScale(s);
}
void SetRangeForAutoTicks(const vtkm::Range& range);

@ -10,6 +10,8 @@
#include <vtkm/rendering/AxisAnnotation3D.h>
#include <sstream>
namespace vtkm
{
namespace rendering
@ -36,8 +38,6 @@ AxisAnnotation3D::AxisAnnotation3D()
{
}
AxisAnnotation3D::~AxisAnnotation3D() {}
void AxisAnnotation3D::SetTickInvert(bool x, bool y, bool z)
{
this->Invert[0] = x ? +1.0f : -1.0f;
@ -48,9 +48,9 @@ void AxisAnnotation3D::SetTickInvert(bool x, bool y, bool z)
void AxisAnnotation3D::SetLabelFontScale(Float64 s)
{
this->FontScale = s;
for (unsigned int i = 0; i < this->Labels.size(); i++)
for (auto& label : this->Labels)
{
this->Labels[i]->SetScale(vtkm::Float32(s));
label->SetScale(vtkm::Float32(s));
}
}
@ -65,12 +65,11 @@ void AxisAnnotation3D::Render(const Camera& camera,
std::vector<vtkm::Float64> proportions;
// major ticks
CalculateTicks(this->Range, false, positions, proportions, this->MoreOrLessTickAdjustment);
unsigned int nmajor = (unsigned int)proportions.size();
auto nmajor = (unsigned int)proportions.size();
while (this->Labels.size() < nmajor)
{
this->Labels.push_back(
std::unique_ptr<TextAnnotationBillboard>(new vtkm::rendering::TextAnnotationBillboard(
"test", this->Color, vtkm::Float32(this->FontScale), vtkm::Vec3f_32(0, 0, 0), 0)));
this->Labels.push_back(std::make_unique<TextAnnotationBillboard>(
"test", this->Color, vtkm::Float32(this->FontScale), vtkm::Vec3f_32(0, 0, 0)));
}
std::stringstream numberToString;
@ -144,15 +143,12 @@ void AxisAnnotation3D::Render(const Camera& camera,
this->Labels[i]->SetPosition(vtkm::Float32(tickPos[0] - tickSize[0]),
vtkm::Float32(tickPos[1] - tickSize[1]),
vtkm::Float32(tickPos[2] - tickSize[2]));
vtkm::Vec3f_32 pp(vtkm::Float32(tickPos[0] - tickSize[0]),
vtkm::Float32(tickPos[1] - tickSize[1]),
vtkm::Float32(tickPos[2] - tickSize[2]));
this->Labels[i]->SetAlignment(TextAnnotation::HCenter, TextAnnotation::VCenter);
}
// minor ticks
CalculateTicks(this->Range, true, positions, proportions, this->MoreOrLessTickAdjustment);
unsigned int nminor = (unsigned int)proportions.size();
auto nminor = (unsigned int)proportions.size();
for (unsigned int i = 0; i < nminor; ++i)
{
vtkm::Vec3f_64 tickPos = proportions[i] * (this->Point1 - this->Point0) + this->Point0;
@ -197,9 +193,9 @@ void AxisAnnotation3D::Render(const Camera& camera,
}
}
for (unsigned int i = 0; i < nmajor; ++i)
for (auto& label : this->Labels)
{
this->Labels[i]->Render(camera, worldAnnotator, canvas);
label->Render(camera, worldAnnotator, canvas);
}
}
}

@ -22,7 +22,7 @@
#include <vtkm/rendering/TextAnnotationBillboard.h>
#include <vtkm/rendering/WorldAnnotator.h>
#include <sstream>
#include <memory>
namespace vtkm
{
@ -49,8 +49,6 @@ protected:
public:
AxisAnnotation3D();
~AxisAnnotation3D();
AxisAnnotation3D(const AxisAnnotation3D&) = delete;
AxisAnnotation3D& operator=(const AxisAnnotation3D&) = delete;
@ -111,9 +109,9 @@ public:
this->SetRange(vtkm::Range(lower, upper));
}
virtual void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas) override;
void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas) override;
};
}
} //namespace vtkm::rendering

@ -153,7 +153,6 @@ void Camera::GetRealViewport(vtkm::Id screenWidth,
vtkm::Float32 daspect =
(this->Camera2D.Right - this->Camera2D.Left) / (this->Camera2D.Top - this->Camera2D.Bottom);
daspect *= this->Camera2D.XScale;
//cerr << "waspect="<<waspect << " \tdaspect="<<daspect<<endl;
//needed as center is a constant value
#if defined(VTKM_MSVC)

@ -20,12 +20,9 @@ ColorBarAnnotation::ColorBarAnnotation()
: ColorTable(vtkm::ColorSpace::Lab)
, Position(vtkm::Range(-0.88, +0.88), vtkm::Range(+0.87, +0.92), vtkm::Range(0, 0))
, Horizontal(true)
, FieldName("")
{
}
ColorBarAnnotation::~ColorBarAnnotation() {}
void ColorBarAnnotation::SetFieldName(const std::string& fieldName)
{
FieldName = fieldName;
@ -83,7 +80,7 @@ void ColorBarAnnotation::Render(const vtkm::rendering::Camera& camera,
this->Axis.SetMinorTickSize(0, 0, 0); // no minor ticks
this->Axis.Render(camera, worldAnnotator, canvas);
if (FieldName != "")
if (!FieldName.empty())
{
vtkm::Vec2f_32 labelPos;
if (Horizontal)

@ -35,8 +35,6 @@ protected:
public:
ColorBarAnnotation();
virtual ~ColorBarAnnotation();
VTKM_CONT
void SetColorTable(const vtkm::cont::ColorTable& colorTable) { this->ColorTable = colorTable; }
@ -56,9 +54,9 @@ public:
VTKM_CONT
void SetPosition(const vtkm::Bounds& position);
virtual void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas);
void Render(const vtkm::rendering::Camera& camera,
const vtkm::rendering::WorldAnnotator& worldAnnotator,
vtkm::rendering::Canvas& canvas);
};
}
} //namespace vtkm::rendering

@ -21,8 +21,6 @@ ColorLegendAnnotation::ColorLegendAnnotation()
this->LabelColor = vtkm::rendering::Color::white;
}
ColorLegendAnnotation::~ColorLegendAnnotation() {}
void ColorLegendAnnotation::Clear()
{
this->Labels.clear();
@ -42,9 +40,9 @@ void ColorLegendAnnotation::Render(const vtkm::rendering::Camera& camera,
vtkm::Float32 l = -0.95f, r = -0.90f;
vtkm::Float32 b = +0.90f, t = +0.95f;
for (unsigned int i = 0; i < this->ColorSwatchList.size(); ++i)
for (auto& color : this->ColorSwatchList)
{
canvas.AddColorSwatch(l, b, l, t, r, t, r, b, this->ColorSwatchList[i]);
canvas.AddColorSwatch(l, b, l, t, r, t, r, b, color);
b -= 0.07f;
t -= 0.07f;
}
@ -57,9 +55,8 @@ void ColorLegendAnnotation::Render(const vtkm::rendering::Camera& camera,
while (this->Annot.size() < this->Labels.size())
{
this->Annot.push_back(
std::unique_ptr<TextAnnotationScreen>(new vtkm::rendering::TextAnnotationScreen(
"test", this->LabelColor, this->FontScale, vtkm::Vec2f_32(0, 0), 0)));
this->Annot.push_back(std::make_unique<TextAnnotationScreen>(
"test", this->LabelColor, this->FontScale, vtkm::Vec2f_32(0, 0)));
}
for (unsigned int i = 0; i < this->Annot.size(); ++i)

@ -34,7 +34,6 @@ private:
public:
ColorLegendAnnotation();
~ColorLegendAnnotation();
ColorLegendAnnotation(const ColorLegendAnnotation&) = delete;
ColorLegendAnnotation& operator=(const ColorLegendAnnotation&) = delete;
@ -46,13 +45,13 @@ public:
void SetLabelFontScale(vtkm::Float32 s)
{
this->FontScale = s;
for (unsigned int i = 0; i < this->Annot.size(); i++)
this->Annot[i]->SetScale(s);
for (auto& annot : this->Annot)
annot->SetScale(s);
}
virtual void Render(const vtkm::rendering::Camera&,
const vtkm::rendering::WorldAnnotator& annotator,
vtkm::rendering::Canvas& canvas);
void Render(const vtkm::rendering::Camera&,
const vtkm::rendering::WorldAnnotator& annotator,
vtkm::rendering::Canvas& canvas);
};
}
} //namespace vtkm::rendering

@ -15,6 +15,8 @@
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <memory>
namespace vtkm
{
@ -52,8 +54,6 @@ public:
}
}
~InternalsType() {}
VTKM_CONT
void SetUnitScalar(vtkm::Float32 unitScalar) { Tracer.SetUnitScalar(unitScalar); }
@ -241,7 +241,7 @@ public:
VTKM_CONT
ConnectivityProxy::ConnectivityProxy(const vtkm::cont::DataSet& dataSet,
const std::string& fieldName)
: Internals(new InternalsType(dataSet, fieldName))
: Internals(std::make_unique<InternalsType>(dataSet, fieldName))
{
}
@ -256,11 +256,45 @@ ConnectivityProxy::ConnectivityProxy(const vtkm::cont::UnknownCellSet& cellset,
dataset.AddCoordinateSystem(coords);
dataset.AddField(scalarField);
Internals = std::shared_ptr<InternalsType>(new InternalsType(dataset, scalarField.GetName()));
Internals = std::make_unique<InternalsType>(dataset, scalarField.GetName());
}
ConnectivityProxy::ConnectivityProxy(const ConnectivityProxy& rhs)
: Internals(nullptr)
{
// rhs might have been moved, its Internal would be nullptr
if (rhs.Internals)
{
Internals = std::make_unique<InternalsType>(*rhs.Internals);
}
}
ConnectivityProxy& ConnectivityProxy::operator=(const ConnectivityProxy& rhs)
{
// both *this and rhs might have been moved.
if (!rhs.Internals)
{
Internals.reset();
}
else if (!Internals)
{
Internals = std::make_unique<InternalsType>(*rhs.Internals);
}
else
{
*Internals = *rhs.Internals;
}
return *this;
}
VTKM_CONT
ConnectivityProxy::~ConnectivityProxy() {}
ConnectivityProxy::ConnectivityProxy(ConnectivityProxy&&) noexcept = default;
VTKM_CONT
ConnectivityProxy& ConnectivityProxy::operator=(vtkm::rendering::ConnectivityProxy&&) noexcept =
default;
VTKM_CONT
ConnectivityProxy::~ConnectivityProxy() = default;
VTKM_CONT
void ConnectivityProxy::SetSampleDistance(const vtkm::Float32& distance)

@ -34,9 +34,15 @@ public:
ConnectivityProxy(const vtkm::cont::UnknownCellSet& cellset,
const vtkm::cont::CoordinateSystem& coords,
const vtkm::cont::Field& scalarField);
// Do not allow the default constructor
ConnectivityProxy() = delete;
ConnectivityProxy(const ConnectivityProxy&);
ConnectivityProxy& operator=(const ConnectivityProxy&);
ConnectivityProxy(ConnectivityProxy&&) noexcept;
ConnectivityProxy& operator=(ConnectivityProxy&&) noexcept;
~ConnectivityProxy();
enum struct RenderMode
{
Volume,
@ -45,10 +51,8 @@ public:
void SetRenderMode(RenderMode mode);
void SetSampleDistance(const vtkm::Float32&);
void SetCanvas(vtkm::rendering::Canvas* canvas);
void SetScalarField(const std::string& fieldName);
void SetEmissionField(const std::string& fieldName);
void SetCamera(const vtkm::rendering::Camera& camera);
void SetScalarRange(const vtkm::Range& range);
void SetColorMap(vtkm::cont::ArrayHandle<vtkm::Vec4f_32>& colormap);
void SetCompositeBackground(bool on);
@ -69,9 +73,8 @@ public:
protected:
struct InternalsType;
struct BoundsFunctor;
std::shared_ptr<InternalsType> Internals;
std::unique_ptr<InternalsType> Internals;
};
}
} //namespace vtkm::rendering
#endif //vtk_m_rendering_SceneRendererVolume_h
#endif //vtk_m_rendering_ConnectivityProxy_h

@ -98,13 +98,11 @@ void MapperVolume::RenderCells(const vtkm::cont::UnknownCellSet& cellset,
vtkm::rendering::raytracing::VolumeRendererStructured tracer;
vtkm::rendering::raytracing::Camera rayCamera;
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
vtkm::Int32 width = (vtkm::Int32)this->Internals->Canvas->GetWidth();
vtkm::Int32 height = (vtkm::Int32)this->Internals->Canvas->GetHeight();
rayCamera.SetParameters(camera, width, height);
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
rayCamera.CreateRays(rays, coords.GetBounds());
rays.Buffers.at(0).InitConst(0.f);
raytracing::RayOperations::MapCanvasToRays(rays, camera, *this->Internals->Canvas);

@ -102,12 +102,12 @@ ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& cam
vtkm::cont::Timer timer;
timer.Start();
//
// Create rays
//
vtkm::rendering::raytracing::Camera cam;
cam.SetParameters(camera, this->Internals->Width, this->Internals->Height);
// FIXME: rays are created with an unused Buffers.at(0), that ChannelBuffer
// also has wrong number of channels, thus allocates memory that is wasted.
vtkm::rendering::raytracing::Ray<vtkm::Float32> rays;
cam.CreateRays(rays, this->Internals->ShapeBounds);
rays.Buffers.at(0).InitConst(0.f);
@ -117,12 +117,10 @@ ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& cam
std::map<std::string, vtkm::Range> rangeMap;
for (vtkm::Id i = 0; i < numFields; ++i)
{
vtkm::cont::Field field = this->Internals->DataSet.GetField(i);
vtkm::cont::ArrayHandle<vtkm::Range> ranges;
ranges = field.GetRange();
vtkm::Id comps = ranges.GetNumberOfValues();
if (comps == 1)
const auto& field = this->Internals->DataSet.GetField(i);
if (field.GetData().GetNumberOfComponents() == 1)
{
auto ranges = field.GetRange();
rangeMap[field.GetName()] = ranges.ReadPortal().Get(0);
this->Internals->Tracer.AddField(field);
}
@ -153,7 +151,6 @@ ScalarRenderer::Result ScalarRenderer::Render(const vtkm::rendering::Camera& cam
raytracing::ChannelBuffer<vtkm::Float32> depthExpanded =
depthChannel.ExpandBuffer(rays.PixelIdx, expandSize, Internals->DefaultValue);
Result result;
result.Width = Internals->Width;
result.Height = Internals->Height;

@ -27,9 +27,9 @@ Scene::Scene()
{
}
void Scene::AddActor(const vtkm::rendering::Actor& actor)
void Scene::AddActor(vtkm::rendering::Actor actor)
{
this->Internals->Actors.push_back(actor);
this->Internals->Actors.push_back(std::move(actor));
}
const vtkm::rendering::Actor& Scene::GetActor(vtkm::IdComponent index) const
@ -46,9 +46,8 @@ void Scene::Render(vtkm::rendering::Mapper& mapper,
vtkm::rendering::Canvas& canvas,
const vtkm::rendering::Camera& camera) const
{
for (vtkm::IdComponent actorIndex = 0; actorIndex < this->GetNumberOfActors(); actorIndex++)
for (const auto& actor : this->Internals->Actors)
{
const vtkm::rendering::Actor& actor = this->GetActor(actorIndex);
actor.Render(mapper, canvas, camera);
}
}
@ -56,10 +55,9 @@ void Scene::Render(vtkm::rendering::Mapper& mapper,
vtkm::Bounds Scene::GetSpatialBounds() const
{
vtkm::Bounds bounds;
for (vtkm::IdComponent actorIndex = 0; actorIndex < this->GetNumberOfActors(); actorIndex++)
for (const auto& actor : this->Internals->Actors)
{
// accumulate all Actors' spatial bounds into the scene spatial bounds
bounds.Include(this->GetActor(actorIndex).GetSpatialBounds());
bounds.Include(actor.GetSpatialBounds());
}
return bounds;

@ -29,7 +29,7 @@ class VTKM_RENDERING_EXPORT Scene
public:
Scene();
void AddActor(const vtkm::rendering::Actor& actor);
void AddActor(vtkm::rendering::Actor actor);
const vtkm::rendering::Actor& GetActor(vtkm::IdComponent index) const;

@ -25,7 +25,7 @@ TextAnnotation::TextAnnotation(const std::string& text,
{
}
TextAnnotation::~TextAnnotation() {}
TextAnnotation::~TextAnnotation() = default;
void TextAnnotation::SetText(const std::string& text)
{

@ -28,8 +28,6 @@ TextAnnotationBillboard::TextAnnotationBillboard(const std::string& text,
{
}
TextAnnotationBillboard::~TextAnnotationBillboard() {}
void TextAnnotationBillboard::SetPosition(const vtkm::Vec3f_32& position)
{
this->Position = position;

@ -30,8 +30,6 @@ public:
const vtkm::Vec3f_32& position,
vtkm::Float32 angleDegrees = 0);
~TextAnnotationBillboard();
void SetPosition(const vtkm::Vec3f_32& position);
void SetPosition(vtkm::Float32 posx, vtkm::Float32 posy, vtkm::Float32 posz);

@ -26,8 +26,6 @@ TextAnnotationScreen::TextAnnotationScreen(const std::string& text,
{
}
TextAnnotationScreen::~TextAnnotationScreen() {}
void TextAnnotationScreen::SetPosition(const vtkm::Vec2f_32& position)
{
this->Position = position;

@ -30,8 +30,6 @@ public:
const vtkm::Vec2f_32& position,
vtkm::Float32 angleDegrees = 0);
~TextAnnotationScreen();
void SetPosition(const vtkm::Vec2f_32& position);
void SetPosition(vtkm::Float32 posx, vtkm::Float32 posy);

@ -37,7 +37,7 @@ View::View(const vtkm::rendering::Scene& scene,
const vtkm::rendering::Canvas& canvas,
const vtkm::rendering::Color& backgroundColor,
const vtkm::rendering::Color& foregroundColor)
: Internal(std::make_shared<InternalData>())
: Internal(std::make_unique<InternalData>())
{
this->Internal->Scene = scene;
this->Internal->MapperPointer = mapper.NewCopy();
@ -65,7 +65,7 @@ View::View(const vtkm::rendering::Scene& scene,
const vtkm::rendering::Camera& camera,
const vtkm::rendering::Color& backgroundColor,
const vtkm::rendering::Color& foregroundColor)
: Internal(std::make_shared<InternalData>())
: Internal(std::make_unique<InternalData>())
{
this->Internal->Scene = scene;
this->Internal->MapperPointer = mapper.NewCopy();
@ -77,7 +77,7 @@ View::View(const vtkm::rendering::Scene& scene,
this->AxisColor = foregroundColor;
}
View::~View() {}
View::~View() = default;
const vtkm::rendering::Scene& View::GetScene() const
{

@ -90,7 +90,7 @@ public:
void SetWorldAnnotationsEnabled(bool val) { this->WorldAnnotationsEnabled = val; }
VTKM_CONT void SetRenderAnnotationsEnabled(bool val) { this->RenderAnnotationsEnabled = val; }
VTKM_CONT bool GetRenderAnnotationsEnabled() { return this->RenderAnnotationsEnabled; }
VTKM_CONT bool GetRenderAnnotationsEnabled() const { return this->RenderAnnotationsEnabled; }
virtual void Paint() = 0;
virtual void RenderScreenAnnotations() = 0;
@ -126,7 +126,7 @@ protected:
bool RenderAnnotationsEnabled = true;
private:
std::shared_ptr<InternalData> Internal;
std::unique_ptr<InternalData> Internal;
};
} // namespace vtkm::rendering

@ -36,8 +36,6 @@ View1D::View1D(const vtkm::rendering::Scene& scene,
{
}
View1D::~View1D() {}
void View1D::Paint()
{
this->GetCanvas().Clear();
@ -104,7 +102,7 @@ void View1D::RenderColorLegendAnnotations()
this->GetCanvas().BeginTextRenderingBatch();
for (int i = 0; i < this->GetScene().GetNumberOfActors(); ++i)
{
vtkm::rendering::Actor act = this->GetScene().GetActor(i);
const auto& act = this->GetScene().GetActor(i);
vtkm::Vec<double, 4> colorData;
act.GetColorTable().GetPoint(0, colorData);

@ -35,8 +35,6 @@ public:
const vtkm::rendering::Color& backgroundColor = vtkm::rendering::Color(0, 0, 0, 1),
const vtkm::rendering::Color& foregroundColor = vtkm::rendering::Color(1, 1, 1, 1));
~View1D();
void Paint() override;
void RenderScreenAnnotations() override;
void RenderWorldAnnotations() override;

@ -34,8 +34,6 @@ View2D::View2D(const vtkm::rendering::Scene& scene,
{
}
View2D::~View2D() {}
void View2D::Paint()
{
this->GetCanvas().Clear();

@ -36,8 +36,6 @@ public:
const vtkm::rendering::Color& backgroundColor = vtkm::rendering::Color(0, 0, 0, 1),
const vtkm::rendering::Color& foregroundColor = vtkm::rendering::Color(1, 1, 1, 1));
~View2D();
void Paint() override;
void RenderScreenAnnotations() override;

@ -34,8 +34,6 @@ View3D::View3D(const vtkm::rendering::Scene& scene,
{
}
View3D::~View3D() {}
void View3D::Paint()
{
this->GetCanvas().Clear();

@ -37,8 +37,6 @@ public:
const vtkm::rendering::Color& backgroundColor = vtkm::rendering::Color(0, 0, 0, 1),
const vtkm::rendering::Color& foregroundColor = vtkm::rendering::Color(1, 1, 1, 1));
~View3D();
void Paint() override;
void RenderScreenAnnotations() override;

@ -51,7 +51,7 @@ void WorldAnnotator::AddText(const vtkm::Vec3f_32& origin,
const vtkm::Vec2f_32& anchor,
const vtkm::rendering::Color& color,
const std::string& text,
const vtkm::Float32 depth) const
vtkm::Float32 depth) const
{
vtkm::Vec3f_32 n = vtkm::Cross(right, up);
vtkm::Normalize(n);

@ -27,7 +27,7 @@ class Canvas;
class VTKM_RENDERING_EXPORT WorldAnnotator
{
public:
WorldAnnotator(const vtkm::rendering::Canvas* canvas);
explicit WorldAnnotator(const vtkm::rendering::Canvas* canvas);
void AddLine(const vtkm::Vec3f_64& point0,
const vtkm::Vec3f_64& point1,
@ -63,7 +63,7 @@ public:
const vtkm::Vec2f_32& anchor,
const vtkm::rendering::Color& color,
const std::string& text,
const vtkm::Float32 depth = 0.f) const;
vtkm::Float32 depth = 0.f) const;
VTKM_CONT
void AddText(vtkm::Float32 originX,

@ -13,20 +13,16 @@
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/rendering/raytracing/Camera.h>
#include <vtkm/rendering/raytracing/Logger.h>
#include <vtkm/rendering/raytracing/RayOperations.h>
#include <vtkm/rendering/raytracing/RayTracingTypeDefs.h>
#include <vtkm/rendering/raytracing/Sampler.h>
#include <vtkm/rendering/raytracing/Worklets.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <limits>
namespace vtkm
{
namespace rendering
@ -91,9 +87,9 @@ public:
vtkm::Normalize(nlook);
}
VTKM_EXEC inline vtkm::Float32 rcp(vtkm::Float32 f) const { return 1.0f / f; }
VTKM_EXEC static inline vtkm::Float32 rcp(vtkm::Float32 f) { return 1.0f / f; }
VTKM_EXEC inline vtkm::Float32 rcp_safe(vtkm::Float32 f) const
VTKM_EXEC static inline vtkm::Float32 rcp_safe(vtkm::Float32 f)
{
return rcp((fabs(f) < 1e-8f) ? 1e-8f : f);
}
@ -229,7 +225,7 @@ public:
}; // class perspective ray gen jitter
class Camera::Ortho2DRayGen : public vtkm::worklet::WorkletMapField
class Ortho2DRayGen : public vtkm::worklet::WorkletMapField
{
public:
vtkm::Int32 w;
@ -263,15 +259,18 @@ public:
vtkm::Float32 _h = static_cast<vtkm::Float32>(height) * (vt - vb) / 2.f;
vtkm::Vec2f_32 minPoint(left, bottom);
vtkm::Vec2f_32 maxPoint(right, top);
// pixel size in world coordinate
vtkm::Vec2f_32 delta = maxPoint - minPoint;
//delta[0] /= vtkm::Float32(width);
//delta[1] /= vtkm::Float32(height);
delta[0] /= vtkm::Float32(_w);
delta[1] /= vtkm::Float32(_h);
PixelDelta[0] = delta[0];
PixelDelta[1] = delta[1];
PixelDelta[2] = 0.f;
// "first" ray starts at the bottom-lower corner, with half pixel offset. All other
// pixels will be one pixel size (i.e. PixelData) apart.
vtkm::Vec2f_32 startOffset = minPoint + delta / 2.f;
StartOffset[0] = startOffset[0];
StartOffset[1] = startOffset[1];
@ -297,6 +296,7 @@ public:
rayDirX = 0.f;
rayDirY = 0.f;
rayDirZ = 1.f;
//
// Pixel subset is the pixels in the 2d viewport
// not where the rays might intersect data like
@ -305,14 +305,13 @@ public:
int i = vtkm::Int32(idx) % SubsetWidth;
int j = vtkm::Int32(idx) / SubsetWidth;
vtkm::Vec3f_32 pos;
pos[0] = vtkm::Float32(i);
pos[1] = vtkm::Float32(j);
pos[2] = 0.f;
vtkm::Vec3f_32 pos{ vtkm::Float32(i), vtkm::Float32(j), 0.f };
vtkm::Vec3f_32 origin = StartOffset + pos * PixelDelta;
rayOriginX = origin[0];
rayOriginY = origin[1];
rayOriginZ = origin[2];
i += Minx;
j += Miny;
pixelIndex = static_cast<vtkm::Id>(j * w + i);
@ -320,7 +319,7 @@ public:
}; // class perspective ray gen
class Camera::PerspectiveRayGen : public vtkm::worklet::WorkletMapField
class PerspectiveRayGen : public vtkm::worklet::WorkletMapField
{
public:
vtkm::Int32 w;
@ -350,11 +349,13 @@ public:
{
vtkm::Float32 thx = tanf((fovX * vtkm::Pi_180f()) * .5f);
vtkm::Float32 thy = tanf((fovY * vtkm::Pi_180f()) * .5f);
vtkm::Vec3f_32 ru = vtkm::Cross(look, up);
vtkm::Normalize(ru);
vtkm::Vec3f_32 rv = vtkm::Cross(ru, look);
vtkm::Normalize(rv);
delta_x = ru * (2 * thx / (float)w);
delta_y = rv * (2 * thy / (float)h);
@ -367,6 +368,7 @@ public:
delta_y[1] = delta_y[1] / _zoom;
delta_y[2] = delta_y[2] / _zoom;
}
nlook = look;
vtkm::Normalize(nlook);
}
@ -381,14 +383,15 @@ public:
Precision& rayDirZ,
vtkm::Id& pixelIndex) const
{
vtkm::Vec<Precision, 3> ray_dir(rayDirX, rayDirY, rayDirZ);
int i = vtkm::Int32(idx) % SubsetWidth;
int j = vtkm::Int32(idx) / SubsetWidth;
auto i = vtkm::Int32(idx) % SubsetWidth;
auto j = vtkm::Int32(idx) / SubsetWidth;
i += Minx;
j += Miny;
// Write out the global pixelId
pixelIndex = static_cast<vtkm::Id>(j * w + i);
ray_dir = nlook + delta_x * ((2.f * Precision(i) - Precision(w)) / 2.0f) +
vtkm::Vec<Precision, 3> ray_dir = nlook +
delta_x * ((2.f * Precision(i) - Precision(w)) / 2.0f) +
delta_y * ((2.f * Precision(j) - Precision(h)) / 2.0f);
// avoid some numerical issues
for (vtkm::Int32 d = 0; d < 3; ++d)
@ -396,19 +399,16 @@ public:
if (ray_dir[d] == 0.f)
ray_dir[d] += 0.0000001f;
}
Precision dot = vtkm::Dot(ray_dir, ray_dir);
Precision sq_mag = vtkm::Sqrt(dot);
rayDirX = ray_dir[0] / sq_mag;
rayDirY = ray_dir[1] / sq_mag;
rayDirZ = ray_dir[2] / sq_mag;
vtkm::Normalize(ray_dir);
rayDirX = ray_dir[0];
rayDirY = ray_dir[1];
rayDirZ = ray_dir[2];
}
}; // class perspective ray gen
bool Camera::operator==(const Camera& other) const
{
if (this->Height != other.Height)
return false;
if (this->Width != other.Width)
@ -427,68 +427,21 @@ bool Camera::operator==(const Camera& other) const
return false;
if (this->Zoom != other.Zoom)
return false;
if (this->Look[0] != other.Look[0])
if (this->Look != other.Look)
return false;
if (this->Look[1] != other.Look[1])
if (this->LookAt != other.LookAt)
return false;
if (this->Look[2] != other.Look[2])
if (this->Up != other.Up)
return false;
if (this->LookAt[0] != other.LookAt[0])
return false;
if (this->LookAt[1] != other.LookAt[1])
return false;
if (this->LookAt[2] != other.LookAt[2])
return false;
if (this->Up[0] != other.Up[0])
return false;
if (this->Up[1] != other.Up[1])
return false;
if (this->Up[2] != other.Up[2])
return false;
if (this->Position[0] != other.Position[0])
return false;
if (this->Position[1] != other.Position[1])
return false;
if (this->Position[2] != other.Position[2])
if (this->Position != other.Position)
return false;
return true;
}
VTKM_CONT
Camera::Camera()
{
this->Height = 500;
this->Width = 500;
this->SubsetWidth = 500;
this->SubsetHeight = 500;
this->SubsetMinX = 0;
this->SubsetMinY = 0;
this->FovY = 30.f;
this->FovX = 30.f;
this->Zoom = 1.f;
this->Look[0] = 0.f;
this->Look[1] = 0.f;
this->Look[2] = -1.f;
this->LookAt[0] = 0.f;
this->LookAt[1] = 0.f;
this->LookAt[2] = -1.f;
this->Up[0] = 0.f;
this->Up[1] = 1.f;
this->Up[2] = 0.f;
this->Position[0] = 0.f;
this->Position[1] = 0.f;
this->Position[2] = 0.f;
this->IsViewDirty = true;
}
VTKM_CONT
Camera::~Camera() {}
VTKM_CONT
void Camera::SetParameters(const vtkm::rendering::Camera& camera,
const vtkm::Int32 width,
const vtkm::Int32 height)
vtkm::Int32 width,
vtkm::Int32 height)
{
this->SetUp(camera.GetViewUp());
this->SetLookAt(camera.GetLookAt());
@ -500,7 +453,6 @@ void Camera::SetParameters(const vtkm::rendering::Camera& camera,
this->CameraView = camera;
}
VTKM_CONT
void Camera::SetHeight(const vtkm::Int32& height)
{
@ -726,19 +678,19 @@ void Camera::GetPixelData(const vtkm::cont::CoordinateSystem& coords,
}
VTKM_CONT
void Camera::CreateRays(Ray<vtkm::Float32>& rays, vtkm::Bounds bounds)
void Camera::CreateRays(Ray<vtkm::Float32>& rays, const vtkm::Bounds& bounds)
{
CreateRaysImpl(rays, bounds);
}
VTKM_CONT
void Camera::CreateRays(Ray<vtkm::Float64>& rays, vtkm::Bounds bounds)
void Camera::CreateRays(Ray<vtkm::Float64>& rays, const vtkm::Bounds& bounds)
{
CreateRaysImpl(rays, bounds);
}
template <typename Precision>
VTKM_CONT void Camera::CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds boundingBox)
VTKM_CONT void Camera::CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds& boundingBox)
{
Logger* logger = Logger::GetInstance();
vtkm::cont::Timer createTimer;
@ -748,9 +700,9 @@ VTKM_CONT void Camera::CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds b
bool ortho = this->CameraView.GetMode() == vtkm::rendering::Camera::Mode::TwoD;
this->UpdateDimensions(rays, boundingBox, ortho);
this->WriteSettingsToLog();
vtkm::cont::Timer timer;
timer.Start();
//Set the origin of the ray back to the camera position
Precision infinity;
GetInfinity(infinity);
@ -772,40 +724,44 @@ VTKM_CONT void Camera::CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds b
//Reset the camera look vector
this->Look = this->LookAt - this->Position;
vtkm::Normalize(this->Look);
vtkm::cont::Invoker invoke;
if (ortho)
{
vtkm::worklet::DispatcherMapField<Ortho2DRayGen> dispatcher(Ortho2DRayGen(this->Width,
this->Height,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY,
this->CameraView));
dispatcher.Invoke(rays.DirX,
rays.DirY,
rays.DirZ,
rays.OriginX,
rays.OriginY,
rays.OriginZ,
rays.PixelIdx); //X Y Z
invoke(Ortho2DRayGen{ this->Width,
this->Height,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY,
this->CameraView },
rays.DirX,
rays.DirY,
rays.DirZ,
rays.OriginX,
rays.OriginY,
rays.OriginZ,
rays.PixelIdx);
}
else
{
//Create the ray direction
vtkm::worklet::DispatcherMapField<PerspectiveRayGen> dispatcher(
PerspectiveRayGen(this->Width,
this->Height,
this->FovX,
this->FovY,
this->Look,
this->Up,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY));
dispatcher.Invoke(rays.DirX, rays.DirY, rays.DirZ, rays.PixelIdx); //X Y Z
invoke(PerspectiveRayGen{ this->Width,
this->Height,
this->FovX,
this->FovY,
this->Look,
this->Up,
this->Zoom,
this->SubsetWidth,
this->SubsetMinX,
this->SubsetMinY },
rays.DirX,
rays.DirY,
rays.DirZ,
rays.PixelIdx);
//Set the origin of the ray back to the camera position
vtkm::cont::ArrayHandleConstant<Precision> posX(this->Position[0], rays.NumRays);
vtkm::cont::Algorithm::Copy(posX, rays.OriginX);
@ -934,11 +890,10 @@ VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
if (imageSubsetModeOn && !ortho2D)
{
//Create a transform matrix using the rendering::camera class
vtkm::rendering::Camera camera = this->CameraView;
camera.SetFieldOfView(this->GetFieldOfView());
camera.SetLookAt(this->GetLookAt());
camera.SetPosition(this->GetPosition());
camera.SetViewUp(this->GetUp());
this->CameraView.SetFieldOfView(this->GetFieldOfView());
this->CameraView.SetLookAt(this->GetLookAt());
this->CameraView.SetPosition(this->GetPosition());
this->CameraView.SetViewUp(this->GetUp());
//
// Just create come clipping range, we ignore the zmax value in subsetting
//
@ -947,7 +902,8 @@ VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
vtkm::Max(boundingBox.Y.Max - boundingBox.Y.Min, boundingBox.Z.Max - boundingBox.Z.Min));
maxDim *= 100;
camera.SetClippingRange(.0001, maxDim);
this->CameraView.SetClippingRange(.0001, maxDim);
//Update our ViewProjection matrix
this->ViewProjectionMat =
vtkm::MatrixMultiply(this->CameraView.CreateProjectionMatrix(this->Width, this->Height),
@ -957,7 +913,7 @@ VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
else if (ortho2D)
{
// 2D rendering has a viewport that represents the area of the canvas where the image
// is drawn. Thus, we have to create rays cooresponding to that region of the
// is drawn. Thus, we have to create rays corresponding to that region of the
// canvas, so annotations are correctly rendered
vtkm::Float32 vl, vr, vb, vt;
this->CameraView.GetRealViewport(this->GetWidth(), this->GetHeight(), vl, vr, vb, vt);
@ -983,8 +939,7 @@ VTKM_CONT void Camera::UpdateDimensions(Ray<Precision>& rays,
// resize rays and buffers
if (rays.NumRays != SubsetWidth * SubsetHeight)
{
RayOperations::Resize(
rays, this->SubsetHeight * this->SubsetWidth, vtkm::cont::DeviceAdapterTagSerial());
RayOperations::Resize(rays, this->SubsetHeight * this->SubsetWidth);
}
}
@ -1001,7 +956,7 @@ void Camera::CreateDebugRay(vtkm::Vec2i_32 pixel, Ray<vtkm::Float32>& rays)
template <typename Precision>
void Camera::CreateDebugRayImp(vtkm::Vec2i_32 pixel, Ray<Precision>& rays)
{
RayOperations::Resize(rays, 1, vtkm::cont::DeviceAdapterTagSerial());
RayOperations::Resize(rays, 1);
vtkm::Int32 pixelIndex = this->Width * (this->Height - pixel[1]) + pixel[0];
rays.PixelIdx.WritePortal().Set(0, pixelIndex);
rays.OriginX.WritePortal().Set(0, this->Position[0]);

@ -12,7 +12,6 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/rendering/Camera.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/raytracing/Ray.h>
namespace vtkm
@ -24,55 +23,35 @@ namespace raytracing
class VTKM_RENDERING_EXPORT Camera
{
private:
struct PixelDataFunctor;
vtkm::Int32 Height;
vtkm::Int32 Width;
vtkm::Int32 SubsetWidth;
vtkm::Int32 SubsetHeight;
vtkm::Int32 SubsetMinX;
vtkm::Int32 SubsetMinY;
vtkm::Float32 FovX;
vtkm::Float32 FovY;
vtkm::Float32 Zoom;
bool IsViewDirty;
vtkm::Int32 Height = 500;
vtkm::Int32 Width = 500;
vtkm::Int32 SubsetWidth = 500;
vtkm::Int32 SubsetHeight = 500;
vtkm::Int32 SubsetMinX = 0;
vtkm::Int32 SubsetMinY = 0;
vtkm::Float32 FovX = 30.f;
vtkm::Float32 FovY = 30.f;
vtkm::Float32 Zoom = 1.f;
bool IsViewDirty = true;
vtkm::Vec3f_32 Look;
vtkm::Vec3f_32 Up;
vtkm::Vec3f_32 LookAt;
vtkm::Vec3f_32 Position;
vtkm::Vec3f_32 Look{ 0.f, 0.f, -1.f };
vtkm::Vec3f_32 Up{ 0.f, 1.f, 0.f };
vtkm::Vec3f_32 LookAt{ 0.f, 0.f, -1.f };
vtkm::Vec3f_32 Position{ 0.f, 0.f, 0.f };
vtkm::rendering::Camera CameraView;
vtkm::Matrix<vtkm::Float32, 4, 4> ViewProjectionMat;
public:
VTKM_CONT
Camera();
VTKM_CONT
~Camera();
// cuda does not compile if this is private
class PerspectiveRayGen;
class Ortho2DRayGen;
std::string ToString();
VTKM_CONT
void SetParameters(const vtkm::rendering::Camera& camera,
const vtkm::Int32 width,
const vtkm::Int32 height);
VTKM_CONT
void SetParameters(const vtkm::rendering::Camera& camera,
vtkm::rendering::CanvasRayTracer& canvas);
void SetParameters(const vtkm::rendering::Camera& camera, vtkm::Int32 width, vtkm::Int32 height);
VTKM_CONT
void SetHeight(const vtkm::Int32& height);
VTKM_CONT
void WriteSettingsToLog();
VTKM_CONT
vtkm::Int32 GetHeight() const;
@ -125,10 +104,10 @@ public:
bool GetIsViewDirty() const;
VTKM_CONT
void CreateRays(Ray<vtkm::Float32>& rays, vtkm::Bounds bounds);
void CreateRays(Ray<vtkm::Float32>& rays, const vtkm::Bounds& bounds);
VTKM_CONT
void CreateRays(Ray<vtkm::Float64>& rays, vtkm::Bounds bounds);
void CreateRays(Ray<vtkm::Float64>& rays, const vtkm::Bounds& bounds);
VTKM_CONT
void GetPixelData(const vtkm::cont::CoordinateSystem& coords,
@ -136,7 +115,7 @@ public:
vtkm::Float32& aveRayDistance);
template <typename Precision>
VTKM_CONT void CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds boundingBox);
VTKM_CONT void CreateRaysImpl(Ray<Precision>& rays, const vtkm::Bounds& boundingBox);
void CreateDebugRay(vtkm::Vec2i_32 pixel, Ray<vtkm::Float32>& rays);
@ -146,10 +125,14 @@ public:
private:
template <typename Precision>
void CreateDebugRayImp(vtkm::Vec2i_32 pixel, Ray<Precision>& rays);
VTKM_CONT void CreateDebugRayImp(vtkm::Vec2i_32 pixel, Ray<Precision>& rays);
VTKM_CONT
void FindSubset(const vtkm::Bounds& bounds);
VTKM_CONT
void WriteSettingsToLog();
template <typename Precision>
VTKM_CONT void UpdateDimensions(Ray<Precision>& rays,
const vtkm::Bounds& boundingBox,

@ -430,7 +430,7 @@ public:
cellIndex[dir1] = cellIndex[dir1] + dir1Offset;
cellIndex[dir2] = cellIndex[dir2] + dir2Offset;
vtkm::Id cellId = Connectivity.LogicalToFlatToIndex(cellIndex);
vtkm::Id cellId = Connectivity.LogicalToFlatVisitIndex(cellIndex);
vtkm::VecVariable<vtkm::Id, 8> cellIndices = Connectivity.GetIndices(cellId);
// Look up the offset into the face list for each cell type

@ -69,7 +69,6 @@ public:
vtkm::cont::ArrayHandle<Precision> IntersectionY;
vtkm::cont::ArrayHandle<Precision> IntersectionZ;
vtkm::cont::ArrayHandle<Precision> OriginX; //ray Origin
vtkm::cont::ArrayHandle<Precision> OriginY;
vtkm::cont::ArrayHandle<Precision> OriginZ;
@ -117,40 +116,26 @@ public:
DebugHeight = -1;
}
struct EnableIntersectionDataFunctor
{
template <typename Device>
VTKM_CONT bool operator()(Device, Ray<Precision>* self)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->EnableIntersectionData(Device());
return true;
}
};
void EnableIntersectionData() { vtkm::cont::TryExecute(EnableIntersectionDataFunctor(), this); }
template <typename Device>
void EnableIntersectionData(Device)
void EnableIntersectionData()
{
if (IntersectionDataEnabled)
{
return;
}
vtkm::cont::Token token;
IntersectionDataEnabled = true;
IntersectionX.PrepareForOutput(NumRays, Device(), token);
IntersectionY.PrepareForOutput(NumRays, Device(), token);
IntersectionZ.PrepareForOutput(NumRays, Device(), token);
U.PrepareForOutput(NumRays, Device(), token);
V.PrepareForOutput(NumRays, Device(), token);
Scalar.PrepareForOutput(NumRays, Device(), token);
NormalX.PrepareForOutput(NumRays, Device(), token);
NormalY.PrepareForOutput(NumRays, Device(), token);
NormalZ.PrepareForOutput(NumRays, Device(), token);
IntersectionX.Allocate(NumRays);
IntersectionY.Allocate(NumRays);
IntersectionZ.Allocate(NumRays);
U.Allocate(NumRays);
V.Allocate(NumRays);
Scalar.Allocate(NumRays);
NormalX.Allocate(NumRays);
NormalY.Allocate(NumRays);
NormalZ.Allocate(NumRays);
}
void DisableIntersectionData()
@ -173,90 +158,9 @@ public:
NormalZ.ReleaseResources();
}
template <typename Device>
VTKM_CONT Ray(const vtkm::Int32 size, Device, bool enableIntersectionData = false)
{
NumRays = size;
IntersectionDataEnabled = enableIntersectionData;
ChannelBuffer<Precision> buffer;
this->Buffers.push_back(buffer);
DebugWidth = -1;
DebugHeight = -1;
this->Resize(size, Device());
}
struct ResizeFunctor
{
template <typename Device>
VTKM_CONT bool operator()(Device, Ray<Precision>* self, const vtkm::Int32 size)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
self->Resize(size, Device());
return true;
}
};
VTKM_CONT void Resize(const vtkm::Int32 size) { vtkm::cont::TryExecute(ResizeFunctor(), size); }
template <typename Device>
VTKM_CONT void Resize(const vtkm::Int32 size, Device)
{
NumRays = size;
vtkm::cont::Token token;
if (IntersectionDataEnabled)
{
IntersectionX.PrepareForOutput(NumRays, Device(), token);
IntersectionY.PrepareForOutput(NumRays, Device(), token);
IntersectionZ.PrepareForOutput(NumRays, Device(), token);
U.PrepareForOutput(NumRays, Device(), token);
V.PrepareForOutput(NumRays, Device(), token);
Scalar.PrepareForOutput(NumRays, Device(), token);
NormalX.PrepareForOutput(NumRays, Device(), token);
NormalY.PrepareForOutput(NumRays, Device(), token);
NormalZ.PrepareForOutput(NumRays, Device(), token);
}
OriginX.PrepareForOutput(NumRays, Device(), token);
OriginY.PrepareForOutput(NumRays, Device(), token);
OriginZ.PrepareForOutput(NumRays, Device(), token);
DirX.PrepareForOutput(NumRays, Device(), token);
DirY.PrepareForOutput(NumRays, Device(), token);
DirZ.PrepareForOutput(NumRays, Device(), token);
Distance.PrepareForOutput(NumRays, Device(), token);
MinDistance.PrepareForOutput(NumRays, Device(), token);
MaxDistance.PrepareForOutput(NumRays, Device(), token);
Status.PrepareForOutput(NumRays, Device(), token);
HitIdx.PrepareForOutput(NumRays, Device(), token);
PixelIdx.PrepareForOutput(NumRays, Device(), token);
Intersection =
vtkm::cont::make_ArrayHandleCompositeVector(IntersectionX, IntersectionY, IntersectionZ);
Normal = vtkm::cont::make_ArrayHandleCompositeVector(NormalX, NormalY, NormalZ);
Origin = vtkm::cont::make_ArrayHandleCompositeVector(OriginX, OriginY, OriginZ);
Dir = vtkm::cont::make_ArrayHandleCompositeVector(DirX, DirY, DirZ);
const size_t numBuffers = this->Buffers.size();
for (size_t i = 0; i < numBuffers; ++i)
{
this->Buffers[i].Resize(NumRays, Device());
}
}
VTKM_CONT
void AddBuffer(const vtkm::Int32 numChannels, const std::string name)
{
ChannelBuffer<Precision> buffer(numChannels, this->NumRays);
buffer.SetName(name);
this->Buffers.push_back(buffer);
@ -265,41 +169,24 @@ public:
VTKM_CONT
bool HasBuffer(const std::string name)
{
size_t numBuffers = this->Buffers.size();
bool found = false;
for (size_t i = 0; i < numBuffers; ++i)
for (const auto& buffer : this->Buffers)
{
if (this->Buffers[i].GetName() == name)
{
found = true;
break;
}
if (buffer.GetName() == name)
return true;
}
return found;
return false;
}
VTKM_CONT
ChannelBuffer<Precision>& GetBuffer(const std::string name)
{
const size_t numBuffers = this->Buffers.size();
bool found = false;
size_t index = 0;
for (size_t i = 0; i < numBuffers; ++i)
for (auto&& buffer : this->Buffers)
{
if (this->Buffers[i].GetName() == name)
{
found = true;
index = i;
}
}
if (found)
{
return this->Buffers.at(index);
}
else
{
throw vtkm::cont::ErrorBadValue("No channel buffer with requested name: " + name);
if (buffer.GetName() == name)
return buffer;
}
throw vtkm::cont::ErrorBadValue("No channel buffer with requested name: " + name);
}
void PrintRay(vtkm::Id pixelId)

Some files were not shown because too many files have changed in this diff Show More