diff --git a/CMake/FindMPI.cmake b/CMake/FindMPI.cmake index 734510e53..3ecf1facd 100644 --- a/CMake/FindMPI.cmake +++ b/CMake/FindMPI.cmake @@ -306,6 +306,19 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95 mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r mpixlf mpixlf_r mpxlf mpxlf_r) +# Allow CMake 3.8.0 to use OS specific `separate_arguments` signature. +# Otherwise use the 3.9 NATIVE_COMMAND feature that does this for us +# automatically +if (CMAKE_VERSION VERSION_LESS "3.9.0") + if (WIN32 AND NOT CYGWIN) + set(_MPI_parse_kind WINDOWS_COMMAND) + else () + set(_MPI_parse_kind UNIX_COMMAND) + endif () +else () + set(_MPI_parse_kind NATIVE_COMMAND) +endif () + # Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler, # attempt all of them. # By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper @@ -340,9 +353,9 @@ unset(_MPIEXEC_NAMES_BASE) function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) if(DEFINED MPI_${LANG}_COMPILER_FLAGS) - separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_${LANG}_COMPILER_FLAGS}") + separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS ${_MPI_parse_kind} "${MPI_${LANG}_COMPILER_FLAGS}") else() - separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_COMPILER_FLAGS}") + separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS ${_MPI_parse_kind} "${MPI_COMPILER_FLAGS}") endif() execute_process( COMMAND ${MPI_${LANG}_COMPILER} ${_MPI_COMPILER_WRAPPER_OPTIONS} ${QUERY_FLAG} @@ -630,7 +643,7 @@ function (_MPI_interrogate_compiler LANG) if (NOT MPI_ALL_INCLUDE_PATHS) _MPI_check_compiler(${LANG} "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN) if(MPI_INCDIRS_COMPILER_RETURN) - separate_arguments(MPI_ALL_INCLUDE_PATHS NATIVE_COMMAND "${MPI_INCDIRS_CMDLINE}") + separate_arguments(MPI_ALL_INCLUDE_PATHS ${_MPI_parse_kind} "${MPI_INCDIRS_CMDLINE}") endif() endif() @@ -698,7 +711,7 @@ function (_MPI_interrogate_compiler LANG) if (NOT MPI_ALL_LINK_PATHS) _MPI_check_compiler(${LANG} "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN) if(MPI_LIBDIRS_COMPILER_RETURN) - separate_arguments(MPI_ALL_LINK_PATHS NATIVE_COMMAND "${MPI_LIBDIRS_CMDLINE}") + separate_arguments(MPI_ALL_LINK_PATHS ${_MPI_parse_kind} "${MPI_LIBDIRS_CMDLINE}") endif() endif() @@ -1142,8 +1155,14 @@ macro(_MPI_create_imported_target LANG) endif() # When this is consumed for compiling CUDA, use '-Xcompiler' to wrap '-pthread'. - string(REPLACE "-pthread" "$<$:SHELL:-Xcompiler >-pthread" - _MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}") + # This only robustly works with CMake 3.12+ as before than it would be an error + # when evaluated with CUDA language disabled. + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12 OR CMAKE_CUDA_COMPILER_LOADED) + string(REPLACE "-pthread" "$<$:SHELL:-Xcompiler >-pthread" + _MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}") + else() + set(_MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}") + endif() set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}") unset(_MPI_${LANG}_COMPILE_OPTIONS) @@ -1151,7 +1170,7 @@ macro(_MPI_create_imported_target LANG) set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_LIBRARIES "") if(MPI_${LANG}_LINK_FLAGS) - separate_arguments(_MPI_${LANG}_LINK_FLAGS NATIVE_COMMAND "${MPI_${LANG}_LINK_FLAGS}") + separate_arguments(_MPI_${LANG}_LINK_FLAGS ${_MPI_parse_kind} "${MPI_${LANG}_LINK_FLAGS}") if(CMAKE_VERSION VERSION_LESS 3.13) set_property(TARGET MPI::MPI_${LANG} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${_MPI_${LANG}_LINK_FLAGS}") else() @@ -1343,7 +1362,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES) unset(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS) unset(MPI_${LANG}_EXTRA_COMPILE_OPTIONS) if(MPI_${LANG}_COMPILE_FLAGS) - separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}") + separate_arguments(MPI_SEPARATE_FLAGS ${_MPI_parse_kind} "${MPI_${LANG}_COMPILE_FLAGS}") foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS) if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)") list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}") @@ -1712,7 +1731,13 @@ foreach(LANG IN ITEMS C CXX Fortran) set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}") unset(MPI_${LANG}_COMPILE_FLAGS) if(MPI_${LANG}_COMPILE_OPTIONS) - list(JOIN MPI_${LANG}_COMPILE_FLAGS " " MPI_${LANG}_COMPILE_OPTIONS) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) + list(JOIN MPI_${LANG}_COMPILE_OPTIONS " " MPI_${LANG}_COMPILE_FLAGS) + else() + foreach(_MPI_OPT IN LISTS MPI_${LANG}_COMPILE_OPTIONS) + string(APPEND MPI_${LANG}_COMPILE_FLAGS " ${_MPI_OPT}") + endforeach() + endif() endif() if(MPI_${LANG}_COMPILE_DEFINITIONS) foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS) diff --git a/CMake/VTKmCheckCopyright.cmake b/CMake/VTKmCheckCopyright.cmake index 073d15b2d..c84359b2f 100644 --- a/CMake/VTKmCheckCopyright.cmake +++ b/CMake/VTKmCheckCopyright.cmake @@ -15,7 +15,7 @@ ## cmake -DVTKm_SOURCE_DIR= -P /CMake/VTKMCheckCopyright.cmake ## -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) set(FILES_TO_CHECK *.txt *.cmake diff --git a/CMake/VTKmCompilerFlags.cmake b/CMake/VTKmCompilerFlags.cmake index bc4e7948d..257646b96 100644 --- a/CMake/VTKmCompilerFlags.cmake +++ b/CMake/VTKmCompilerFlags.cmake @@ -73,10 +73,17 @@ if(VTKM_COMPILER_IS_MSVC) target_compile_definitions(vtkm_developer_flags INTERFACE "_SCL_SECURE_NO_WARNINGS" "_CRT_SECURE_NO_WARNINGS") + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15) + set(cxx_flags "-W3") + set(cuda_flags "-Xcompiler=-W3") + endif() + list(APPEND cxx_flags -wd4702 -wd4505) + list(APPEND cuda_flags "-Xcompiler=-wd4702,-wd4505") + #Setup MSVC warnings with CUDA and CXX - target_compile_options(vtkm_developer_flags INTERFACE $<$:-wd4702 -wd4505>) + target_compile_options(vtkm_developer_flags INTERFACE $<$:${cxx_flags}>) if(TARGET vtkm::cuda) - target_compile_options(vtkm_developer_flags INTERFACE $<$:-Xcompiler=-wd4702,-wd4505 -Xcudafe=--diag_suppress=1394,--diag_suppress=766>) + target_compile_options(vtkm_developer_flags INTERFACE $<$:${cuda_flags} -Xcudafe=--diag_suppress=1394,--diag_suppress=766>) endif() if(MSVC_VERSION LESS 1900) diff --git a/CMake/VTKmDeviceAdapters.cmake b/CMake/VTKmDeviceAdapters.cmake index 775a6f7e3..8d3d795ee 100644 --- a/CMake/VTKmDeviceAdapters.cmake +++ b/CMake/VTKmDeviceAdapters.cmake @@ -86,7 +86,7 @@ endif() if(VTKm_ENABLE_OPENMP AND NOT TARGET vtkm::openmp) - cmake_minimum_required(VERSION 3.9...3.14 FATAL_ERROR) + cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR) find_package(OpenMP 4.0 REQUIRED COMPONENTS CXX QUIET) add_library(vtkm::openmp INTERFACE IMPORTED GLOBAL) @@ -107,7 +107,7 @@ if(VTKm_ENABLE_OPENMP AND NOT TARGET vtkm::openmp) endif() if(VTKm_ENABLE_CUDA) - cmake_minimum_required(VERSION 3.13...3.14 FATAL_ERROR) + cmake_minimum_required(VERSION 3.13...3.15 FATAL_ERROR) enable_language(CUDA) if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" AND diff --git a/CMakeLists.txt b/CMakeLists.txt index 872eba880..fe3f3f476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,11 +11,11 @@ # If you want CUDA support, you will need to have CMake 3.9 on Linux/OSX. # We require CMake 3.11 with the MSVC generator as the $ # generator expression is not supported on older versions. -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project (VTKm) if(${CMAKE_GENERATOR} MATCHES "Visual Studio") - cmake_minimum_required(VERSION 3.11...3.14 FATAL_ERROR) + cmake_minimum_required(VERSION 3.11...3.15 FATAL_ERROR) endif() # Update module path diff --git a/README.md b/README.md index 05f73389f..965a52c70 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ inputData.GetPointField(fieldName).GetRange(&range); vtkm::Float64 isovalue = range.Center(); // Create an isosurface filter -vtkm::filter::MarchingCubes filter; +vtkm::filter::Contour filter; filter.SetIsoValue(0, isovalue); filter.SetActiveField(fieldName); vtkm::cont::DataSet outputData = filter.Execute(inputData); diff --git a/benchmarking/BenchmarkFilters.cxx b/benchmarking/BenchmarkFilters.cxx index 57f4e5084..d0d37f8ee 100644 --- a/benchmarking/BenchmarkFilters.cxx +++ b/benchmarking/BenchmarkFilters.cxx @@ -30,10 +30,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -468,12 +468,12 @@ class BenchmarkFilters VTKM_MAKE_BENCHMARK(WarpVector, BenchWarpVector); template - struct BenchMarchingCubes + struct BenchContour { - vtkm::filter::MarchingCubes Filter; + vtkm::filter::Contour Filter; VTKM_CONT - BenchMarchingCubes(vtkm::Id numIsoVals, bool mergePoints, bool normals, bool fastNormals) + BenchContour(vtkm::Id numIsoVals, bool mergePoints, bool normals, bool fastNormals) : Filter() { this->Filter.SetActiveField(PointScalarsName, vtkm::cont::Field::Association::POINTS); @@ -510,25 +510,25 @@ class BenchmarkFilters std::string Description() const { std::ostringstream desc; - desc << "MarchingCubes numIsoVal=" << this->Filter.GetNumberOfIsoValues() << " " + desc << "Contour numIsoVal=" << this->Filter.GetNumberOfIsoValues() << " " << "mergePoints=" << this->Filter.GetMergeDuplicatePoints() << " " << "normals=" << this->Filter.GetGenerateNormals() << " " << "fastNormals=" << this->Filter.GetComputeFastNormalsForStructured(); return desc.str(); } }; - VTKM_MAKE_BENCHMARK(MarchingCubes1FFF, BenchMarchingCubes, 1, false, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes3FFF, BenchMarchingCubes, 3, false, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes12FFF, BenchMarchingCubes, 12, false, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes1TFF, BenchMarchingCubes, 1, true, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes3TFF, BenchMarchingCubes, 3, true, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes12TFF, BenchMarchingCubes, 12, true, false, false); - VTKM_MAKE_BENCHMARK(MarchingCubes1FTF, BenchMarchingCubes, 1, false, true, false); - VTKM_MAKE_BENCHMARK(MarchingCubes3FTF, BenchMarchingCubes, 3, false, true, false); - VTKM_MAKE_BENCHMARK(MarchingCubes12FTF, BenchMarchingCubes, 12, false, true, false); - VTKM_MAKE_BENCHMARK(MarchingCubes1FTT, BenchMarchingCubes, 1, false, true, true); - VTKM_MAKE_BENCHMARK(MarchingCubes3FTT, BenchMarchingCubes, 3, false, true, true); - VTKM_MAKE_BENCHMARK(MarchingCubes12FTT, BenchMarchingCubes, 12, false, true, true); + VTKM_MAKE_BENCHMARK(Contour1FFF, BenchContour, 1, false, false, false); + VTKM_MAKE_BENCHMARK(Contour3FFF, BenchContour, 3, false, false, false); + VTKM_MAKE_BENCHMARK(Contour12FFF, BenchContour, 12, false, false, false); + VTKM_MAKE_BENCHMARK(Contour1TFF, BenchContour, 1, true, false, false); + VTKM_MAKE_BENCHMARK(Contour3TFF, BenchContour, 3, true, false, false); + VTKM_MAKE_BENCHMARK(Contour12TFF, BenchContour, 12, true, false, false); + VTKM_MAKE_BENCHMARK(Contour1FTF, BenchContour, 1, false, true, false); + VTKM_MAKE_BENCHMARK(Contour3FTF, BenchContour, 3, false, true, false); + VTKM_MAKE_BENCHMARK(Contour12FTF, BenchContour, 12, false, true, false); + VTKM_MAKE_BENCHMARK(Contour1FTT, BenchContour, 1, false, true, true); + VTKM_MAKE_BENCHMARK(Contour3FTT, BenchContour, 3, false, true, true); + VTKM_MAKE_BENCHMARK(Contour12FTT, BenchContour, 12, false, true, true); template struct BenchExternalFaces @@ -747,26 +747,26 @@ public: { if (ReducedOptions) { - VTKM_RUN_BENCHMARK(MarchingCubes1FFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12TFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FTF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FTT, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour1FFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12TFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FTF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FTT, dummyTypes, id); } else { - VTKM_RUN_BENCHMARK(MarchingCubes1FFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes3FFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes1TFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes3TFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12TFF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes1FTF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes3FTF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FTF, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes1FTT, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes3FTT, dummyTypes, id); - VTKM_RUN_BENCHMARK(MarchingCubes12FTT, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour1FFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour3FFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour1TFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour3TFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12TFF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour1FTF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour3FTF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FTF, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour1FTT, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour3FTT, dummyTypes, id); + VTKM_RUN_BENCHMARK(Contour12FTT, dummyTypes, id); } } if (benches & BenchmarkName::EXTERNAL_FACES) diff --git a/docs/changelog/array-handle-soa.md b/docs/changelog/array-handle-soa.md new file mode 100644 index 000000000..b7fc7d1b4 --- /dev/null +++ b/docs/changelog/array-handle-soa.md @@ -0,0 +1,61 @@ +# Added ArrayHandleSOA + +`ArrayHandleSOA` behaves like a regular `ArrayHandle` (with a basic +storage) except that if you specify a `ValueType` of a `Vec` or a +`Vec`-like, it will actually store each component in a separate physical +array. When data are retrieved from the array, they are reconstructed into +`Vec` objects as expected. + +The intention of this array type is to help cover the most common ways data +is lain out in memory. Typically, arrays of data are either an "array of +structures" like the basic storage where you have a single array of +structures (like `Vec`) or a "structure of arrays" where you have an array +of a basic type (like `float`) for each component of the data being +represented. The `ArrayHandleSOA` makes it easy to cover this second case +without creating special types. + +`ArrayHandleSOA` can be constructed from a collection of `ArrayHandle` with +basic storage. This allows you to construct `Vec` arrays from components +without deep copies. + +``` cpp +std::vector accel0; +std::vector accel1; +std::vector accel2; + +// Let's say accel arrays are set to some field of acceleration vectors by +// some other software. + +vtkm::cont::ArrayHandle accelHandle0 = vtkm::cont::make_ArrayHandle(accel0); +vtkm::cont::ArrayHandle accelHandle1 = vtkm::cont::make_ArrayHandle(accel1); +vtkm::cont::ArrayHandle accelHandle2 = vtkm::cont::make_ArrayHandle(accel2); + +vtkm::cont::ArrayHandleSOA accel = { accelHandle0, accelHandle1, accelHandle2 }; +``` + +Also provided are constructors and versions of `make_ArrayHandleSOA` that +take `std::vector` or C arrays as either initializer lists or variable +arguments. + +``` cpp +std::vector accel0; +std::vector accel1; +std::vector accel2; + +// Let's say accel arrays are set to some field of acceleration vectors by +// some other software. + +vtkm::cont::ArrayHandleSOA accel = { accel0, accel1, accel2 }; +``` + +However, setting arrays is a little awkward because you also have to +specify the length. This is done either outside the initializer list or as +the first argument. + +``` cpp +vtkm::cont::make_ArrayHandleSOA({ array0, array1, array2 }, ARRAY_SIZE); +``` + +``` cpp +vtkm::cont::make_ArrayHandleSOA(ARRAY_SIZE, array0, array1, array2); +``` diff --git a/docs/changelog/simplify-create-fields.md b/docs/changelog/simplify-create-fields.md new file mode 100644 index 000000000..a6f763375 --- /dev/null +++ b/docs/changelog/simplify-create-fields.md @@ -0,0 +1,21 @@ +# Simplify creating Fields from ArrayHandles + +VTK-m now offers `make_FieldPoint` and `make_FieldCell` functions +that reduce the complexity of construction `vtkm::cont::Fields` +from `vtkm::cont::ArrayHandles`. + +Previously to construct a point and cell fields you would do: +```cpp +vtkm::cont::ArrayHandle pointHandle; +vtkm::cont::ArrayHandle cellHandle; +vtkm::cont::Field pointField("p", vtkm::cont::Field::Association::POINTS, pointHandle); +vtkm::cont::Field cellField("c", vtkm::cont::Field::Association::CELL_SET, "cells", cellHandle); +``` + +Now with the new `make_` functions you can do: +```cpp +vtkm::cont::ArrayHandle pointHandle; +vtkm::cont::ArrayHandle cellHandle; +auto pointField = vtkm::cont::make_FieldPoint("p", pointHandle); +auto cellField = vtkm::cont::make_FieldCell("c", "cells", cellHandle); +``` diff --git a/docs/changelog/simplify-create-result.md b/docs/changelog/simplify-create-result.md new file mode 100644 index 000000000..198104395 --- /dev/null +++ b/docs/changelog/simplify-create-result.md @@ -0,0 +1,27 @@ +# Simplify creating results for Filters + +As part of the process of making VTK-m filters easier to write for newcomers +whe have a couple of changes to make constructing the output `vtkm::cont::DataSet` +easier. + +First we have moved the `CreateResult` functions out of the internals namespace +and directly into `vtkm::filter`. This makes it clearer to developers that this +was the 'proper' way to construct the output DataSet. + +Second we have streamlined the collection of `vtkm::filter::CreateResult` methods to +require the user to provide less information and provide clearer names explaing what +they do. + +To construct output identical to the input but with a new field you now just pass +the `vtkm::filter::FieldMetadata` as a paramter instead of explictly stating +the field association, and the possible cell set name: +```cpp +return CreateResult(input, newField, name, fieldMetadata); +``` + +To construct output identical to the input but with a cell field added you +can now pass the `vtkm::cont::CellSet` as a paramter instead of explictly stating +the field association, and the cell set name: +```cpp +return CreateResultFieldCell(input, newCellField, name, cellset); +``` diff --git a/docs/changelog/threshold-explicit-cells.md b/docs/changelog/threshold-explicit-cells.md new file mode 100644 index 000000000..53a5f2585 --- /dev/null +++ b/docs/changelog/threshold-explicit-cells.md @@ -0,0 +1,21 @@ +# Copy Threshold output to a CellSetExplicit + +Perhaps a better title for this change would be "Make the Threshold filter +not totally useless." + +A long standing issue with the Threshold filter is that its output CellSet +was stored in a CellSetPermutation. This made Threshold hyper- efficient +because it required hardly any data movement to implement. However, the +problem was that any other unit that had to use the CellSet failed. To have +VTK-m handle that output correctly in other filters and writers, they all +would have to check for the existance of CellSetPermutation. And +CellSetPermutation is templated on the CellSet type it is permuting, so all +units would have to compile special cases for all these combinations. This +is not likely to be feasible in any static solution. + +The simple solution, implemented here, is to deep copy the cells to a +CellSetExplicit, which is a known type that is already used everywhere in +VTK-m. The solution is a bit disappointing since it requires more memory +and time to build. But it is on par with solutions in other libraries (like +VTK). And it really does not matter how efficient the old solution was if +it was useless. diff --git a/examples/clipping/CMakeLists.txt b/examples/clipping/CMakeLists.txt index be7c72315..7b1a83294 100644 --- a/examples/clipping/CMakeLists.txt +++ b/examples/clipping/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(Clipping CXX) #Find the VTK-m package diff --git a/examples/contour_tree/CMakeLists.txt b/examples/contour_tree/CMakeLists.txt index 172719963..2b30448a5 100644 --- a/examples/contour_tree/CMakeLists.txt +++ b/examples/contour_tree/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(ContourTree CXX) #Find the VTK-m package diff --git a/examples/cosmotools/CMakeLists.txt b/examples/cosmotools/CMakeLists.txt index f47d77b0c..120a6da45 100644 --- a/examples/cosmotools/CMakeLists.txt +++ b/examples/cosmotools/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(CosmoTools CXX) #Find the VTK-m package diff --git a/examples/demo/CMakeLists.txt b/examples/demo/CMakeLists.txt index 1d64afb0d..af3139ae1 100644 --- a/examples/demo/CMakeLists.txt +++ b/examples/demo/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(VTKmDemo CXX) #Find the VTK-m package diff --git a/examples/demo/Demo.cxx b/examples/demo/Demo.cxx index dd75f036c..f2e1feee4 100644 --- a/examples/demo/Demo.cxx +++ b/examples/demo/Demo.cxx @@ -17,7 +17,7 @@ #include #include -#include +#include // This example creates a simple data set and uses VTK-m's rendering engine to render an image and // write that image to a file. It then computes an isosurface on the input data set and renders @@ -76,14 +76,14 @@ int main(int argc, char* argv[]) view.SaveAs("demo_input.pnm"); // Create an isosurface filter - vtkm::filter::MarchingCubes filter; + vtkm::filter::Contour filter; filter.SetGenerateNormals(false); filter.SetMergeDuplicatePoints(false); filter.SetIsoValue(0, isovalue); filter.SetActiveField(fieldName); vtkm::cont::DataSet outputData = filter.Execute(inputData); // Render a separate image with the output isosurface - std::cout << "about to render the results of the MarchingCubes filter" << std::endl; + std::cout << "about to render the results of the Contour filter" << std::endl; vtkm::rendering::Scene scene2; vtkm::rendering::Actor actor2(outputData.GetCellSet(), outputData.GetCoordinateSystem(), diff --git a/examples/game_of_life/CMakeLists.txt b/examples/game_of_life/CMakeLists.txt index 3bbab95c9..57901709b 100644 --- a/examples/game_of_life/CMakeLists.txt +++ b/examples/game_of_life/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(GameOfLife CXX) #Find the VTK-m package diff --git a/examples/hello_worklet/CMakeLists.txt b/examples/hello_worklet/CMakeLists.txt index fdc63c893..36d99fbc1 100644 --- a/examples/hello_worklet/CMakeLists.txt +++ b/examples/hello_worklet/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.9...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR) project(HelloWorklet CXX) #Find the VTK-m package diff --git a/examples/histogram/CMakeLists.txt b/examples/histogram/CMakeLists.txt index 3b9f17cf0..ee8776092 100644 --- a/examples/histogram/CMakeLists.txt +++ b/examples/histogram/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(Histogram CXX) #Find the VTK-m package diff --git a/examples/lagrangian/CMakeLists.txt b/examples/lagrangian/CMakeLists.txt index ba0e2e75d..1060a31e8 100644 --- a/examples/lagrangian/CMakeLists.txt +++ b/examples/lagrangian/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) #Find the VTK-m package find_package(VTKm REQUIRED QUIET) diff --git a/examples/lagrangian_structures/CMakeLists.txt b/examples/lagrangian_structures/CMakeLists.txt index 93d8351ea..84adb5889 100644 --- a/examples/lagrangian_structures/CMakeLists.txt +++ b/examples/lagrangian_structures/CMakeLists.txt @@ -9,7 +9,7 @@ ## PURPOSE. See the above copyright notice for more information. ## ##============================================================================= -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(ParticleAdvection CXX) #Find the VTK-m package diff --git a/examples/mesh_quality/CMakeLists.txt b/examples/mesh_quality/CMakeLists.txt index 7bd7a3f16..38c3229a0 100644 --- a/examples/mesh_quality/CMakeLists.txt +++ b/examples/mesh_quality/CMakeLists.txt @@ -19,7 +19,7 @@ ## this software. ## ##============================================================================= -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(MeshQuality CXX) #Find the VTK-m package diff --git a/examples/multi_backend/CMakeLists.txt b/examples/multi_backend/CMakeLists.txt index 11edc475a..7e54382a9 100644 --- a/examples/multi_backend/CMakeLists.txt +++ b/examples/multi_backend/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(MultiBackend CXX) #Find the VTK-m package diff --git a/examples/oscillator/CMakeLists.txt b/examples/oscillator/CMakeLists.txt index a51676a94..955fbade7 100644 --- a/examples/oscillator/CMakeLists.txt +++ b/examples/oscillator/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(Oscillator CXX) #Find the VTK-m package diff --git a/examples/particle_advection/CMakeLists.txt b/examples/particle_advection/CMakeLists.txt index 739d67b98..0b32bd79b 100644 --- a/examples/particle_advection/CMakeLists.txt +++ b/examples/particle_advection/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(ParticleAdvection CXX) #Find the VTK-m package diff --git a/examples/polyline_archimedean_helix/CMakeLists.txt b/examples/polyline_archimedean_helix/CMakeLists.txt index 22efa87c9..8f0bc5ac0 100644 --- a/examples/polyline_archimedean_helix/CMakeLists.txt +++ b/examples/polyline_archimedean_helix/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(PolyLineArchimedeanHelix CXX) find_package(VTKm REQUIRED QUIET) diff --git a/examples/redistribute_points/CMakeLists.txt b/examples/redistribute_points/CMakeLists.txt index 42f1a4564..f53189d7d 100644 --- a/examples/redistribute_points/CMakeLists.txt +++ b/examples/redistribute_points/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(RedistributePoints CXX) #Find the VTK-m package diff --git a/examples/temporal_advection/CMakeLists.txt b/examples/temporal_advection/CMakeLists.txt index 5fdb43594..39ad2c6a6 100644 --- a/examples/temporal_advection/CMakeLists.txt +++ b/examples/temporal_advection/CMakeLists.txt @@ -9,7 +9,7 @@ ##============================================================================ #Find the VTK-m package -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(TemporalAdvection CXX) #Find the VTK-m package diff --git a/examples/tetrahedra/CMakeLists.txt b/examples/tetrahedra/CMakeLists.txt index 6b5bbb781..dc2771a5b 100644 --- a/examples/tetrahedra/CMakeLists.txt +++ b/examples/tetrahedra/CMakeLists.txt @@ -7,7 +7,7 @@ ## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ## PURPOSE. See the above copyright notice for more information. ##============================================================================ -cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR) +cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR) project(Tetrahedra CXX) #Find the VTK-m package diff --git a/vtkm/ImplicitFunction.h b/vtkm/ImplicitFunction.h index 0fe048dc3..84077728c 100644 --- a/vtkm/ImplicitFunction.h +++ b/vtkm/ImplicitFunction.h @@ -10,6 +10,7 @@ #ifndef vtk_m_ImplicitFunction_h #define vtk_m_ImplicitFunction_h +#include #include #include #include @@ -99,12 +100,19 @@ private: //============================================================================ /// \brief Implicit function for a box +/// +/// \c Box computes the implicit function and/or gradient for a axis-aligned +/// bounding box. Each side of the box is orthogonal to all other sides +/// meeting along shared edges and all faces are orthogonal to the x-y-z +/// coordinate axes. + class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction { public: + /// \brief Construct box with center at (0,0,0) and each side of length 1.0. VTKM_EXEC_CONT Box() - : MinPoint(Vector(Scalar(0))) - , MaxPoint(Vector(Scalar(0))) + : MinPoint(Vector(Scalar(-0.5))) + , MaxPoint(Vector(Scalar(0.5))) { } @@ -120,6 +128,8 @@ public: { } + VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); } + VTKM_CONT void SetMinPoint(const Vector& point) { this->MinPoint = point; @@ -136,6 +146,19 @@ public: VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; } + VTKM_CONT void SetBounds(const vtkm::Bounds& bounds) + { + this->SetMinPoint({ Scalar(bounds.X.Min), Scalar(bounds.Y.Min), Scalar(bounds.Z.Min) }); + this->SetMaxPoint({ Scalar(bounds.X.Max), Scalar(bounds.Y.Max), Scalar(bounds.Z.Max) }); + } + + VTKM_EXEC_CONT vtkm::Bounds GetBounds() const + { + return vtkm::Bounds(vtkm::Range(this->MinPoint[0], this->MaxPoint[0]), + vtkm::Range(this->MinPoint[1], this->MaxPoint[1]), + vtkm::Range(this->MinPoint[2], this->MaxPoint[2])); + } + VTKM_EXEC_CONT Scalar Value(const Vector& point) const final { Scalar minDistance = vtkm::NegativeInfinity32(); @@ -333,13 +356,24 @@ private: //============================================================================ /// \brief Implicit function for a cylinder +/// +/// \c Cylinder computes the implicit function and function gradient +/// for a cylinder using F(r)=r^2-Radius^2. By default the Cylinder is +/// centered at the origin and the axis of rotation is along the +/// y-axis. You can redefine the center and axis of rotation by setting +/// the Center and Axis data members. +/// +/// Note that the cylinder is infinite in extent. +/// class VTKM_ALWAYS_EXPORT Cylinder final : public vtkm::ImplicitFunction { public: + /// Construct cylinder radius of 0.5; centered at origin with axis + /// along y coordinate axis. VTKM_EXEC_CONT Cylinder() : Center(Scalar(0)) - , Axis(Scalar(1), Scalar(0), Scalar(0)) - , Radius(Scalar(0.2)) + , Axis(Scalar(0), Scalar(1), Scalar(0)) + , Radius(Scalar(0.5)) { } @@ -352,7 +386,7 @@ public: VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius) : Center(center) - , Axis(axis) + , Axis(vtkm::Normal(axis)) , Radius(radius) { } @@ -365,7 +399,7 @@ public: VTKM_CONT void SetAxis(const Vector& axis) { - this->Axis = axis; + this->Axis = vtkm::Normal(axis); this->Modified(); } @@ -402,6 +436,7 @@ private: class VTKM_ALWAYS_EXPORT Frustum final : public vtkm::ImplicitFunction { public: + /// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0. Frustum() = default; VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6]) @@ -465,7 +500,7 @@ public: const Vector& v2 = points[planes[i][2]]; this->Points[i] = v0; - this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0)); + this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2)); } this->Modified(); } @@ -502,27 +537,37 @@ public: } private: - Vector Points[6]; - Vector Normals[6]; + Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f }, + { 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } }; + Vector Normals[6] = { { -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } }; }; //============================================================================ /// \brief Implicit function for a plane +/// +/// A plane is defined by a point in the plane and a normal to the plane. +/// The normal does not have to be a unit vector. The implicit function will +/// still evaluate to 0 at the plane, but the values outside the plane +/// (and the gradient) will be scaled by the length of the normal vector. class VTKM_ALWAYS_EXPORT Plane final : public vtkm::ImplicitFunction { public: + /// Construct plane passing through origin and normal to z-axis. VTKM_EXEC_CONT Plane() : Origin(Scalar(0)) , Normal(Scalar(0), Scalar(0), Scalar(1)) { } + /// Construct a plane through the origin with the given normal. VTKM_EXEC_CONT explicit Plane(const Vector& normal) : Origin(Scalar(0)) , Normal(normal) { } + /// Construct a plane through the given point with the given normal. VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal) : Origin(origin) , Normal(normal) @@ -558,15 +603,23 @@ private: //============================================================================ /// \brief Implicit function for a sphere +/// +/// A sphere is defined by its center and a radius. +/// +/// The value of the sphere implicit function is the square of the distance +/// from the center biased by the radius (so the surface of the sphere is +/// at value 0). class VTKM_ALWAYS_EXPORT Sphere final : public vtkm::ImplicitFunction { public: + /// Construct sphere with center at (0,0,0) and radius = 0.5. VTKM_EXEC_CONT Sphere() - : Radius(Scalar(0.2)) + : Radius(Scalar(0.5)) , Center(Scalar(0)) { } + /// Construct a sphere with center at (0,0,0) and the given radius. VTKM_EXEC_CONT explicit Sphere(Scalar radius) : Radius(radius) , Center(Scalar(0)) diff --git a/vtkm/VecTraits.h b/vtkm/VecTraits.h index e4cf0d23f..77374f064 100644 --- a/vtkm/VecTraits.h +++ b/vtkm/VecTraits.h @@ -121,10 +121,16 @@ struct VTKM_NEVER_EXPORT VecTraits namespace detail { -template ::ComponentType> -std::true_type HasVecTraitsImpl(T*); +template +struct HasVecTraitsImpl +{ + template ::ComponentType> + static std::true_type Test(A*); -std::false_type HasVecTraitsImpl(...); + static std::false_type Test(...); + + using Type = decltype(Test(std::declval())); +}; } // namespace detail @@ -137,7 +143,7 @@ std::false_type HasVecTraitsImpl(...); /// VecTraits are not defined. /// template -using HasVecTraits = decltype(detail::HasVecTraitsImpl(std::declval())); +using HasVecTraits = typename detail::HasVecTraitsImpl::Type; // This partial specialization allows you to define a non-const version of // VecTraits and have it still work for const version. diff --git a/vtkm/VectorAnalysis.h b/vtkm/VectorAnalysis.h index ca144a31a..44e78e21b 100644 --- a/vtkm/VectorAnalysis.h +++ b/vtkm/VectorAnalysis.h @@ -189,6 +189,10 @@ VTKM_EXEC_CONT vtkm::Vec::Type, 3> C /// a triangle and the plane the triangle is on, returns a vector perpendicular /// to that triangle/plane. /// +/// Note that the returned vector might not be a unit vector. In fact, the length +/// is equal to twice the area of the triangle. If you want a unit vector, +/// send the result through the \c Normal function. +/// template VTKM_EXEC_CONT vtkm::Vec::Type, 3> TriangleNormal(const vtkm::Vec& a, const vtkm::Vec& b, const vtkm::Vec& c) diff --git a/vtkm/cont/ArrayHandleExtrudeCoords.h b/vtkm/cont/ArrayHandleExtrudeCoords.h index 7557fc87d..c6185144d 100644 --- a/vtkm/cont/ArrayHandleExtrudeCoords.h +++ b/vtkm/cont/ArrayHandleExtrudeCoords.h @@ -41,6 +41,8 @@ public: vtkm::Id GetNumberOfPointsPerPlane() const { return (this->GetStorage().GetLength() / 2); } vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().GetNumberOfPlanes(); } + bool GetUseCylindrical() const { return this->GetStorage().GetUseCylindrical(); } + const vtkm::cont::ArrayHandle& GetArray() const { return this->GetStorage().Array; } }; template @@ -94,6 +96,58 @@ vtkm::cont::ArrayHandleExtrudeCoords make_ArrayHandleExtrudeCoords( } } } +} // end namespace vtkm::cont + +//============================================================================= +// Specializations of serialization related classes +namespace vtkm +{ +namespace cont +{ + +template +struct SerializableTypeString> +{ + static VTKM_CONT const std::string& Get() + { + static std::string name = "AH_ExtrudeCoords<" + SerializableTypeString::Get() + ">"; + return name; + } +}; } +} // vtkm::cont + +namespace mangled_diy_namespace +{ + +template +struct Serialization> +{ +private: + using Type = vtkm::cont::ArrayHandleExtrudeCoords; + +public: + static VTKM_CONT void save(BinaryBuffer& bb, const Type& ah) + { + vtkmdiy::save(bb, ah.GetNumberOfPlanes()); + vtkmdiy::save(bb, ah.GetUseCylindrical()); + vtkmdiy::save(bb, ah.GetArray()); + } + + static VTKM_CONT void load(BinaryBuffer& bb, Type& ah) + { + vtkm::Int32 numberOfPlanes; + bool isCylindrical; + vtkm::cont::ArrayHandle array; + + vtkmdiy::load(bb, numberOfPlanes); + vtkmdiy::load(bb, isCylindrical); + vtkmdiy::load(bb, array); + + ah = vtkm::cont::make_ArrayHandleExtrudeCoords(array, numberOfPlanes, isCylindrical); + } +}; + +} // diy #endif diff --git a/vtkm/cont/ArrayHandleExtrudeField.h b/vtkm/cont/ArrayHandleExtrudeField.h index 1341f582c..72a309de5 100644 --- a/vtkm/cont/ArrayHandleExtrudeField.h +++ b/vtkm/cont/ArrayHandleExtrudeField.h @@ -40,8 +40,21 @@ public: } vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().GetNumberOfPlanes(); } + bool GetUseCylindrical() const { return this->GetStorage().GetUseCylindrical(); } + const vtkm::cont::ArrayHandle& GetArray() const { return this->GetStorage().Array; } }; +template +vtkm::cont::ArrayHandleExtrudeField make_ArrayHandleExtrudeField( + const vtkm::cont::ArrayHandle& array, + vtkm::Int32 numberOfPlanes, + bool cylindrical) +{ + using StorageType = vtkm::cont::internal::Storage; + auto storage = StorageType{ array, numberOfPlanes, cylindrical }; + return ArrayHandleExtrudeField(storage); +} + template vtkm::cont::ArrayHandleExtrudeField make_ArrayHandleExtrudeField( const T* array, @@ -77,4 +90,56 @@ vtkm::cont::ArrayHandleExtrudeField make_ArrayHandleExtrudeField( } } // vtkm::cont +//============================================================================= +// Specializations of serialization related classes +namespace vtkm +{ +namespace cont +{ + +template +struct SerializableTypeString> +{ + static VTKM_CONT const std::string& Get() + { + static std::string name = "AH_ExtrudeField<" + SerializableTypeString::Get() + ">"; + return name; + } +}; +} +} // vtkm::cont + +namespace mangled_diy_namespace +{ + +template +struct Serialization> +{ +private: + using Type = vtkm::cont::ArrayHandleExtrudeField; + +public: + static VTKM_CONT void save(BinaryBuffer& bb, const Type& ah) + { + vtkmdiy::save(bb, ah.GetNumberOfPlanes()); + vtkmdiy::save(bb, ah.GetUseCylindrical()); + vtkmdiy::save(bb, ah.GetArray()); + } + + static VTKM_CONT void load(BinaryBuffer& bb, Type& ah) + { + vtkm::Int32 numberOfPlanes; + bool isCylindrical; + vtkm::cont::ArrayHandle array; + + vtkmdiy::load(bb, numberOfPlanes); + vtkmdiy::load(bb, isCylindrical); + vtkmdiy::load(bb, array); + + ah = vtkm::cont::make_ArrayHandleExtrudeField(array, numberOfPlanes, isCylindrical); + } +}; + +} // diy + #endif diff --git a/vtkm/cont/ArrayHandleSOA.cxx b/vtkm/cont/ArrayHandleSOA.cxx new file mode 100644 index 000000000..b415ba27d --- /dev/null +++ b/vtkm/cont/ArrayHandleSOA.cxx @@ -0,0 +1,39 @@ +//============================================================================ +// 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. +//============================================================================ + +#define vtkm_cont_ArrayHandleSOA_cxx +#include + +namespace vtkm +{ +namespace cont +{ + +#define VTKM_ARRAYHANDLE_SOA_INSTANTIATE(Type) \ + template class VTKM_CONT_EXPORT ArrayHandle; \ + template class VTKM_CONT_EXPORT ArrayHandle, StorageTagSOA>; \ + template class VTKM_CONT_EXPORT ArrayHandle, StorageTagSOA>; \ + template class VTKM_CONT_EXPORT ArrayHandle, StorageTagSOA>; + +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(char) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int8) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt8) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int16) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt16) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int32) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt32) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int64) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt64) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Float32) +VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Float64) + +#undef VTKM_ARRAYHANDLE_SOA_INSTANTIATE +} +} // end vtkm::cont diff --git a/vtkm/cont/ArrayHandleSOA.h b/vtkm/cont/ArrayHandleSOA.h new file mode 100644 index 000000000..efcbea5cb --- /dev/null +++ b/vtkm/cont/ArrayHandleSOA.h @@ -0,0 +1,712 @@ +//============================================================================ +// 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_ArrayHandleSOA_h +#define vtk_m_cont_ArrayHandleSOA_h + +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +namespace vtkm +{ + +namespace internal +{ + +/// \brief An array portal that combines indices from multiple sources. +/// +/// This will only work if \c VecTraits is defined for the type. +/// +template +class ArrayPortalSOA +{ +public: + using ValueType = ValueType_; + +private: + using ComponentType = typename SourcePortalType::ValueType; + + VTKM_STATIC_ASSERT(vtkm::HasVecTraits::value); + using VTraits = vtkm::VecTraits; + VTKM_STATIC_ASSERT((std::is_same::value)); + static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; + + SourcePortalType Portals[NUM_COMPONENTS]; + vtkm::Id NumberOfValues; + +public: + VTKM_SUPPRESS_EXEC_WARNINGS + VTKM_EXEC_CONT explicit ArrayPortalSOA(vtkm::Id numValues = 0) + : NumberOfValues(numValues) + { + } + + VTKM_SUPPRESS_EXEC_WARNINGS + VTKM_EXEC_CONT void SetPortal(vtkm::IdComponent index, const SourcePortalType& portal) + { + this->Portals[index] = portal; + } + + VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; } + + template ::type, + typename = typename std::enable_if::type> + VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex) const + { + return this->Get(valueIndex, tao::seq::make_index_sequence()); + } + + template ::type, + typename = typename std::enable_if::type> + VTKM_EXEC_CONT void Set(vtkm::Id valueIndex, const ValueType& value) const + { + this->Set(valueIndex, value, tao::seq::make_index_sequence()); + } + +private: + template + VTKM_EXEC_CONT ComponentType GetComponent(vtkm::Id valueIndex) const + { + return this->Portals[I].Get(valueIndex); + } + + template + VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, tao::seq::index_sequence) const + { + return ValueType{ this->GetComponent(valueIndex)... }; + } + + template + VTKM_EXEC_CONT bool SetComponent(vtkm::Id valueIndex, const ValueType& value) const + { + this->Portals[I].Set(valueIndex, + VTraits::GetComponent(value, static_cast(I))); + return true; + } + + template + VTKM_EXEC_CONT void Set(vtkm::Id valueIndex, + const ValueType& value, + tao::seq::index_sequence) const + { + // Is there a better way to unpack an expression and execute them with no other side effects? + (void)std::initializer_list{ this->SetComponent(valueIndex, value)... }; + } +}; + +} // namespace internal + +namespace cont +{ + +struct VTKM_ALWAYS_EXPORT StorageTagSOA +{ +}; + +namespace internal +{ + +namespace detail +{ + +template +struct SOAPortalChooser; + +template +struct SOAPortalChooser +{ + using Type = vtkm::internal::ArrayPortalSOA; +}; + +template +struct SOAPortalChooser +{ + using Type = PortalType; +}; + +template +ReturnType MakeSOAPortal(std::array, + NUM_COMPONENTS> arrays, + vtkm::Id numValues, + const PortalMaker& portalMaker) +{ + ReturnType portal(numValues); + for (std::size_t componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + portal.SetPortal(static_cast(componentIndex), + portalMaker(arrays[componentIndex])); + VTKM_ASSERT(arrays[componentIndex].GetNumberOfValues() == numValues); + } + return portal; +} + +template +ReturnType MakeSOAPortal( + std::array, 1> arrays, + vtkm::Id vtkmNotUsed(numValues), + const PortalMaker& portalMaker) +{ + return portalMaker(arrays[0]); +} + +} // namespace detail + +template +struct ArrayHandleSOATraits +{ + using VTraits = vtkm::VecTraits; + using ComponentType = typename VTraits::ComponentType; + using BaseArrayType = vtkm::cont::ArrayHandle; + static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; + VTKM_STATIC_ASSERT_MSG(NUM_COMPONENTS > 0, + "ArrayHandleSOA requires a type with at least 1 component."); + + using IsTrueVec = std::integral_constant 1)>; + + using PortalControl = typename detail::SOAPortalChooser::Type; + using PortalConstControl = + typename detail::SOAPortalChooser::Type; + + template + using PortalExecution = typename detail::SOAPortalChooser< + ValueType, + typename BaseArrayType::template ExecutionTypes::Portal, + IsTrueVec>::Type; + template + using PortalConstExecution = typename detail::SOAPortalChooser< + ValueType, + typename BaseArrayType::template ExecutionTypes::PortalConst, + IsTrueVec>::Type; +}; + +template +class Storage +{ + using Traits = ArrayHandleSOATraits; + static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS; + using BaseArrayType = typename Traits::BaseArrayType; + + std::array Arrays; + + VTKM_CONT bool IsValidImpl(std::true_type) const + { + vtkm::Id size = this->Arrays[0].GetNumberOfValues(); + for (vtkm::IdComponent componentIndex = 1; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + if (this->GetArray(componentIndex).GetNumberOfValues() != size) + { + return false; + } + } + return true; + } + + VTKM_CONT constexpr bool IsValidImpl(std::false_type) const { return true; } + +public: + using ValueType = ValueType_; + using PortalType = typename Traits::PortalControl; + using PortalConstType = typename Traits::PortalConstControl; + + VTKM_CONT bool IsValid() const { return this->IsValidImpl(typename Traits::IsTrueVec{}); } + + Storage() = default; + + VTKM_CONT Storage(std::initializer_list&& arrays) + : Arrays{ std::move(arrays) } + { + VTKM_ASSERT(IsValid()); + } + + // For this constructor to work, all types have to be + // vtkm::cont::ArrayHandle + template + VTKM_CONT Storage(const BaseArrayType& array0, const ArrayTypes&... arrays) + : Arrays{ { array0, arrays... } } + { + VTKM_ASSERT(IsValid()); + } + + VTKM_CONT BaseArrayType& GetArray(vtkm::IdComponent index) + { + return this->Arrays[static_cast(index)]; + } + + VTKM_CONT const BaseArrayType& GetArray(vtkm::IdComponent index) const + { + return this->Arrays[static_cast(index)]; + } + + VTKM_CONT std::array& GetArrays() { return this->Arrays; } + + VTKM_CONT const std::array& GetArrays() const + { + return this->Arrays; + } + + VTKM_CONT void SetArray(vtkm::IdComponent index, const BaseArrayType& array) + { + this->Arrays[static_cast(index)] = array; + } + + VTKM_CONT vtkm::Id GetNumberOfValues() const + { + VTKM_ASSERT(IsValid()); + return this->GetArray(0).GetNumberOfValues(); + } + + VTKM_CONT PortalType GetPortal() + { + VTKM_ASSERT(this->IsValid()); + return detail::MakeSOAPortal( + this->Arrays, this->GetNumberOfValues(), [](BaseArrayType& array) { + return array.GetPortalControl(); + }); + } + + VTKM_CONT PortalConstType GetPortalConst() const + { + VTKM_ASSERT(this->IsValid()); + return detail::MakeSOAPortal( + this->Arrays, this->GetNumberOfValues(), [](const BaseArrayType& array) { + return array.GetPortalConstControl(); + }); + } + + VTKM_CONT void Allocate(vtkm::Id numValues) + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + this->GetArray(componentIndex).Allocate(numValues); + } + } + + VTKM_CONT void Shrink(vtkm::Id numValues) + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + this->GetArray(componentIndex).Shrink(numValues); + } + } + + VTKM_CONT void ReleaseResources() + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + this->GetArray(componentIndex).ReleaseResources(); + } + } +}; + +template +class ArrayTransfer +{ + VTKM_IS_DEVICE_ADAPTER_TAG(Device); + + using StorageType = vtkm::cont::internal::Storage; + + using Traits = ArrayHandleSOATraits; + using BaseArrayType = typename Traits::BaseArrayType; + static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS; + + StorageType* Storage; + +public: + using ValueType = ValueType_; + + using PortalControl = typename StorageType::PortalType; + using PortalConstControl = typename StorageType::PortalConstType; + + using PortalExecution = typename Traits::template PortalExecution; + using PortalConstExecution = typename Traits::template PortalConstExecution; + + VTKM_CONT ArrayTransfer(StorageType* storage) + : Storage(storage) + { + } + + VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); } + + VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const + { + return detail::MakeSOAPortal( + this->Storage->GetArrays(), this->GetNumberOfValues(), [](const BaseArrayType& array) { + return array.PrepareForInput(Device{}); + }); + } + + VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData)) const + { + return detail::MakeSOAPortal( + this->Storage->GetArrays(), this->GetNumberOfValues(), [](BaseArrayType& array) { + return array.PrepareForInPlace(Device{}); + }); + } + + VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numValues) const + { + return detail::MakeSOAPortal( + this->Storage->GetArrays(), numValues, [numValues](BaseArrayType& array) { + return array.PrepareForOutput(numValues, Device{}); + }); + } + + VTKM_CONT + void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const + { + // Implementation of this method should be unnecessary. The internal + // array handle should automatically retrieve the output data as + // necessary. + } + + VTKM_CONT void Shrink(vtkm::Id numValues) + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + this->Storage->GetArray(componentIndex).Shrink(numValues); + } + } + + VTKM_CONT void ReleaseResources() + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + this->Storage->GetArray(componentIndex).ReleaseResourcesExecution(); + } + } +}; + +} // namespace internal + +/// \brief An \c ArrayHandle that for Vecs stores each component in a separate physical array. +/// +/// \c ArrayHandleSOA behaves like a regular \c ArrayHandle (with a basic storage) except that +/// if you specify a \c ValueType of a \c Vec or a \c Vec-like, it will actually store each +/// component in a separate physical array. When data are retrieved from the array, they are +/// reconstructed into \c Vec objects as expected. +/// +/// The intention of this array type is to help cover the most common ways data is lain out in +/// memory. Typically, arrays of data are either an "array of structures" like the basic storage +/// where you have a single array of structures (like \c Vec) or a "structure of arrays" where +/// you have an array of a basic type (like \c float) for each component of the data being +/// represented. The\c ArrayHandleSOA makes it easy to cover this second case without creating +/// special types. +/// +/// \c ArrayHandleSOA can be constructed from a collection of \c ArrayHandle with basic storage. +/// This allows you to construct \c Vec arrays from components without deep copies. +/// +template +class ArrayHandleSOA : public ArrayHandle +{ + using Traits = vtkm::cont::internal::ArrayHandleSOATraits; + using ComponentType = typename Traits::ComponentType; + using BaseArrayType = typename Traits::BaseArrayType; + + using StorageType = vtkm::cont::internal::Storage; + +public: + VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleSOA, + (ArrayHandleSOA), + (ArrayHandle)); + + ArrayHandleSOA(std::initializer_list&& componentArrays) + : Superclass(StorageType(std::move(componentArrays))) + { + } + + ArrayHandleSOA(std::initializer_list>&& componentVectors) + { + VTKM_ASSERT(componentVectors.size() == Traits::NUM_COMPONENTS); + vtkm::IdComponent componentIndex = 0; + for (auto&& vectorIter = componentVectors.begin(); vectorIter != componentVectors.end(); + ++vectorIter) + { + // Note, std::vectors that come from std::initializer_list must be copied because the scope + // of the objects in the initializer list disappears. + this->SetArray(componentIndex, vtkm::cont::make_ArrayHandle(*vectorIter, vtkm::CopyFlag::On)); + ++componentIndex; + } + } + + // This only works if all the templated arguments are of type std::vector. + template + ArrayHandleSOA(vtkm::CopyFlag copy, + const std::vector& vector0, + const RemainingVectors&... componentVectors) + : Superclass(StorageType(vtkm::cont::make_ArrayHandle(vector0, copy), + vtkm::cont::make_ArrayHandle(componentVectors, copy)...)) + { + VTKM_STATIC_ASSERT(sizeof...(RemainingVectors) + 1 == Traits::NUM_COMPONENTS); + } + + // This only works if all the templated arguments are of type std::vector. + template + ArrayHandleSOA(const std::vector& vector0, + const RemainingVectors&... componentVectors) + : Superclass(StorageType(vtkm::cont::make_ArrayHandle(vector0), + vtkm::cont::make_ArrayHandle(componentVectors)...)) + { + VTKM_STATIC_ASSERT(sizeof...(RemainingVectors) + 1 == Traits::NUM_COMPONENTS); + } + + ArrayHandleSOA(std::initializer_list componentArrays, + vtkm::Id length, + vtkm::CopyFlag copy = vtkm::CopyFlag::Off) + { + VTKM_ASSERT(componentArrays.size() == Traits::NUM_COMPONENTS); + vtkm::IdComponent componentIndex = 0; + for (auto&& vectorIter = componentArrays.begin(); vectorIter != componentArrays.end(); + ++vectorIter) + { + this->SetArray(componentIndex, vtkm::cont::make_ArrayHandle(*vectorIter, length, copy)); + ++componentIndex; + } + } + + // This only works if all the templated arguments are of type std::vector. + template + ArrayHandleSOA(vtkm::Id length, + vtkm::CopyFlag copy, + const ComponentType* array0, + const RemainingArrays&... componentArrays) + : Superclass(StorageType(vtkm::cont::make_ArrayHandle(array0, length, copy), + vtkm::cont::make_ArrayHandle(componentArrays, length, copy)...)) + { + VTKM_STATIC_ASSERT(sizeof...(RemainingArrays) + 1 == Traits::NUM_COMPONENTS); + } + + // This only works if all the templated arguments are of type std::vector. + template + ArrayHandleSOA(vtkm::Id length, + const ComponentType* array0, + const RemainingArrays&... componentArrays) + : Superclass(StorageType(vtkm::cont::make_ArrayHandle(array0, length), + vtkm::cont::make_ArrayHandle(componentArrays, length)...)) + { + VTKM_STATIC_ASSERT(sizeof...(RemainingArrays) + 1 == Traits::NUM_COMPONENTS); + } + + VTKM_CONT BaseArrayType& GetArray(vtkm::IdComponent index) + { + return this->GetStorage().GetArray(index); + } + + VTKM_CONT const BaseArrayType& GetArray(vtkm::IdComponent index) const + { + return this->GetStorage().GetArray(index); + } + + VTKM_CONT void SetArray(vtkm::IdComponent index, const BaseArrayType& array) + { + this->GetStorage().SetArray(index, array); + } +}; + +template +VTKM_CONT ArrayHandleSOA make_ArrayHandleSOA( + std::initializer_list::ComponentType, + vtkm::cont::StorageTagBasic>>&& componentArrays) +{ + return ArrayHandleSOA(std::move(componentArrays)); +} + +template +VTKM_CONT + ArrayHandleSOA> + make_ArrayHandleSOA( + const vtkm::cont::ArrayHandle& componentArray0, + const RemainingArrays&... componentArrays) +{ + return { componentArray0, componentArrays... }; +} + +template +VTKM_CONT ArrayHandleSOA make_ArrayHandleSOA( + std::initializer_list::ComponentType>>&& + componentVectors) +{ + return ArrayHandleSOA(std::move(componentVectors)); +} + +// This only works if all the templated arguments are of type std::vector. +template +VTKM_CONT + ArrayHandleSOA> + make_ArrayHandleSOA(vtkm::CopyFlag copy, + const std::vector& vector0, + const RemainingVectors&... componentVectors) +{ + return ArrayHandleSOA< + vtkm::Vec>( + vector0, componentVectors..., copy); +} + +template +VTKM_CONT + ArrayHandleSOA> + make_ArrayHandleSOA(const std::vector& vector0, + const RemainingVectors&... componentVectors) +{ + return ArrayHandleSOA< + vtkm::Vec>( + vector0, componentVectors...); +} + +template +VTKM_CONT ArrayHandleSOA make_ArrayHandleSOA( + std::initializer_list::ComponentType*>&& + componentVectors, + vtkm::Id length, + vtkm::CopyFlag copy = vtkm::CopyFlag::Off) +{ + return ArrayHandleSOA(std::move(componentVectors), length, copy); +} + +// This only works if all the templated arguments are of type std::vector. +template +VTKM_CONT + ArrayHandleSOA> + make_ArrayHandleSOA(vtkm::Id length, + vtkm::CopyFlag copy, + const ComponentType* array0, + const RemainingArrays*... componentArrays) +{ + return ArrayHandleSOA< + vtkm::Vec>( + length, copy, array0, componentArrays...); +} + +template +VTKM_CONT + ArrayHandleSOA> + make_ArrayHandleSOA(vtkm::Id length, + const ComponentType* array0, + const RemainingArrays*... componentArrays) +{ + return ArrayHandleSOA< + vtkm::Vec>( + length, array0, componentArrays...); +} +} +} // namespace vtkm::cont + +//============================================================================= +// Specializations of serialization related classes + +namespace vtkm +{ +namespace cont +{ + +template +struct SerializableTypeString> +{ + static VTKM_CONT const std::string& Get() + { + static std::string name = "AH_SOA<" + SerializableTypeString::Get() + ">"; + return name; + } +}; + +template +struct SerializableTypeString> + : SerializableTypeString> +{ +}; +} +} // namespace vtkm::cont + +namespace mangled_diy_namespace +{ + +template +struct Serialization> +{ + using BaseType = vtkm::cont::ArrayHandle; + using Traits = vtkm::cont::internal::ArrayHandleSOATraits; + static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS; + + static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj) + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + vtkmdiy::save(bb, obj.GetStorage().GetArray(componentIndex)); + } + } + + static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj) + { + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + typename Traits::BaseArrayType componentArray; + vtkmdiy::load(bb, componentArray); + obj.GetStorage().SetArray(componentIndex, componentArray); + } + } +}; + +template +struct Serialization> + : Serialization> +{ +}; + +} // namespace mangled_diy_namespace + +//============================================================================= +// Precompiled instances + +#ifndef vtkm_cont_ArrayHandleSOA_cxx + +namespace vtkm +{ +namespace cont +{ + +#define VTKM_ARRAYHANDLE_SOA_EXPORT(Type) \ + extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle; \ + extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle, StorageTagSOA>; \ + extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle, StorageTagSOA>; \ + extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle, StorageTagSOA>; + +VTKM_ARRAYHANDLE_SOA_EXPORT(char) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int8) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt8) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int16) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt16) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int32) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt32) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int64) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt64) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Float32) +VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Float64) + +#undef VTKM_ARRAYHANDLE_SOA_EXPORT +} +} // namespace vtkm::cont + +#endif // !vtkm_cont_ArrayHandleSOA_cxx + +#endif //vtk_m_cont_ArrayHandleSOA_h diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index 0c2385912..f9da479c9 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -30,6 +30,7 @@ set(headers ArrayHandleMultiplexer.h ArrayHandlePermutation.h ArrayHandleReverse.h + ArrayHandleSOA.h ArrayHandleStreaming.h ArrayHandleSwizzle.h ArrayHandleTransform.h @@ -128,6 +129,7 @@ set(template_sources set(sources ArrayHandle.cxx + ArrayHandleSOA.cxx ColorTablePresets.cxx DeviceAdapterTag.cxx EnvironmentTracker.cxx diff --git a/vtkm/cont/CellSetExtrude.h b/vtkm/cont/CellSetExtrude.h index 87567571e..4d2ae47a1 100644 --- a/vtkm/cont/CellSetExtrude.h +++ b/vtkm/cont/CellSetExtrude.h @@ -62,6 +62,16 @@ public: void PrintSummary(std::ostream& out) const override; void ReleaseResourcesExecution() override; + const vtkm::cont::ArrayHandle& GetConnectivityArray() const + { + return this->Connectivity; + } + + vtkm::Int32 GetNumberOfPointsPerPlane() const { return this->NumberOfPointsPerPlane; } + + const vtkm::cont::ArrayHandle& GetNextNodeArray() const { return this->NextNode; } + + bool GetIsPeriodic() const { return this->IsPeriodic; } template using ConnectivityP2C = vtkm::exec::ConnectivityExtrude; @@ -141,5 +151,68 @@ CellSetExtrude make_CellSetExtrude(const std::vector& conn, } } // vtkm::cont + +//============================================================================= +// Specializations of serialization related classes +namespace vtkm +{ +namespace cont +{ + +template <> +struct SerializableTypeString +{ + static VTKM_CONT const std::string& Get() + { + static std::string name = "CS_Extrude"; + return name; + } +}; +} +} // vtkm::cont + +namespace mangled_diy_namespace +{ + +template <> +struct Serialization +{ +private: + using Type = vtkm::cont::CellSetExtrude; + +public: + static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs) + { + vtkmdiy::save(bb, cs.GetName()); + vtkmdiy::save(bb, cs.GetNumberOfPointsPerPlane()); + vtkmdiy::save(bb, cs.GetNumberOfPlanes()); + vtkmdiy::save(bb, cs.GetIsPeriodic()); + vtkmdiy::save(bb, cs.GetConnectivityArray()); + vtkmdiy::save(bb, cs.GetNextNodeArray()); + } + + static VTKM_CONT void load(BinaryBuffer& bb, Type& cs) + { + std::string name; + vtkm::Int32 numberOfPointsPerPlane; + vtkm::Int32 numberOfPlanes; + bool isPeriodic; + vtkm::cont::ArrayHandle conn; + vtkm::cont::ArrayHandle nextNode; + + vtkmdiy::load(bb, name); + vtkmdiy::load(bb, numberOfPointsPerPlane); + vtkmdiy::load(bb, numberOfPlanes); + vtkmdiy::load(bb, isPeriodic); + vtkmdiy::load(bb, conn); + vtkmdiy::load(bb, nextNode); + + cs = Type{ conn, numberOfPointsPerPlane, numberOfPlanes, nextNode, isPeriodic, name }; + } +}; + +} // diy + #include -#endif + +#endif // vtk_m_cont_CellSetExtrude.h diff --git a/vtkm/cont/StorageExtrude.h b/vtkm/cont/StorageExtrude.h index 156f0386e..3ce84e2e5 100644 --- a/vtkm/cont/StorageExtrude.h +++ b/vtkm/cont/StorageExtrude.h @@ -69,11 +69,6 @@ struct VTKM_ALWAYS_EXPORT ArrayPortalExtrudePlane return result; } - - VTKM_SUPPRESS_EXEC_WARNINGS - VTKM_EXEC_CONT - void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {} - PortalType Portal; vtkm::Int32 NumberOfPlanes; }; @@ -285,10 +280,6 @@ struct VTKM_ALWAYS_EXPORT ArrayPortalExtrude VTKM_EXEC_CONT vtkm::Vec GetWedge(const IndicesExtrude& index) const; - VTKM_SUPPRESS_EXEC_WARNINGS - VTKM_EXEC_CONT - void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {} - PortalType Portal; vtkm::Int32 NumberOfValues; vtkm::Int32 NumberOfPlanes; diff --git a/vtkm/cont/testing/TestingFancyArrayHandles.h b/vtkm/cont/testing/TestingFancyArrayHandles.h index eeb8de8f4..4b95b6256 100644 --- a/vtkm/cont/testing/TestingFancyArrayHandles.h +++ b/vtkm/cont/testing/TestingFancyArrayHandles.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -244,6 +245,184 @@ public: private: #endif + struct TestArrayPortalSOA + { + template + VTKM_CONT void operator()(ComponentType) const + { + constexpr vtkm::IdComponent NUM_COMPONENTS = 4; + using ValueType = vtkm::Vec; + using ComponentArrayType = vtkm::cont::ArrayHandle; + using SOAPortalType = + vtkm::internal::ArrayPortalSOA; + + std::cout << "Test SOA portal reflects data in component portals." << std::endl; + SOAPortalType soaPortalIn(ARRAY_SIZE); + + std::array, NUM_COMPONENTS> implArrays; + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + vtkm::cont::ArrayHandle array; + array.Allocate(ARRAY_SIZE); + auto portal = array.GetPortalControl(); + for (vtkm::IdComponent valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) + { + portal.Set(valueIndex, TestValue(valueIndex, ValueType{})[componentIndex]); + } + + soaPortalIn.SetPortal(componentIndex, portal); + + implArrays[static_cast(componentIndex)] = array; + } + + VTKM_TEST_ASSERT(soaPortalIn.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaPortalIn); + + std::cout << "Test data set in SOA portal gets set in component portals." << std::endl; + SOAPortalType soaPortalOut(ARRAY_SIZE); + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + vtkm::cont::ArrayHandle array; + array.Allocate(ARRAY_SIZE); + auto portal = array.GetPortalControl(); + soaPortalOut.SetPortal(componentIndex, portal); + + implArrays[static_cast(componentIndex)] = array; + } + + SetPortal(soaPortalOut); + + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + auto portal = implArrays[static_cast(componentIndex)].GetPortalConstControl(); + for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) + { + ComponentType x = TestValue(valueIndex, ValueType{})[componentIndex]; + VTKM_TEST_ASSERT(test_equal(x, portal.Get(valueIndex))); + } + } + } + }; + + struct TestSOAAsInput + { + template + VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const + { + using VTraits = vtkm::VecTraits; + using ComponentType = typename VTraits::ComponentType; + constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; + + { + vtkm::cont::ArrayHandleSOA soaArray; + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; + ++componentIndex) + { + vtkm::cont::ArrayHandle componentArray; + componentArray.Allocate(ARRAY_SIZE); + auto componentPortal = componentArray.GetPortalControl(); + for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) + { + componentPortal.Set( + valueIndex, + VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex)); + } + soaArray.SetArray(componentIndex, componentArray); + } + + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + VTKM_TEST_ASSERT(soaArray.GetPortalConstControl().GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + + vtkm::cont::ArrayHandle basicArray; + vtkm::cont::ArrayCopy(soaArray, basicArray); + VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(basicArray.GetPortalConstControl()); + } + + { + // Check constructors + using Vec3 = vtkm::Vec; + std::vector vector0; + std::vector vector1; + std::vector vector2; + for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) + { + Vec3 value = TestValue(valueIndex, Vec3{}); + vector0.push_back(value[0]); + vector1.push_back(value[1]); + vector2.push_back(value[2]); + } + + { + vtkm::cont::ArrayHandleSOA soaArray = { vector0, vector1, vector2 }; + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + } + + { + vtkm::cont::ArrayHandleSOA soaArray = + vtkm::cont::make_ArrayHandleSOA({ vector0, vector1, vector2 }); + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + } + + { + vtkm::cont::ArrayHandleSOA soaArray = + vtkm::cont::make_ArrayHandleSOA(vector0, vector1, vector2); + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + } + + { + vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA( + { &vector0.front(), &vector1.front(), &vector2.front() }, ARRAY_SIZE); + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + } + + { + vtkm::cont::ArrayHandleSOA soaArray = vtkm::cont::make_ArrayHandleSOA( + ARRAY_SIZE, &vector0.front(), &vector1.front(), &vector2.front()); + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + CheckPortal(soaArray.GetPortalConstControl()); + } + } + } + }; + + struct TestSOAAsOutput + { + template + VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const + { + using VTraits = vtkm::VecTraits; + using ComponentType = typename VTraits::ComponentType; + constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS; + + vtkm::cont::ArrayHandle basicArray; + basicArray.Allocate(ARRAY_SIZE); + SetPortal(basicArray.GetPortalControl()); + + vtkm::cont::ArrayHandleSOA soaArray; + vtkm::cont::ArrayCopy(basicArray, soaArray); + + VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE); + for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex) + { + vtkm::cont::ArrayHandle componentArray = soaArray.GetArray(componentIndex); + auto componentPortal = componentArray.GetPortalConstControl(); + for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex) + { + ComponentType expected = + VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex); + ComponentType got = componentPortal.Get(valueIndex); + VTKM_TEST_ASSERT(test_equal(expected, got)); + } + } + } + }; + struct TestCompositeAsInput { template @@ -1260,6 +1439,21 @@ private: { std::cout << "Doing FancyArrayHandle tests" << std::endl; + std::cout << "-------------------------------------------" << std::endl; + std::cout << "Testing ArrayPortalSOA" << std::endl; + vtkm::testing::Testing::TryTypes( + TestingFancyArrayHandles::TestArrayPortalSOA(), ScalarTypesToTest()); + + std::cout << "-------------------------------------------" << std::endl; + std::cout << "Testing ArrayHandleSOA as Input" << std::endl; + vtkm::testing::Testing::TryTypes(TestingFancyArrayHandles::TestSOAAsInput(), + HandleTypesToTest()); + + std::cout << "-------------------------------------------" << std::endl; + std::cout << "Testing ArrayHandleSOA as Output" << std::endl; + vtkm::testing::Testing::TryTypes( + TestingFancyArrayHandles::TestSOAAsOutput(), HandleTypesToTest()); + std::cout << "-------------------------------------------" << std::endl; std::cout << "Testing ArrayHandleCompositeVector as Input" << std::endl; vtkm::testing::Testing::TryTypes( diff --git a/vtkm/cont/testing/TestingImplicitFunction.h b/vtkm/cont/testing/TestingImplicitFunction.h index 440ed903d..0f21dbac6 100644 --- a/vtkm/cont/testing/TestingImplicitFunction.h +++ b/vtkm/cont/testing/TestingImplicitFunction.h @@ -99,7 +99,7 @@ bool TestArrayEqual(const vtkm::cont::ArrayHandle& result, } else { - std::cout << "result: " << portal.Get(0); + std::cout << "result: " << portal.Get(0); for (vtkm::Id i = 1; i < count; ++i) { std::cout << ", " << portal.Get(i); @@ -138,39 +138,72 @@ public: } private: + template + void Try(vtkm::cont::ImplicitFunctionHandle& function, + const std::array& expectedValues, + const std::array& expectedGradients, + DeviceAdapter device) + { + vtkm::cont::ArrayHandle values; + vtkm::cont::ArrayHandle> gradients; + implicit_function_detail::EvaluateOnCoordinates( + this->Input.GetCoordinateSystem(0), function, values, gradients, device); + + VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expectedValues), + "Result does not match expected values"); + VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), + "Result does not match expected gradients values"); + } + template void TestBox(DeviceAdapter device) { std::cout << "Testing vtkm::Box on " << vtkm::cont::DeviceAdapterTraits::GetName() << "\n"; - vtkm::cont::ArrayHandle values; - vtkm::cont::ArrayHandle> gradients; - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), - vtkm::cont::make_ImplicitFunctionHandle( - vtkm::Box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f })), - values, - gradients, - device); + std::cout << " default box" << std::endl; + vtkm::Box box; + vtkm::cont::ImplicitFunctionHandle boxHandle(&box, false); + this->Try(boxHandle, + { { -0.5f, 0.5f, 0.707107f, 0.5f, 0.5f, 0.707107f, 0.866025f, 0.707107f } }, + { { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.707107f, 0.0f, 0.707107f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 1.0f, 0.0f }, + vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f }, + vtkm::Vec3f{ 0.57735f, 0.57735f, 0.57735f }, + vtkm::Vec3f{ 0.0f, 0.707107f, 0.707107f } } }, + device); - std::array expected = { - { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } - }; - std::array, 8> expectedGradients = { - { { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f } } - }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + std::cout << " Specified min/max box" << std::endl; + box.SetMinPoint({ 0.0f, -0.5f, -0.5f }); + box.SetMaxPoint({ 1.5f, 1.5f, 0.5f }); + this->Try(boxHandle, + { { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } }, + { { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } }, + device); + + std::cout << " Specified bounds box" << std::endl; + box.SetBounds({ vtkm::Range(0.0, 1.5), vtkm::Range(-0.5, 1.5), vtkm::Range(-0.5, 0.5) }); + this->Try(boxHandle, + { { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } }, + { { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } }, + device); } template @@ -179,37 +212,52 @@ private: std::cout << "Testing vtkm::Cylinder on " << vtkm::cont::DeviceAdapterTraits::GetName() << "\n"; + std::cout << " Default cylinder" << std::endl; vtkm::Cylinder cylinder; + vtkm::cont::ImplicitFunctionHandle cylinderHandle(&cylinder, false); + this->Try(cylinderHandle, + { { -0.25f, 0.75f, 1.75f, 0.75f, -0.25f, 0.75f, 1.75f, 0.75f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } } }, + device); + + std::cout << " Translated, scaled cylinder" << std::endl; cylinder.SetCenter({ 0.0f, 0.0f, 1.0f }); cylinder.SetAxis({ 0.0f, 1.0f, 0.0f }); cylinder.SetRadius(1.0f); + this->Try(cylinderHandle, + { { 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 0.0f } } }, + device); - vtkm::cont::ArrayHandle values; - vtkm::cont::ArrayHandle> gradients; - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), - vtkm::cont::ImplicitFunctionHandle(&cylinder, false), - values, - gradients, - device); - - std::array expected = { - { 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f } - }; - std::array, 8> expectedGradients = { - { { 0.0f, 0.0f, -2.0f }, - { 2.0f, 0.0f, -2.0f }, - { 2.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, -2.0f }, - { 2.0f, 0.0f, -2.0f }, - { 2.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f } } - }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + std::cout << " Non-unit axis" << std::endl; + cylinder.SetCenter({ 0.0f, 0.0f, 0.0f }); + cylinder.SetAxis({ 1.0f, 1.0f, 0.0f }); + cylinder.SetRadius(1.0f); + this->Try(cylinderHandle, + { { -1.0f, -0.5f, 0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.5f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, -1.0f, 0.0f }, + vtkm::Vec3f{ 1.0f, -1.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ -1.0f, 1.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ -1.0f, 1.0f, 2.0f } } }, + device); } template @@ -218,45 +266,51 @@ private: std::cout << "Testing vtkm::Frustum on " << vtkm::cont::DeviceAdapterTraits::GetName() << "\n"; - vtkm::Vec3f points[8] = { - { 0.0f, 0.0f, 0.0f }, // 0 - { 1.0f, 0.0f, 0.0f }, // 1 - { 1.0f, 0.0f, 1.0f }, // 2 - { 0.0f, 0.0f, 1.0f }, // 3 - { 0.5f, 1.5f, 0.5f }, // 4 - { 1.5f, 1.5f, 0.5f }, // 5 - { 1.5f, 1.5f, 1.5f }, // 6 - { 0.5f, 1.5f, 1.5f } // 7 + std::cout << " With corner points" << std::endl; + vtkm::Vec3f cornerPoints[8] = { + { -0.5f, 0.0f, -0.5f }, // 0 + { -0.5f, 0.0f, 0.5f }, // 1 + { 0.5f, 0.0f, 0.5f }, // 2 + { 0.5f, 0.0f, -0.5f }, // 3 + { -0.5f, 1.0f, -0.5f }, // 4 + { -0.5f, 1.0f, 0.5f }, // 5 + { 1.5f, 1.0f, 0.5f }, // 6 + { 1.5f, 1.0f, -0.5f } // 7 }; - vtkm::Frustum frustum; - frustum.CreateFromPoints(points); + vtkm::cont::ImplicitFunctionHandle frustumHandle = + vtkm::cont::make_ImplicitFunctionHandle(cornerPoints); + vtkm::Frustum* frustum = static_cast(frustumHandle.Get()); + this->Try(frustumHandle, + { { 0.0f, 0.353553f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f } }, + { { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f }, + vtkm::Vec3f{ 0.707107f, -0.707107f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 1.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 1.0f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } }, + device); - vtkm::cont::ArrayHandle values; - vtkm::cont::ArrayHandle> gradients; - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), - vtkm::cont::make_ImplicitFunctionHandle(frustum), - values, - gradients, - device); - - std::array expected = { - { 0.0f, 0.0f, 0.0f, 0.0f, 0.316228f, 0.316228f, -0.316228f, 0.316228f } - }; - std::array, 8> expectedGradients = { - { { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, 0.316228f, -0.948683f }, - { 0.0f, 0.316228f, -0.948683f }, - { 0.948683f, -0.316228f, 0.0f }, - { -0.948683f, 0.316228f, 0.0f } } - }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + std::cout << " With 6 planes" << std::endl; + vtkm::Vec3f planePoints[6] = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f }, + { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, + { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } }; + vtkm::Vec3f planeNormals[6] = { { 0.0f, -1.0f, 0.0f }, { 0.707107f, 0.707107f, 0.0f }, + { -1.0f, 0.0f, 0.0f }, { 0.707107f, -0.707107f, 0.0f }, + { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } }; + frustum->SetPlanes(planePoints, planeNormals); + this->Try(frustumHandle, + { { 0.0f, 0.353553f, 0.5f, 0.5f, -0.5f, 0.0f, 0.5f, 0.5f } }, + { { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f }, + vtkm::Vec3f{ 0.707107f, -0.707107f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } }, + device); } template @@ -265,48 +319,65 @@ private: std::cout << "Testing vtkm::Plane on " << vtkm::cont::DeviceAdapterTraits::GetName() << "\n"; - auto planeHandle = vtkm::cont::make_ImplicitFunctionHandle( - vtkm::make_Vec(0.5f, 0.5f, 0.5f), vtkm::make_Vec(1.0f, 0.0f, 1.0f)); - auto plane = static_cast(planeHandle.Get()); + std::cout << " Default plane" << std::endl; + vtkm::cont::ImplicitFunctionHandle planeHandle = + vtkm::cont::make_ImplicitFunctionHandle(vtkm::Plane()); + vtkm::Plane* plane = static_cast(planeHandle.Get()); + this->Try(planeHandle, + { { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } }, + device); - vtkm::cont::ArrayHandle values; - vtkm::cont::ArrayHandle> gradients; - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device); - std::array expected = { - { -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } - }; - std::array, 8> expectedGradients = { - { { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f } } - }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + std::cout << " Normal of length 2" << std::endl; + plane->SetOrigin({ 1.0f, 1.0f, 1.0f }); + plane->SetNormal({ 0.0f, 0.0f, 2.0f }); + this->Try(planeHandle, + { { -2.0f, -2.0f, 0.0f, 0.0f, -2.0f, -2.0f, 0.0f, 0.0f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } } }, + device); + std::cout << " Oblique plane" << std::endl; + plane->SetOrigin({ 0.5f, 0.5f, 0.5f }); + plane->SetNormal({ 1.0f, 0.0f, 1.0f }); + this->Try(planeHandle, + { { -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } }, + { { vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, + vtkm::Vec3f{ 1.0f, 0.0f, 1.0f } } }, + device); + + std::cout << " Another oblique plane" << std::endl; plane->SetNormal({ -1.0f, 0.0f, -1.0f }); - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device); - expected = { { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } }; - expectedGradients = { { { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f }, - { -1.0f, 0.0f, -1.0f } } }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + this->Try(planeHandle, + { { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } }, + { { vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f }, + vtkm::Vec3f{ -1.0f, 0.0f, -1.0f } } }, + device); } template @@ -315,32 +386,35 @@ private: std::cout << "Testing vtkm::Sphere on " << vtkm::cont::DeviceAdapterTraits::GetName() << "\n"; - vtkm::cont::ArrayHandle values; - vtkm::cont::ArrayHandle> gradients; - implicit_function_detail::EvaluateOnCoordinates( - this->Input.GetCoordinateSystem(0), - vtkm::cont::make_ImplicitFunctionHandle(vtkm::make_Vec(0.0f, 0.0f, 0.0f), 1.0f), - values, - gradients, - device); + std::cout << " Default sphere" << std::endl; + vtkm::Sphere sphere; + vtkm::cont::ImplicitFunctionHandle sphereHandle(&sphere, false); + this->Try(sphereHandle, + { { -0.25f, 0.75f, 1.75f, 0.75f, 0.75f, 1.75f, 2.75f, 1.75f } }, + { { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 2.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 2.0f, 0.0f }, + vtkm::Vec3f{ 2.0f, 2.0f, 2.0f }, + vtkm::Vec3f{ 0.0f, 2.0f, 2.0f } } }, + device); - std::array expected = { - { -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f } - }; - std::array, 8> expectedGradients = { - { { 0.0f, 0.0f, 0.0f }, - { 2.0f, 0.0f, 0.0f }, - { 2.0f, 0.0f, 2.0f }, - { 0.0f, 0.0f, 2.0f }, - { 0.0f, 2.0f, 0.0f }, - { 2.0f, 2.0f, 0.0f }, - { 2.0f, 2.0f, 2.0f }, - { 0.0f, 2.0f, 2.0f } } - }; - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected), - "Result does not match expected values"); - VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients), - "Result does not match expected gradients values"); + std::cout << " Shifted and scaled sphere" << std::endl; + sphere.SetCenter({ 1.0f, 1.0f, 1.0f }); + sphere.SetRadius(1.0f); + this->Try(sphereHandle, + { { 2.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f } }, + { { vtkm::Vec3f{ -2.0f, -2.0f, -2.0f }, + vtkm::Vec3f{ 0.0f, -2.0f, -2.0f }, + vtkm::Vec3f{ 0.0f, -2.0f, 0.0f }, + vtkm::Vec3f{ -2.0f, -2.0f, 0.0f }, + vtkm::Vec3f{ -2.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, -2.0f }, + vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }, + vtkm::Vec3f{ -2.0f, 0.0f, 0.0f } } }, + device); } vtkm::cont::DataSet Input; diff --git a/vtkm/cont/testing/UnitTestSerializationArrayHandle.cxx b/vtkm/cont/testing/UnitTestSerializationArrayHandle.cxx index 55763fc1e..0a0965434 100644 --- a/vtkm/cont/testing/UnitTestSerializationArrayHandle.cxx +++ b/vtkm/cont/testing/UnitTestSerializationArrayHandle.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,18 @@ struct TestArrayHandleBasic } }; +struct TestArrayHandleSOA +{ + template + void operator()(T) const + { + vtkm::cont::ArrayHandleSOA array; + vtkm::cont::ArrayCopy(RandomArrayHandle::Make(ArraySize), array); + RunTest(array); + RunTest(MakeTestVariantArrayHandle(array)); + } +}; + struct TestArrayHandleCartesianProduct { template @@ -451,6 +464,9 @@ void TestArrayHandleSerialization() std::cout << "Testing ArrayHandleBasic\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleBasic(), TestTypesList()); + std::cout << "Testing ArrayHandleSOA\n"; + vtkm::testing::Testing::TryTypes(TestArrayHandleSOA(), TestTypesList()); + std::cout << "Testing ArrayHandleCartesianProduct\n"; vtkm::testing::Testing::TryTypes(TestArrayHandleCartesianProduct(), TestTypesList()); diff --git a/vtkm/exec/CellDerivative.h b/vtkm/exec/CellDerivative.h index cdc52b1a7..ae7faaa48 100644 --- a/vtkm/exec/CellDerivative.h +++ b/vtkm/exec/CellDerivative.h @@ -1165,6 +1165,27 @@ VTKM_EXEC vtkm::Vec CellDerivative( vtkm::Vec wpoints; wCoords.CopyInto(wpoints); + if (pcoords[2] > static_cast(0.999)) + { + // If we are at the apex of the pyramid we need to do something special. + // As we approach the apex, the derivatives of the parametric shape + // functions in x and y go to 0 while the inverse of the Jacobian + // also goes to 0. This results in 0/0 but using l'Hopital's rule + // we could actually compute the value of the limit, if we had a + // functional expression to compute the gradient. We're on a computer + // so we don't but we can cheat and do a linear extrapolation of the + // derivatives which really ends up as the same thing. + using PCoordType = vtkm::Vec; + using ReturnType = vtkm::Vec; + PCoordType pcoords1(0.5f, 0.5f, (2 * 0.998f) - pcoords[2]); + ReturnType derivative1 = + detail::CellDerivativeFor3DCell(field, wpoints, pcoords1, vtkm::CellShapeTagPyramid{}); + PCoordType pcoords2(0.5f, 0.5f, 0.998f); + ReturnType derivative2 = + detail::CellDerivativeFor3DCell(field, wpoints, pcoords2, vtkm::CellShapeTagPyramid{}); + return (ValueType(2) * derivative2) - derivative1; + } + return detail::CellDerivativeFor3DCell(field, wpoints, pcoords, vtkm::CellShapeTagPyramid()); } } diff --git a/vtkm/filter/CMakeLists.txt b/vtkm/filter/CMakeLists.txt index a39a01700..d1a54fdb4 100644 --- a/vtkm/filter/CMakeLists.txt +++ b/vtkm/filter/CMakeLists.txt @@ -16,6 +16,7 @@ set(headers ClipWithField.h ClipWithImplicitFunction.h ComputeMoments.h + Contour.h ContourTreeUniform.h ContourTreeUniformAugmented.h CoordinateSystemTransform.h @@ -43,7 +44,6 @@ set(headers ImageConnectivity.h Lagrangian.h LagrangianStructures.h - MarchingCubes.h Mask.h MaskPoints.h MeshQuality.h @@ -86,6 +86,7 @@ set(header_template_sources ClipWithField.hxx ClipWithImplicitFunction.hxx ComputeMoments.hxx + Contour.hxx ContourTreeUniform.hxx ContourTreeUniformAugmented.hxx CoordinateSystemTransform.hxx @@ -109,7 +110,6 @@ set(header_template_sources ImageConnectivity.hxx Lagrangian.hxx LagrangianStructures.hxx - MarchingCubes.hxx Mask.hxx MaskPoints.hxx MeshQuality.hxx diff --git a/vtkm/filter/MarchingCubes.h b/vtkm/filter/Contour.h similarity index 93% rename from vtkm/filter/MarchingCubes.h rename to vtkm/filter/Contour.h index efc8db5de..75c144925 100644 --- a/vtkm/filter/MarchingCubes.h +++ b/vtkm/filter/Contour.h @@ -8,11 +8,11 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_filter_MarchingCubes_h -#define vtk_m_filter_MarchingCubes_h +#ifndef vtk_m_filter_Contour_h +#define vtk_m_filter_Contour_h #include -#include +#include namespace vtkm { @@ -25,13 +25,13 @@ namespace filter /// Multiple contour values must be specified to generate the isosurfaces. /// @warning /// This filter is currently only supports 3D volumes. -class MarchingCubes : public vtkm::filter::FilterDataSetWithField +class Contour : public vtkm::filter::FilterDataSetWithField { public: using SupportedTypes = vtkm::ListTagBase; VTKM_CONT - MarchingCubes(); + Contour(); VTKM_CONT void SetNumberOfIsoValues(vtkm::Id num); @@ -125,11 +125,11 @@ private: bool ComputeFastNormalsForUnstructured; std::string NormalArrayName; std::string InterpolationEdgeIdsArrayName; - vtkm::worklet::MarchingCubes Worklet; + vtkm::worklet::Contour Worklet; }; } } // namespace vtkm::filter -#include +#include -#endif // vtk_m_filter_MarchingCubes_h +#endif // vtk_m_filter_Contour_h diff --git a/vtkm/filter/MarchingCubes.hxx b/vtkm/filter/Contour.hxx similarity index 89% rename from vtkm/filter/MarchingCubes.hxx rename to vtkm/filter/Contour.hxx index 996427668..ad2425a9d 100644 --- a/vtkm/filter/MarchingCubes.hxx +++ b/vtkm/filter/Contour.hxx @@ -38,8 +38,8 @@ bool IsCellSetStructured(const vtkm::cont::DynamicCellSetBase& cell } // anonymous namespace //----------------------------------------------------------------------------- -inline VTKM_CONT MarchingCubes::MarchingCubes() - : vtkm::filter::FilterDataSetWithField() +inline VTKM_CONT Contour::Contour() + : vtkm::filter::FilterDataSetWithField() , IsoValues() , GenerateNormals(false) , AddInterpolationEdgeIds(false) @@ -53,7 +53,7 @@ inline VTKM_CONT MarchingCubes::MarchingCubes() } //----------------------------------------------------------------------------- -inline void MarchingCubes::SetNumberOfIsoValues(vtkm::Id num) +inline void Contour::SetNumberOfIsoValues(vtkm::Id num) { if (num >= 0) { @@ -62,13 +62,13 @@ inline void MarchingCubes::SetNumberOfIsoValues(vtkm::Id num) } //----------------------------------------------------------------------------- -inline vtkm::Id MarchingCubes::GetNumberOfIsoValues() const +inline vtkm::Id Contour::GetNumberOfIsoValues() const { return static_cast(this->IsoValues.size()); } //----------------------------------------------------------------------------- -inline void MarchingCubes::SetIsoValue(vtkm::Id index, vtkm::Float64 v) +inline void Contour::SetIsoValue(vtkm::Id index, vtkm::Float64 v) { std::size_t i = static_cast(index); if (i >= this->IsoValues.size()) @@ -79,20 +79,20 @@ inline void MarchingCubes::SetIsoValue(vtkm::Id index, vtkm::Float64 v) } //----------------------------------------------------------------------------- -inline void MarchingCubes::SetIsoValues(const std::vector& values) +inline void Contour::SetIsoValues(const std::vector& values) { this->IsoValues = values; } //----------------------------------------------------------------------------- -inline vtkm::Float64 MarchingCubes::GetIsoValue(vtkm::Id index) const +inline vtkm::Float64 Contour::GetIsoValue(vtkm::Id index) const { return this->IsoValues[static_cast(index)]; } //----------------------------------------------------------------------------- template -inline VTKM_CONT vtkm::cont::DataSet MarchingCubes::DoExecute( +inline VTKM_CONT vtkm::cont::DataSet Contour::DoExecute( const vtkm::cont::DataSet& input, const vtkm::cont::ArrayHandle& field, const vtkm::filter::FieldMetadata& fieldMeta, @@ -206,11 +206,10 @@ inline VTKM_CONT vtkm::cont::DataSet MarchingCubes::DoExecute( //----------------------------------------------------------------------------- template -inline VTKM_CONT bool MarchingCubes::DoMapField( - vtkm::cont::DataSet& result, - const vtkm::cont::ArrayHandle& input, - const vtkm::filter::FieldMetadata& fieldMeta, - const vtkm::filter::PolicyBase&) +inline VTKM_CONT bool Contour::DoMapField(vtkm::cont::DataSet& result, + const vtkm::cont::ArrayHandle& input, + const vtkm::filter::FieldMetadata& fieldMeta, + const vtkm::filter::PolicyBase&) { vtkm::cont::ArrayHandle fieldArray; diff --git a/vtkm/filter/GhostCellRemove.h b/vtkm/filter/GhostCellRemove.h index 888771972..c9cb5c735 100644 --- a/vtkm/filter/GhostCellRemove.h +++ b/vtkm/filter/GhostCellRemove.h @@ -51,15 +51,10 @@ public: VTKM_CONT bool GetRemoveAllGhost() const { return this->RemoveAll; } - VTKM_CONT - void ConvertOutputToUnstructured() { this->ConvertToUnstructured = true; } - VTKM_CONT bool GetRemoveByType() const { return !this->RemoveAll; } VTKM_CONT vtkm::UInt8 GetRemoveType() const { return this->RemoveVals; } - VTKM_CONT - bool GetConvertOutputToUnstructured() { return this->ConvertToUnstructured; } template VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input, @@ -78,16 +73,14 @@ public: private: bool RemoveAll; bool RemoveField; - bool ConvertToUnstructured; vtkm::UInt8 RemoveVals; vtkm::worklet::Threshold Worklet; - - VTKM_CONT vtkm::cont::CellSetExplicit<> ConvertOutputToUnstructured( - vtkm::cont::DynamicCellSet& inCells); }; } } // namespace vtkm::filter +#ifndef vtk_m_filter_GhostCellRemove_hxx #include +#endif #endif // vtk_m_filter_GhostCellRemove_h diff --git a/vtkm/filter/GhostCellRemove.hxx b/vtkm/filter/GhostCellRemove.hxx index b98f57d42..d4e31d3da 100644 --- a/vtkm/filter/GhostCellRemove.hxx +++ b/vtkm/filter/GhostCellRemove.hxx @@ -8,6 +8,10 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#ifndef vtk_m_filter_GhostCellRemove_hxx +#define vtk_m_filter_GhostCellRemove_hxx +#include + #include #include #include @@ -286,7 +290,6 @@ inline VTKM_CONT GhostCellRemove::GhostCellRemove() : vtkm::filter::FilterDataSetWithField() , RemoveAll(false) , RemoveField(false) - , ConvertToUnstructured(false) , RemoveVals(0) { this->SetActiveField("vtkmGhostCells"); @@ -331,29 +334,27 @@ inline VTKM_CONT vtkm::cont::DataSet GhostCellRemove::DoExecute( } if (this->GetRemoveAllGhost()) + { cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy), field, fieldMeta.GetAssociation(), RemoveAllGhosts()); + } else if (this->GetRemoveByType()) + { cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy), field, fieldMeta.GetAssociation(), RemoveGhostByType(this->GetRemoveType())); + } else + { throw vtkm::cont::ErrorFilterExecution("Unsupported ghost cell removal type"); + } vtkm::cont::DataSet output; output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex())); - - if (this->GetConvertOutputToUnstructured()) - { - vtkm::cont::CellSetExplicit<> explicitCells; - explicitCells = this->ConvertOutputToUnstructured(cellOut); - output.AddCellSet(explicitCells); - } - else - output.AddCellSet(cellOut); + output.AddCellSet(cellOut); return output; } @@ -383,41 +384,7 @@ inline VTKM_CONT bool GhostCellRemove::DoMapField( return false; } } - -inline VTKM_CONT vtkm::cont::CellSetExplicit<> GhostCellRemove::ConvertOutputToUnstructured( - vtkm::cont::DynamicCellSet& inCells) -{ - using PermStructured2d = vtkm::cont::CellSetPermutation>; - using PermStructured3d = vtkm::cont::CellSetPermutation>; - using PermExplicit = vtkm::cont::CellSetPermutation>; - using PermExplicitSingle = vtkm::cont::CellSetPermutation>; - - vtkm::cont::CellSetExplicit<> explicitCells; - - if (inCells.IsSameType(PermStructured2d())) - { - PermStructured2d perm = inCells.Cast(); - vtkm::worklet::CellDeepCopy::Run(perm, explicitCells); - } - else if (inCells.IsSameType(PermStructured3d())) - { - PermStructured3d perm = inCells.Cast(); - vtkm::worklet::CellDeepCopy::Run(perm, explicitCells); - } - else if (inCells.IsSameType(PermExplicit())) - { - PermExplicit perm = inCells.Cast(); - vtkm::worklet::CellDeepCopy::Run(perm, explicitCells); - } - else if (inCells.IsSameType(PermExplicitSingle())) - { - PermExplicitSingle perm = inCells.Cast(); - vtkm::worklet::CellDeepCopy::Run(perm, explicitCells); - } - else - throw vtkm::cont::ErrorFilterExecution("Unsupported permutation cell type"); - - return explicitCells; -} } } + +#endif //vtk_m_filter_GhostCellRemove_hxx diff --git a/vtkm/filter/testing/CMakeLists.txt b/vtkm/filter/testing/CMakeLists.txt index 1a9fdf624..dce052a74 100644 --- a/vtkm/filter/testing/CMakeLists.txt +++ b/vtkm/filter/testing/CMakeLists.txt @@ -15,6 +15,7 @@ set(unit_tests UnitTestCleanGrid.cxx UnitTestClipWithFieldFilter.cxx UnitTestClipWithImplicitFunctionFilter.cxx + UnitTestContourFilter.cxx UnitTestContourTreeUniformFilter.cxx UnitTestContourTreeUniformAugmentedFilter.cxx UnitTestCoordinateSystemTransform.cxx @@ -35,7 +36,6 @@ set(unit_tests UnitTestImageConnectivityFilter.cxx UnitTestLagrangianFilter.cxx UnitTestLagrangianStructuresFilter.cxx - UnitTestMarchingCubesFilter.cxx UnitTestMaskFilter.cxx UnitTestMaskPointsFilter.cxx UnitTestMeshQualityFilter.cxx diff --git a/vtkm/filter/testing/UnitTestCellSetConnectivityFilter.cxx b/vtkm/filter/testing/UnitTestCellSetConnectivityFilter.cxx index 6286891b5..73e708ee0 100644 --- a/vtkm/filter/testing/UnitTestCellSetConnectivityFilter.cxx +++ b/vtkm/filter/testing/UnitTestCellSetConnectivityFilter.cxx @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace { @@ -117,7 +117,7 @@ public: vtkm::Id3 dims(4, 4, 4); vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims); - vtkm::filter::MarchingCubes filter; + vtkm::filter::Contour filter; filter.SetGenerateNormals(true); filter.SetMergeDuplicatePoints(true); filter.SetIsoValue(0, 0.1); diff --git a/vtkm/filter/testing/UnitTestCleanGrid.cxx b/vtkm/filter/testing/UnitTestCleanGrid.cxx index 39452f033..f7cf44914 100644 --- a/vtkm/filter/testing/UnitTestCleanGrid.cxx +++ b/vtkm/filter/testing/UnitTestCleanGrid.cxx @@ -10,7 +10,7 @@ #include -#include +#include #include #include @@ -72,7 +72,7 @@ void TestPointMerging() vtkm::cont::testing::MakeTestDataSet makeDataSet; vtkm::cont::DataSet baseData = makeDataSet.Make3DUniformDataSet3(vtkm::Id3(4, 4, 4)); - vtkm::filter::MarchingCubes marchingCubes; + vtkm::filter::Contour marchingCubes; marchingCubes.SetIsoValue(0.05); marchingCubes.SetMergeDuplicatePoints(false); marchingCubes.SetActiveField("pointvar"); diff --git a/vtkm/filter/testing/UnitTestMarchingCubesFilter.cxx b/vtkm/filter/testing/UnitTestContourFilter.cxx similarity index 96% rename from vtkm/filter/testing/UnitTestMarchingCubesFilter.cxx rename to vtkm/filter/testing/UnitTestContourFilter.cxx index 08650c644..557bce6bc 100644 --- a/vtkm/filter/testing/UnitTestMarchingCubesFilter.cxx +++ b/vtkm/filter/testing/UnitTestContourFilter.cxx @@ -17,7 +17,7 @@ #include #include -#include +#include namespace vtkm_ut_mc_filter { @@ -268,14 +268,14 @@ inline vtkm::cont::DataSet MakeRadiantDataSet::Make3DRadiantDataSet(vtkm::IdComp return dataSet; } -void TestMarchingCubesUniformGrid() +void TestContourUniformGrid() { - std::cout << "Testing MarchingCubes filter on a uniform grid" << std::endl; + std::cout << "Testing Contour filter on a uniform grid" << std::endl; vtkm::Id3 dims(4, 4, 4); vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims); - vtkm::filter::MarchingCubes mc; + vtkm::filter::Contour mc; mc.SetGenerateNormals(true); mc.SetIsoValue(0, 0.5); @@ -334,9 +334,9 @@ void TestMarchingCubesUniformGrid() } } -void TestMarchingCubesCustomPolicy() +void TestContourCustomPolicy() { - std::cout << "Testing MarchingCubes filter with custom field and cellset" << std::endl; + std::cout << "Testing Contour filter with custom field and cellset" << std::endl; using DataSetGenerator = MakeRadiantDataSet; DataSetGenerator dataSetGenerator; @@ -344,7 +344,7 @@ void TestMarchingCubesCustomPolicy() const vtkm::IdComponent Dimension = 10; vtkm::cont::DataSet dataSet = dataSetGenerator.Make3DRadiantDataSet(Dimension); - vtkm::filter::MarchingCubes mc; + vtkm::filter::Contour mc; mc.SetGenerateNormals(false); mc.SetIsoValue(0, 0.45); @@ -435,7 +435,7 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured) vtkm::cont::ArrayHandle normals; - vtkm::filter::MarchingCubes mc; + vtkm::filter::Contour mc; mc.SetIsoValue(0, 200); mc.SetGenerateNormals(true); @@ -481,9 +481,9 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured) } } -void TestMarchingCubesNormals() +void TestContourNormals() { - std::cout << "Testing MarchingCubes normals generation" << std::endl; + std::cout << "Testing Contour normals generation" << std::endl; std::cout << "\tStructured dataset\n"; vtkm::cont::DataSet dataset = MakeNormalsTestDataSet(); @@ -498,16 +498,16 @@ void TestMarchingCubesNormals() TestNormals(result, false); } -void TestMarchingCubesFilter() +void TestContourFilter() { - TestMarchingCubesUniformGrid(); - TestMarchingCubesCustomPolicy(); - TestMarchingCubesNormals(); + TestContourUniformGrid(); + TestContourCustomPolicy(); + TestContourNormals(); } } // anonymous namespace -int UnitTestMarchingCubesFilter(int argc, char* argv[]) +int UnitTestContourFilter(int argc, char* argv[]) { - return vtkm::cont::testing::Testing::Run(vtkm_ut_mc_filter::TestMarchingCubesFilter, argc, argv); + return vtkm::cont::testing::Testing::Run(vtkm_ut_mc_filter::TestContourFilter, argc, argv); } diff --git a/vtkm/filter/testing/UnitTestGhostCellRemove.cxx b/vtkm/filter/testing/UnitTestGhostCellRemove.cxx index 77c51a53c..172dd2ebc 100644 --- a/vtkm/filter/testing/UnitTestGhostCellRemove.cxx +++ b/vtkm/filter/testing/UnitTestGhostCellRemove.cxx @@ -264,37 +264,34 @@ void TestGhostCellRemove() ghostCellRemoval.RemoveByType( static_cast(vtkm::CellClassification::GHOST)); - std::vector outputType = { "permutation", "explicit" }; - for (auto& ot : outputType) + auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy()); + vtkm::Id numCells = output.GetCellSet(0).GetNumberOfCells(); + + //Validate the output. + VTKM_TEST_ASSERT(output.GetNumberOfCellSets() == 1, + "Wrong number of cell sets in output"); + vtkm::Id numCellsReq = (nx - 2 * layer) * (ny - 2 * layer); + if (nz != 0) + numCellsReq *= (nz - 2 * layer); + + VTKM_TEST_ASSERT(numCellsReq == numCells, "Wrong number of cells in output"); + if (dsType == "uniform" || dsType == "rectilinear") { - if (ot == "explicit") - ghostCellRemoval.ConvertOutputToUnstructured(); - - auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy()); - vtkm::Id numCells = output.GetCellSet(0).GetNumberOfCells(); - - //Validate the output. - VTKM_TEST_ASSERT(output.GetNumberOfCellSets() == 1, - "Wrong number of cell sets in output"); - vtkm::Id numCellsReq = (nx - 2 * layer) * (ny - 2 * layer); - if (nz != 0) - numCellsReq *= (nz - 2 * layer); - - VTKM_TEST_ASSERT(numCellsReq == numCells, "Wrong number of cells in output"); - if (dsType == "uniform" || dsType == "rectilinear") + if (nz == 0) { - if (nz == 0) - VTKM_TEST_ASSERT( - output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<2>()), - "Wrong cell type for explicit conversion"); - else if (nz > 0) - VTKM_TEST_ASSERT( - output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<3>()), - "Wrong cell type for explicit conversion"); - } - else if (ot == "explicit") - VTKM_TEST_ASSERT(output.GetCellSet(0).IsType>(), + VTKM_TEST_ASSERT(output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<2>()), "Wrong cell type for explicit conversion"); + } + else if (nz > 0) + { + VTKM_TEST_ASSERT(output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<3>()), + "Wrong cell type for explicit conversion"); + } + } + else + { + VTKM_TEST_ASSERT(output.GetCellSet(0).IsType>(), + "Wrong cell type for explicit conversion"); } } @@ -309,7 +306,6 @@ void TestGhostCellRemove() vtkm::filter::GhostCellRemove ghostCellRemoval; ghostCellRemoval.RemoveGhostField(); - ghostCellRemoval.ConvertOutputToUnstructured(); auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy()); VTKM_TEST_ASSERT(output.GetCellSet(0).IsType>(), "Wrong cell type for explicit conversion"); diff --git a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx index e7d2ebc15..03732cd96 100644 --- a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx +++ b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx @@ -8,7 +8,7 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ #include -#include +#include #include #include @@ -236,7 +236,7 @@ void TestWithStructuredData() vtkm::cont::DataSet dataSet = Make3DWavelet(); // Cut a contour: - vtkm::filter::MarchingCubes contour; + vtkm::filter::Contour contour; contour.SetActiveField("scalars", vtkm::cont::Field::Association::POINTS); contour.SetNumberOfIsoValues(1); contour.SetIsoValue(192); diff --git a/vtkm/filter/testing/UnitTestThresholdFilter.cxx b/vtkm/filter/testing/UnitTestThresholdFilter.cxx index 854ecc57d..c47b588af 100644 --- a/vtkm/filter/testing/UnitTestThresholdFilter.cxx +++ b/vtkm/filter/testing/UnitTestThresholdFilter.cxx @@ -11,6 +11,7 @@ #include #include +#include #include using vtkm::cont::testing::MakeTestDataSet; @@ -43,6 +44,11 @@ public: VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 && cellFieldArray.GetPortalConstControl().Get(0) == 200.1f, "Wrong cell field data"); + + // Make sure that the resulting data set can be successfully passed to another + // simple filter using the cell set. + vtkm::filter::CleanGrid clean; + clean.Execute(output); } void TestRegular3D() const @@ -68,6 +74,11 @@ public: cellFieldArray.GetPortalConstControl().Get(0) == 100.1f && cellFieldArray.GetPortalConstControl().Get(1) == 100.2f, "Wrong cell field data"); + + // Make sure that the resulting data set can be successfully passed to another + // simple filter using the cell set. + vtkm::filter::CleanGrid clean; + clean.Execute(output); } void TestExplicit3D() const @@ -93,6 +104,11 @@ public: cellFieldArray.GetPortalConstControl().Get(0) == 100.1f && cellFieldArray.GetPortalConstControl().Get(1) == 100.2f, "Wrong cell field data"); + + // Make sure that the resulting data set can be successfully passed to another + // simple filter using the cell set. + vtkm::filter::CleanGrid clean; + clean.Execute(output); } void TestExplicit3DZeroResults() const @@ -115,6 +131,11 @@ public: output.GetField("cellvar").GetData().CopyTo(cellFieldArray); VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 0, "field should be empty"); + + // Make sure that the resulting data set can be successfully passed to another + // simple filter using the cell set. + vtkm::filter::CleanGrid clean; + clean.Execute(output); } void operator()() const diff --git a/vtkm/thirdparty/diy/update.sh b/vtkm/thirdparty/diy/update.sh index 02f382aaf..3ce5ef0ec 100755 --- a/vtkm/thirdparty/diy/update.sh +++ b/vtkm/thirdparty/diy/update.sh @@ -7,8 +7,8 @@ shopt -s dotglob readonly name="diy" readonly ownership="Diy Upstream " readonly subtree="vtkm/thirdparty/$name/vtkm$name" -readonly repo="https://gitlab.kitware.com/robertmaynard/diy2.git" -readonly tag="for_vtkm_updated" +readonly repo="https://gitlab.kitware.com/third-party/diy2.git" +readonly tag="for/vtk-m" readonly paths=" include LEGAL.txt diff --git a/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.hpp b/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.hpp index e990af1e2..69056f5b0 100644 --- a/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.hpp +++ b/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.hpp @@ -52,7 +52,9 @@ namespace mpi private: std::vector buffer_; int rank_; +#ifndef VTKM_DIY_NO_MPI MPI_Win window_; +#endif }; } // mpi } // diy diff --git a/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/resolve.hpp b/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/resolve.hpp index db01a807c..dae88c6f8 100644 --- a/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/resolve.hpp +++ b/vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/resolve.hpp @@ -7,11 +7,11 @@ namespace diy { // record master gids in assigner and then lookup the procs for all gids in the links - void fix_links(diy::Master& master, diy::DynamicAssigner& assigner); + inline void fix_links(diy::Master& master, diy::DynamicAssigner& assigner); // auxiliary functions; could stick them into detail namespace, but they might be useful on their own - void record_local_gids(const diy::Master& master, diy::DynamicAssigner& assigner); - void update_links(diy::Master& master, const diy::DynamicAssigner& assigner); + inline void record_local_gids(const diy::Master& master, diy::DynamicAssigner& assigner); + inline void update_links(diy::Master& master, const diy::DynamicAssigner& assigner); } void diff --git a/vtkm/worklet/CMakeLists.txt b/vtkm/worklet/CMakeLists.txt index b454338e6..2f6307180 100644 --- a/vtkm/worklet/CMakeLists.txt +++ b/vtkm/worklet/CMakeLists.txt @@ -38,7 +38,7 @@ set(headers Keys.h LagrangianStructures.h Magnitude.h - MarchingCubes.h + Contour.h Mask.h MaskIndices.h MaskNone.h diff --git a/vtkm/worklet/MarchingCubes.h b/vtkm/worklet/Contour.h similarity index 75% rename from vtkm/worklet/MarchingCubes.h rename to vtkm/worklet/Contour.h index 8e50b8a36..0773b5b3b 100644 --- a/vtkm/worklet/MarchingCubes.h +++ b/vtkm/worklet/Contour.h @@ -8,8 +8,8 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_MarchingCubes_h -#define vtk_m_worklet_MarchingCubes_h +#ifndef vtk_m_worklet_Contour_h +#define vtk_m_worklet_Contour_h #include #include @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include @@ -50,25 +50,9 @@ namespace vtkm namespace worklet { -namespace marchingcubes +namespace contour { -template -struct float_type -{ - using type = vtkm::FloatDefault; -}; -template <> -struct float_type -{ - using type = vtkm::Float32; -}; -template <> -struct float_type -{ - using type = vtkm::Float64; -}; - // ----------------------------------------------------------------------------- template vtkm::cont::ArrayHandle make_ScalarField( @@ -103,70 +87,37 @@ template class ClassifyCell : public vtkm::worklet::WorkletVisitCellsWithPoints { public: - struct ClassifyCellTagType : vtkm::ListTagBase - { - }; - using ControlSignature = void(WholeArrayIn isoValues, FieldInPoint fieldIn, - CellSetIn cellset, + CellSetIn cellSet, FieldOutCell outNumTriangles, - WholeArrayIn numTrianglesTable); + ExecObject classifyTable); using ExecutionSignature = void(CellShape, _1, _2, _4, _5); using InputDomain = _3; - template - VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shape, + template + VTKM_EXEC void operator()(CellShapeType shape, const IsoValuesType& isovalues, const FieldInType& fieldIn, vtkm::IdComponent& numTriangles, - const NumTrianglesTablePortalType& numTrianglesTable) const - { - if (shape.Id == CELL_SHAPE_HEXAHEDRON) - { - this->operator()( - vtkm::CellShapeTagHexahedron(), isovalues, fieldIn, numTriangles, numTrianglesTable); - } - else - { - numTriangles = 0; - } - } - - template - VTKM_EXEC void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shape), - const IsoValuesType& vtkmNotUsed(isovalues), - const FieldInType& vtkmNotUsed(fieldIn), - vtkm::IdComponent& vtkmNotUsed(numTriangles), - const NumTrianglesTablePortalType& vtkmNotUsed(numTrianglesTable)) const - { - } - - template - VTKM_EXEC void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shape), - const IsoValuesType& vtkmNotUsed(isovalues), - const FieldInType& vtkmNotUsed(fieldIn), - vtkm::IdComponent& vtkmNotUsed(numTriangles), - const NumTrianglesTablePortalType& vtkmNotUsed(numTrianglesTable)) const - { - } - - template - VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shape), - const IsoValuesType& isovalues, - const FieldInType& fieldIn, - vtkm::IdComponent& numTriangles, - const NumTrianglesTablePortalType& numTrianglesTable) const + const ClassifyTableType& classifyTable) const { vtkm::IdComponent sum = 0; - for (vtkm::Id i = 0; i < isovalues.GetNumberOfValues(); ++i) + vtkm::IdComponent numIsoValues = static_cast(isovalues.GetNumberOfValues()); + vtkm::IdComponent numVerticesPerCell = classifyTable.GetNumVerticesPerCell(shape.Id); + + for (vtkm::Id i = 0; i < numIsoValues; ++i) { - const vtkm::IdComponent caseNumber = - ((fieldIn[0] > isovalues[i]) | (fieldIn[1] > isovalues[i]) << 1 | - (fieldIn[2] > isovalues[i]) << 2 | (fieldIn[3] > isovalues[i]) << 3 | - (fieldIn[4] > isovalues[i]) << 4 | (fieldIn[5] > isovalues[i]) << 5 | - (fieldIn[6] > isovalues[i]) << 6 | (fieldIn[7] > isovalues[i]) << 7); - sum += numTrianglesTable.Get(caseNumber); + vtkm::IdComponent caseNumber = 0; + for (vtkm::IdComponent j = 0; j < numVerticesPerCell; ++j) + { + caseNumber |= (fieldIn[j] > isovalues[i]) << j; + } + + sum += classifyTable.GetNumTriangles(shape.Id, caseNumber); } numTriangles = sum; } @@ -175,6 +126,7 @@ public: /// \brief Used to store data need for the EdgeWeightGenerate worklet. /// This information is not passed as part of the arguments to the worklet as /// that dramatically increase compile time by 200% +// TODO: remove unused data members. // ----------------------------------------------------------------------------- class EdgeWeightGenerateMetaData : vtkm::cont::ExecutionObjectBase { @@ -200,17 +152,11 @@ public: vtkm::cont::ArrayHandle& interpWeights, vtkm::cont::ArrayHandle& interpIds, vtkm::cont::ArrayHandle& interpCellIds, - vtkm::cont::ArrayHandle& interpContourId, - const vtkm::cont::ArrayHandle& edgeTable, - const vtkm::cont::ArrayHandle& numTriTable, - const vtkm::cont::ArrayHandle& triTable) + vtkm::cont::ArrayHandle& interpContourId) : InterpWeightsPortal(interpWeights.PrepareForOutput(3 * size, DeviceAdapter())) , InterpIdPortal(interpIds.PrepareForOutput(3 * size, DeviceAdapter())) , InterpCellIdPortal(interpCellIds.PrepareForOutput(3 * size, DeviceAdapter())) , InterpContourPortal(interpContourId.PrepareForOutput(3 * size, DeviceAdapter())) - , EdgeTable(edgeTable.PrepareForInput(DeviceAdapter())) - , NumTriTable(numTriTable.PrepareForInput(DeviceAdapter())) - , TriTable(triTable.PrepareForInput(DeviceAdapter())) { // Interp needs to be 3 times longer than size as they are per point of the // output triangle @@ -219,9 +165,6 @@ public: typename PortalTypes::Portal InterpIdPortal; typename PortalTypes::Portal InterpCellIdPortal; typename PortalTypes::Portal InterpContourPortal; - typename PortalTypes::PortalConst EdgeTable; - typename PortalTypes::PortalConst NumTriTable; - typename PortalTypes::PortalConst TriTable; }; VTKM_CONT @@ -229,32 +172,20 @@ public: vtkm::cont::ArrayHandle& interpWeights, vtkm::cont::ArrayHandle& interpIds, vtkm::cont::ArrayHandle& interpCellIds, - vtkm::cont::ArrayHandle& interpContourId, - const vtkm::cont::ArrayHandle& edgeTable, - const vtkm::cont::ArrayHandle& numTriTable, - const vtkm::cont::ArrayHandle& triTable) + vtkm::cont::ArrayHandle& interpContourId) : Size(size) , InterpWeights(interpWeights) , InterpIds(interpIds) , InterpCellIds(interpCellIds) , InterpContourId(interpContourId) - , EdgeTable(edgeTable) - , NumTriTable(numTriTable) - , TriTable(triTable) { } template VTKM_CONT ExecObject PrepareForExecution(DeviceAdapter) { - return ExecObject(this->Size, - this->InterpWeights, - this->InterpIds, - this->InterpCellIds, - this->InterpContourId, - this->EdgeTable, - this->NumTriTable, - this->TriTable); + return ExecObject( + this->Size, this->InterpWeights, this->InterpIds, this->InterpCellIds, this->InterpContourId); } private: @@ -263,9 +194,6 @@ private: vtkm::cont::ArrayHandle InterpIds; vtkm::cont::ArrayHandle InterpCellIds; vtkm::cont::ArrayHandle InterpContourId; - vtkm::cont::ArrayHandle EdgeTable; - vtkm::cont::ArrayHandle NumTriTable; - vtkm::cont::ArrayHandle TriTable; }; /// \brief Compute the weights for each edge that is used to generate @@ -275,10 +203,6 @@ template class EdgeWeightGenerate : public vtkm::worklet::WorkletVisitCellsWithPoints { public: - struct ClassifyCellTagType : vtkm::ListTagBase - { - }; - using ScatterType = vtkm::worklet::ScatterCounting; template @@ -290,99 +214,53 @@ public: typedef void ControlSignature(CellSetIn cellset, // Cell set WholeArrayIn isoValues, FieldInPoint fieldIn, // Input point field defining the contour - ExecObject metaData // Metadata for edge weight generation - ); + ExecObject metaData, // Metadata for edge weight generation + ExecObject classifyTable, + ExecObject triTable); using ExecutionSignature = - void(CellShape, _2, _3, _4, InputIndex, WorkIndex, VisitIndex, PointIndices); + void(CellShape, _2, _3, _4, _5, _6, InputIndex, WorkIndex, VisitIndex, PointIndices); using InputDomain = _1; - template - VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shape, + VTKM_EXEC void operator()(const CellShape shape, const IsoValuesType& isovalues, const FieldInType& fieldIn, // Input point field defining the contour - EdgeWeightGenerateMetaData::ExecObject& metaData, + const EdgeWeightGenerateMetaData::ExecObject& metaData, + const ClassifyTableType& classifyTable, + const TriTableType& triTable, vtkm::Id inputCellId, vtkm::Id outputCellId, vtkm::IdComponent visitIndex, const IndicesVecType& indices) const - { //covers when we have hexs coming from unstructured data - if (shape.Id == CELL_SHAPE_HEXAHEDRON) - { - this->operator()(vtkm::CellShapeTagHexahedron(), - isovalues, - fieldIn, - metaData, - inputCellId, - outputCellId, - visitIndex, - indices); - } - } - - template - VTKM_EXEC void operator()( - CellShapeTagQuad vtkmNotUsed(shape), - const IsoValuesType& vtkmNotUsed(isovalues), - const FieldInType& vtkmNotUsed(fieldIn), // Input point field defining the contour - EdgeWeightGenerateMetaData::ExecObject& vtkmNotUsed(metaData), - vtkm::Id vtkmNotUsed(inputCellId), - vtkm::Id vtkmNotUsed(outputCellId), - vtkm::IdComponent vtkmNotUsed(visitIndex), - const IndicesVecType& vtkmNotUsed(indices)) const - { //covers when we have quads coming from 2d structured data - } - - template - VTKM_EXEC void operator()( - CellShapeTagWedge vtkmNotUsed(shape), - const IsoValuesType& vtkmNotUsed(isovalues), - const FieldInType& vtkmNotUsed(fieldIn), // Input point field defining the contour - EdgeWeightGenerateMetaData::ExecObject& vtkmNotUsed(metaData), - vtkm::Id vtkmNotUsed(inputCellId), - vtkm::Id vtkmNotUsed(outputCellId), - vtkm::IdComponent vtkmNotUsed(visitIndex), - const IndicesVecType& vtkmNotUsed(indices)) const - { //covers when we have quads coming from 2d structured data - } - template - VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron, - const IsoValuesType& isovalues, - const FieldInType& fieldIn, // Input point field defining the contour - EdgeWeightGenerateMetaData::ExecObject& metaData, - vtkm::Id inputCellId, - vtkm::Id outputCellId, - vtkm::IdComponent visitIndex, - const IndicesVecType& indices) const - { //covers when we have hexs coming from 3d structured data + { const vtkm::Id outputPointId = 3 * outputCellId; using FieldType = typename vtkm::VecTraits::ComponentType; vtkm::IdComponent sum = 0, caseNumber = 0; - vtkm::IdComponent i = 0, size = static_cast(isovalues.GetNumberOfValues()); - for (i = 0; i < size; ++i) + vtkm::IdComponent i = 0, + numIsoValues = static_cast(isovalues.GetNumberOfValues()); + vtkm::IdComponent numVerticesPerCell = classifyTable.GetNumVerticesPerCell(shape.Id); + + for (i = 0; i < numIsoValues; ++i) { const FieldType ivalue = isovalues[i]; // Compute the Marching Cubes case number for this cell. We need to iterate // the isovalues until the sum >= our visit index. But we need to make // sure the caseNumber is correct before stopping - caseNumber = - ((fieldIn[0] > ivalue) | (fieldIn[1] > ivalue) << 1 | (fieldIn[2] > ivalue) << 2 | - (fieldIn[3] > ivalue) << 3 | (fieldIn[4] > ivalue) << 4 | (fieldIn[5] > ivalue) << 5 | - (fieldIn[6] > ivalue) << 6 | (fieldIn[7] > ivalue) << 7); - sum += metaData.NumTriTable.Get(caseNumber); + caseNumber = 0; + for (vtkm::IdComponent j = 0; j < numVerticesPerCell; ++j) + { + caseNumber |= (fieldIn[j] > ivalue) << j; + } + + sum += classifyTable.GetNumTriangles(shape.Id, caseNumber); if (sum > visitIndex) { break; @@ -392,14 +270,11 @@ public: visitIndex = sum - visitIndex - 1; // Interpolate for vertex positions and associated scalar values - const vtkm::Id triTableOffset = static_cast(caseNumber * 16 + visitIndex * 3); for (vtkm::IdComponent triVertex = 0; triVertex < 3; triVertex++) { - const vtkm::IdComponent edgeIndex = metaData.TriTable.Get(triTableOffset + triVertex); - const vtkm::IdComponent edgeVertex0 = metaData.EdgeTable.Get(2 * edgeIndex + 0); - const vtkm::IdComponent edgeVertex1 = metaData.EdgeTable.Get(2 * edgeIndex + 1); - const FieldType fieldValue0 = fieldIn[edgeVertex0]; - const FieldType fieldValue1 = fieldIn[edgeVertex1]; + auto edgeVertices = triTable.GetEdgeVertices(shape.Id, caseNumber, visitIndex, triVertex); + const FieldType fieldValue0 = fieldIn[edgeVertices.first]; + const FieldType fieldValue1 = fieldIn[edgeVertices.second]; // Store the input cell id so that we can properly generate the normals // in a subsequent call, after we have merged duplicate points @@ -407,8 +282,9 @@ public: metaData.InterpContourPortal.Set(outputPointId + triVertex, static_cast(i)); - metaData.InterpIdPortal.Set(outputPointId + triVertex, - vtkm::Id2(indices[edgeVertex0], indices[edgeVertex1])); + metaData.InterpIdPortal.Set( + outputPointId + triVertex, + vtkm::Id2(indices[edgeVertices.first], indices[edgeVertices.second])); vtkm::FloatDefault interpolant = static_cast(isovalues[i] - fieldValue0) / static_cast(fieldValue1 - fieldValue0); @@ -540,7 +416,7 @@ void MergeDuplicates(const vtkm::cont::ArrayHandle& origina //need to build the new connectivity auto uniqueKeys = keys.GetUniqueKeys(); vtkm::cont::Algorithm::LowerBounds( - uniqueKeys, original_keys, connectivity, marchingcubes::MultiContourLess()); + uniqueKeys, original_keys, connectivity, contour::MultiContourLess()); //update the edge ids vtkm::worklet::DispatcherMapField edgeDispatcher; @@ -745,12 +621,12 @@ struct GenerateNormalsDeduced vtkm::worklet::DispatcherMapTopology dispatcherNormalsPass1( NormalsWorkletPass1::MakeScatter(*edges)); dispatcherNormalsPass1.Invoke( - *cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *normals); + *cellset, *cellset, coordinates, contour::make_ScalarField(*field), *normals); vtkm::worklet::DispatcherMapTopology dispatcherNormalsPass2( NormalsWorkletPass2::MakeScatter(*edges)); dispatcherNormalsPass2.Invoke( - *cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *weights, *normals); + *cellset, *cellset, coordinates, contour::make_ScalarField(*field), *weights, *normals); } }; @@ -779,26 +655,15 @@ void GenerateNormals(vtkm::cont::ArrayHandle>& normals } /// \brief Compute the isosurface for a uniform grid data set -class MarchingCubes +class Contour { public: //---------------------------------------------------------------------------- - MarchingCubes(bool mergeDuplicates = true) + Contour(bool mergeDuplicates = true) : MergeDuplicatePoints(mergeDuplicates) - , EdgeTable() - , NumTrianglesTable() - , TriangleTable() , InterpolationWeights() , InterpolationEdgeIds() { - // Set up the Marching Cubes case tables as part of the filter so that - // we cache these tables in the execution environment between execution runs - this->EdgeTable = vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::edgeTable, 24); - - this->NumTrianglesTable = - vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::numTrianglesTable, 256); - - this->TriangleTable = vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::triTable, 256 * 16); } //---------------------------------------------------------------------------- @@ -859,7 +724,7 @@ public: vtkm::cont::ArrayHandle ProcessPointField( const vtkm::cont::ArrayHandle& input) const { - using vtkm::worklet::marchingcubes::MapPointField; + using vtkm::worklet::contour::MapPointField; MapPointField applyToField; vtkm::worklet::DispatcherMapField applyFieldDispatcher(applyToField); @@ -897,7 +762,7 @@ private: typename NormalType> struct DeduceCellType { - MarchingCubes* MC = nullptr; + Contour* MC = nullptr; const ValueType* isovalues = nullptr; const vtkm::Id* numIsoValues = nullptr; const CoordinateSystem* coordinateSystem = nullptr; @@ -987,10 +852,10 @@ private: vtkm::cont::ArrayHandle, StorageTagNormals> normals, bool withNormals) { - using vtkm::worklet::marchingcubes::ClassifyCell; - using vtkm::worklet::marchingcubes::EdgeWeightGenerate; - using vtkm::worklet::marchingcubes::EdgeWeightGenerateMetaData; - using vtkm::worklet::marchingcubes::MapPointField; + using vtkm::worklet::contour::ClassifyCell; + using vtkm::worklet::contour::EdgeWeightGenerate; + using vtkm::worklet::contour::EdgeWeightGenerateMetaData; + using vtkm::worklet::contour::MapPointField; // Setup the Dispatcher Typedefs using ClassifyDispatcher = vtkm::worklet::DispatcherMapTopology>; @@ -999,16 +864,14 @@ private: vtkm::cont::ArrayHandle isoValuesHandle = vtkm::cont::make_ArrayHandle(isovalues, numIsoValues); + // Call the ClassifyCell functor to compute the Marching Cubes case numbers // for each cell, and the number of vertices to be generated - vtkm::cont::ArrayHandle numOutputTrisPerCell; - { - ClassifyCell classifyCell; - ClassifyDispatcher classifyCellDispatcher(classifyCell); - classifyCellDispatcher.Invoke( - isoValuesHandle, inputField, cells, numOutputTrisPerCell, this->NumTrianglesTable); + contour::ClassifyCell classifyCell; + ClassifyDispatcher dispatcher(classifyCell); + dispatcher.Invoke(isoValuesHandle, inputField, cells, numOutputTrisPerCell, this->classTable); } //Pass 2 Generate the edges @@ -1025,10 +888,7 @@ private: this->InterpolationWeights, this->InterpolationEdgeIds, originalCellIdsForPoints, - contourIds, - this->EdgeTable, - this->NumTrianglesTable, - this->TriangleTable); + contourIds); EdgeWeightGenerate weightGenerate; GenerateDispatcher edgeDispatcher(weightGenerate, scatter); @@ -1037,7 +897,9 @@ private: //cast to a scalar field if not one, as cellderivative only works on those isoValuesHandle, inputField, - metaData); + metaData, + this->classTable, + this->triTable); } if (numIsoValues <= 1 || !this->MergeDuplicatePoints) @@ -1054,15 +916,15 @@ private: // output. But for InterpolationEdgeIds we need to do it manually once done if (numIsoValues == 1) { - marchingcubes::MergeDuplicates(this->InterpolationEdgeIds, //keys - this->InterpolationWeights, //values - this->InterpolationEdgeIds, //values - originalCellIdsForPoints, //values - connectivity); // computed using lower bounds + contour::MergeDuplicates(this->InterpolationEdgeIds, //keys + this->InterpolationWeights, //values + this->InterpolationEdgeIds, //values + originalCellIdsForPoints, //values + connectivity); // computed using lower bounds } else if (numIsoValues > 1) { - marchingcubes::MergeDuplicates( + contour::MergeDuplicates( vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationEdgeIds), //keys this->InterpolationWeights, //values this->InterpolationEdgeIds, //values @@ -1093,22 +955,20 @@ private: //now that the vertices have been generated we can generate the normals if (withNormals) { - marchingcubes::GenerateNormals(normals, - inputField, - cells, - coordinateSystem, - this->InterpolationEdgeIds, - this->InterpolationWeights); + contour::GenerateNormals(normals, + inputField, + cells, + coordinateSystem, + this->InterpolationEdgeIds, + this->InterpolationWeights); } return outputCells; } bool MergeDuplicatePoints; - - vtkm::cont::ArrayHandle EdgeTable; - vtkm::cont::ArrayHandle NumTrianglesTable; - vtkm::cont::ArrayHandle TriangleTable; + vtkm::worklet::internal::CellClassifyTable classTable; + vtkm::worklet::internal::TriangleGenerationTable triTable; vtkm::cont::ArrayHandle InterpolationWeights; vtkm::cont::ArrayHandle InterpolationEdgeIds; @@ -1118,4 +978,4 @@ private: } } // namespace vtkm::worklet -#endif // vtk_m_worklet_MarchingCubes_h +#endif // vtk_m_worklet_Contour_h diff --git a/vtkm/worklet/Threshold.h b/vtkm/worklet/Threshold.h index dd0d14e6b..5e9ed7537 100644 --- a/vtkm/worklet/Threshold.h +++ b/vtkm/worklet/Threshold.h @@ -10,6 +10,7 @@ #ifndef vtkm_m_worklet_Threshold_h #define vtkm_m_worklet_Threshold_h +#include #include #include @@ -171,7 +172,9 @@ public: template void operator()(const CellSetType& cellSet) const { - this->Output = this->Worklet.Run(cellSet, this->Field, this->FieldType, this->Predicate); + // Copy output to an explicit grid so that other units can guess what this is. + this->Output = vtkm::worklet::CellDeepCopy::Run( + this->Worklet.Run(cellSet, this->Field, this->FieldType, this->Predicate)); } }; diff --git a/vtkm/worklet/contour/CMakeLists.txt b/vtkm/worklet/contour/CMakeLists.txt index 5cc2a952c..50bdcd0c2 100644 --- a/vtkm/worklet/contour/CMakeLists.txt +++ b/vtkm/worklet/contour/CMakeLists.txt @@ -9,7 +9,7 @@ ##============================================================================ set(headers - DataTables.h + ContourTables.h ) #----------------------------------------------------------------------------- diff --git a/vtkm/worklet/contour/ContourTables.h b/vtkm/worklet/contour/ContourTables.h new file mode 100644 index 000000000..74f75fe51 --- /dev/null +++ b/vtkm/worklet/contour/ContourTables.h @@ -0,0 +1,627 @@ +//============================================================================ +// 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_ContourTable_h +#define vtk_m_ContourTable_h + +#include +#include + +#include +#include + +namespace vtkm +{ +namespace worklet +{ +namespace internal +{ + +// clang-format off +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumVerticesPerCellTable[] = { + 0, // CELL_SHAPE_EMPTY = 0, + 0, // CELL_SHAPE_VERTEX = 1, + 0, // CELL_SHAPE_POLY_VERTEX = 2, + 0, // CELL_SHAPE_LINE = 3, + 0, // CELL_SHAPE_POLY_LINE = 4, + 3, // CELL_SHAPE_TRIANGLE = 5, + 0, // CELL_SHAPE_TRIANGLE_STRIP = 6, + 0, // CELL_SHAPE_POLYGON = 7, + 0, // CELL_SHAPE_PIXEL = 8, + 4, // CELL_SHAPE_QUAD = 9, + 4, // CELL_SHAPE_TETRA = 10, + 0, // CELL_SHAPE_VOXEL = 11, + 8, // CELL_SHAPE_HEXAHEDRON = 12, + 6, // CELL_SHAPE_WEDGE = 13, + 5 // CELL_SHAPE_PYRAMID = 14, +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumTrianglesTableOffset[] = { + 0, // CELL_SHAPE_EMPTY = 0, + 0, // CELL_SHAPE_VERTEX = 1, + 0, // CELL_SHAPE_POLY_VERTEX = 2, + 0, // CELL_SHAPE_LINE = 3, + 0, // CELL_SHAPE_POLY_LINE = 4, + 0, // CELL_SHAPE_TRIANGLE = 5, + 0, // CELL_SHAPE_TRIANGLE_STRIP = 6, + 0, // CELL_SHAPE_POLYGON = 7, + 0, // CELL_SHAPE_PIXEL = 8, + 0, // CELL_SHAPE_QUAD = 9, + 0, // CELL_SHAPE_TETRA = 10, + 0, // CELL_SHAPE_VOXEL = 11, + 16, // CELL_SHAPE_HEXAHEDRON = 12, + 16+256, // CELL_SHAPE_WEDGE = 13, + 16+256+64 // CELL_SHAPE_PYRAMID = 14, +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumTrianglesTable[] = { + // CELL_SHAPE_TETRA, case 0 - 15 + 0, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0, + // CELL_SHAPE_HEXAHEDRON, case 0 - 255 + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, + 2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2, + 3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, + 3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2, + 3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1, + 3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1, + 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0, + // CELL_SHAPE_WEDGE, case 0 - 63 + 0, 1, 1, 2, 1, 2, 1, 1, 1, 2, 2, 3, 2, 3, 3, 2, + 1, 2, 2, 3, 2, 3, 3, 2, 2, 3, 3, 2, 3, 4, 4, 1, + 1, 2, 2, 3, 2, 3, 3, 2, 2, 3, 3, 4, 3, 2, 4, 1, + 2, 3, 3, 4, 3, 4, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0, + // CELL_SHAPE_PYRAMID, case 0 - 31 + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, + 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0 +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent EdgeTable[] = { + // CELL_SHAPE_TETRA, 6 edge * 2 vertices/edge = 12 entries + 0, 1, // edge 0 : vertex 0 -> vertex 1 + 1, 2, // edge 1 : vertex 1 -> vertex 2 + 0, 2, // edge 2 : vertex 0 -> vertex 2 + 0, 3, // edge 3 : vertex 0 -> vertex 3 + 1, 3, // edge 4 : vertex 1 -> vertex 3 + 2, 3, // edge 5 : vertex 2 -> vertex 3 + // CELL_SHAPE_HEXAHEDRON, 12 edges * 2 vertices/edge = 24 entries + 0, 1, // bottom layer + 1, 2, + 3, 2, + 0, 3, + 4, 5, // top layer + 5, 6, + 7, 6, + 4, 7, + 0, 4, // side + 1, 5, + 2, 6, + 3, 7, + // CELL_SHAPE_WEDGE, 9 edges * 2 vertices/edge = 18 entries + 0, 1, + 1, 2, + 2, 0, + 3, 4, + 4, 5, + 5, 3, + 0, 3, + 1, 4, + 2, 5, + // CELL_SHAPE_PYRAMID, 8 edges * 2 vertices/ede = 16 entries + 0, 1, + 1, 2, + 2, 3, + 3, 0, + 0, 4, + 1, 4, + 2, 4, + 3, 4 +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent EdgeTableOffset[] = { + 0, // CELL_SHAPE_EMPTY = 0, + 0, // CELL_SHAPE_VERTEX = 1, + 0, // CELL_SHAPE_POLY_VERTEX = 2, + 0, // CELL_SHAPE_LINE = 3, + 0, // CELL_SHAPE_POLY_LINE = 4, + 0, // CELL_SHAPE_TRIANGLE = 5, + 0, // CELL_SHAPE_TRIANGLE_STRIP = 6, + 0, // CELL_SHAPE_POLYGON = 7, + 0, // CELL_SHAPE_PIXEL = 8, + 0, // CELL_SHAPE_QUAD = 9, + 0, // CELL_SHAPE_TETRA = 10, + 0, // CELL_SHAPE_VOXEL = 11, + 12, // CELL_SHAPE_HEXAHEDRON = 12, + 12+24, // CELL_SHAPE_WEDGE = 13, + 12+24+18 // CELL_SHAPE_PYRAMID = 14, +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent TriangleTable[] = { +#define X -1 + // CELL_SHAPE_TETRA, 16 cases, 7 edges/cases, 112 entries total + // FIXME, this is different winding rule than VTK + X, X, X, X, X, X, X, + 0, 3, 2, X, X, X, X, + 0, 1, 4, X, X, X, X, + 1, 4, 2, 2, 4, 3, X, + 1, 2, 5, X, X, X, X, + 0, 3, 5, 0, 5, 1, X, + 0, 2, 5, 0, 5, 4, X, + 5, 4, 3, X, X, X, X, + 3, 4, 5, X, X, X, X, + 4, 5, 0, 5, 2, 0, X, + 1, 5, 0, 5, 3, 0, X, + 5, 2, 1, X, X, X, X, + 3, 4, 2, 2, 4, 1, X, + 4, 1, 0, X, X, X, X, + 2, 3, 0, X, X, X, X, + X, X, X, X, X, X, X, + + // CELL_SHAPE_HEXAHEDRON, 256 cases, 16 edges/cases, 4096 entries total + X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, + 0, 8, 3, X, X, X, X, X, X, X, X, X, X, X, X, X, + 0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X, + 1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X, + 1, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X, + 0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X, + 9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X, + 2, 8, 3, 2, 10, 8, 10, 9, 8, X, X, X, X, X, X, X, + 3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X, + 0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X, + 1, 9, 0, 2, 3, 11, X, X, X, X, X, X, X, X, X, X, + 1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X, + 3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X, + 0, 10, 1, 0, 8, 10, 8, 11, 10, X, X, X, X, X, X, X, + 3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X, + 9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X, + 4, 7, 8, X, X, X, X, X, X, X, X, X, X, X, X, X, + 4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X, + 0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, + 4, 1, 9, 4, 7, 1, 7, 3, 1, X, X, X, X, X, X, X, + 1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, + 3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X, + 9, 2, 10, 9, 0, 2, 8, 4, 7, X, X, X, X, X, X, X, + 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X, + 8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, 11, 4, 7, 11, 2, 4, 2, 0, + 4, X, X, X, X, X, X, X, 9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X, + 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X, 3, 10, 1, 3, 11, 10, 7, 8, + 4, X, X, X, X, X, X, X, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X, + 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X, 4, 7, 11, 4, 11, 9, 9, 11, + 10, X, X, X, X, X, X, X, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X, + 9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X, 0, 5, 4, 1, 5, 0, X, X, + X, X, X, X, X, X, X, X, 8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X, + 1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 10, 4, 9, + 5, X, X, X, X, X, X, X, 5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X, + 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X, 9, 5, 4, 2, 3, 11, X, X, + X, X, X, X, X, X, X, X, 0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X, + 0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X, 2, 1, 5, 2, 5, 8, 2, 8, + 11, 4, 8, 5, X, X, X, X, 10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X, + 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X, 5, 4, 0, 5, 0, 11, 5, 11, + 10, 11, 0, 3, X, X, X, X, 5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, + 9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X, 9, 3, 0, 9, 5, 3, 5, 7, + 3, X, X, X, X, X, X, X, 0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X, + 1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X, 9, 7, 8, 9, 5, 7, 10, 1, + 2, X, X, X, X, X, X, X, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X, + 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X, 2, 10, 5, 2, 5, 3, 3, 5, + 7, X, X, X, X, X, X, X, 7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X, + 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X, 2, 3, 11, 0, 1, 8, 1, 7, + 8, 1, 5, 7, X, X, X, X, 11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X, + 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X, 5, 7, 0, 5, 0, 9, 7, 11, + 0, 1, 0, 10, 11, 10, 0, X, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X, + 11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X, 10, 6, 5, X, X, X, X, X, + X, X, X, X, X, X, X, X, 0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, + 9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, 1, 8, 3, 1, 9, 8, 5, 10, + 6, X, X, X, X, X, X, X, 1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X, + 1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X, 9, 6, 5, 9, 0, 6, 0, 2, + 6, X, X, X, X, X, X, X, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X, + 2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X, 11, 0, 8, 11, 2, 0, 10, 6, + 5, X, X, X, X, X, X, X, 0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X, + 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X, 6, 3, 11, 6, 5, 3, 5, 1, + 3, X, X, X, X, X, X, X, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X, + 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X, 6, 5, 9, 6, 9, 11, 11, 9, + 8, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X, + 4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X, 1, 9, 0, 5, 10, 6, 8, 4, + 7, X, X, X, X, X, X, X, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X, + 6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X, 1, 2, 5, 5, 2, 6, 3, 0, + 4, 3, 4, 7, X, X, X, X, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X, + 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X, 3, 11, 2, 7, 8, 4, 10, 6, + 5, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X, + 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X, 9, 2, 1, 9, 11, 2, 9, 4, + 11, 7, 11, 4, 5, 10, 6, X, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X, + 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X, 0, 5, 9, 0, 6, 5, 0, 3, + 6, 11, 6, 3, 8, 4, 7, X, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X, + 10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X, 4, 10, 6, 4, 9, 10, 0, 8, + 3, X, X, X, X, X, X, X, 10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X, + 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X, 1, 4, 9, 1, 2, 4, 2, 6, + 4, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X, + 0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X, 8, 3, 2, 8, 2, 4, 4, 2, + 6, X, X, X, X, X, X, X, 10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X, + 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X, 3, 11, 2, 0, 1, 6, 0, 6, + 4, 6, 1, 10, X, X, X, X, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X, + 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X, 8, 11, 1, 8, 1, 0, 11, 6, + 1, 9, 1, 4, 6, 4, 1, X, 3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X, + 6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X, 7, 10, 6, 7, 8, 10, 8, 9, + 10, X, X, X, X, X, X, X, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X, + 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X, 10, 6, 7, 10, 7, 1, 1, 7, + 3, X, X, X, X, X, X, X, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X, + 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X, 7, 8, 0, 7, 0, 6, 6, 0, + 2, X, X, X, X, X, X, X, 7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X, + 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X, 2, 0, 7, 2, 7, 11, 0, 9, + 7, 6, 7, 10, 9, 10, 7, X, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X, + 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X, 8, 9, 6, 8, 6, 7, 9, 1, + 6, 11, 6, 3, 1, 3, 6, X, 0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X, + 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X, 7, 11, 6, X, X, X, X, X, + X, X, X, X, X, X, X, X, 7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X, + 3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X, 0, 1, 9, 11, 7, 6, X, X, + X, X, X, X, X, X, X, X, 8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X, + 10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 8, 6, 11, + 7, X, X, X, X, X, X, X, 2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X, + 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X, 7, 2, 3, 6, 2, 7, X, X, + X, X, X, X, X, X, X, X, 7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X, + 2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X, 1, 6, 2, 1, 8, 6, 1, 9, + 8, 8, 7, 6, X, X, X, X, 10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X, + 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X, 0, 3, 7, 0, 7, 10, 0, 10, + 9, 6, 10, 7, X, X, X, X, 7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X, + 6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X, 3, 6, 11, 3, 0, 6, 0, 4, + 6, X, X, X, X, X, X, X, 8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X, + 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X, 6, 8, 4, 6, 11, 8, 2, 10, + 1, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X, + 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X, 10, 9, 3, 10, 3, 2, 9, 4, + 3, 11, 3, 6, 4, 6, 3, X, 8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, + 0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 4, 2, 4, + 6, 4, 3, 8, X, X, X, X, 1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X, + 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X, 10, 1, 0, 10, 0, 6, 6, 0, + 4, X, X, X, X, X, X, X, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X, + 10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X, 4, 9, 5, 7, 6, 11, X, X, + X, X, X, X, X, X, X, X, 0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X, + 5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X, 11, 7, 6, 8, 3, 4, 3, 5, + 4, 3, 1, 5, X, X, X, X, 9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X, + 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X, 7, 6, 11, 5, 4, 10, 4, 2, + 10, 4, 0, 2, X, X, X, X, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X, + 7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X, 9, 5, 4, 0, 8, 6, 0, 6, + 2, 6, 8, 7, X, X, X, X, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X, + 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X, 9, 5, 4, 10, 1, 6, 1, 7, + 6, 1, 3, 7, X, X, X, X, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X, + 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X, 7, 6, 10, 7, 10, 8, 5, 4, + 10, 4, 8, 10, X, X, X, X, 6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X, + 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X, 0, 11, 8, 0, 5, 11, 0, 1, + 5, 5, 6, 11, X, X, X, X, 6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X, + 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X, 0, 11, 3, 0, 6, 11, 0, 9, + 6, 5, 6, 9, 1, 2, 10, X, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X, + 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X, 5, 8, 9, 5, 2, 8, 5, 6, + 2, 3, 8, 2, X, X, X, X, 9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X, + 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X, 1, 5, 6, 2, 1, 6, X, X, + X, X, X, X, X, X, X, X, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X, + 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X, 0, 3, 8, 5, 6, 10, X, X, + X, X, X, X, X, X, X, X, 10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, + 11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X, 11, 5, 10, 11, 7, 5, 8, 3, + 0, X, X, X, X, X, X, X, 5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X, + 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X, 11, 1, 2, 11, 7, 1, 7, 5, + 1, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X, + 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X, 7, 5, 2, 7, 2, 11, 5, 9, + 2, 3, 2, 8, 9, 8, 2, X, 2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, + 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X, 9, 0, 1, 5, 10, 3, 5, 3, + 7, 3, 10, 2, X, X, X, X, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X, + 1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X, 0, 8, 7, 0, 7, 1, 1, 7, + 5, X, X, X, X, X, X, X, 9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X, + 9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X, 5, 8, 4, 5, 10, 8, 10, 11, + 8, X, X, X, X, X, X, X, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X, + 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X, 10, 11, 4, 10, 4, 5, 11, 3, + 4, 9, 4, 1, 3, 1, 4, X, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X, + 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X, 0, 2, 5, 0, 5, 9, 2, 11, + 5, 4, 5, 8, 11, 8, 5, X, 9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X, + 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X, 5, 10, 2, 5, 2, 4, 4, 2, + 0, X, X, X, X, X, X, X, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X, + 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X, 8, 4, 5, 8, 5, 3, 3, 5, + 1, X, X, X, X, X, X, X, 0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X, + 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X, 9, 4, 5, X, X, X, X, X, + X, X, X, X, X, X, X, X, 4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X, + 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X, 1, 10, 11, 1, 11, 4, 1, 4, + 0, 7, 4, 11, X, X, X, X, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X, + 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X, 9, 7, 4, 9, 11, 7, 9, 1, + 11, 2, 11, 1, 0, 8, 3, X, 11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X, + 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X, 2, 9, 10, 2, 7, 9, 2, 3, + 7, 7, 4, 9, X, X, X, X, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X, + 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X, 1, 10, 2, 8, 7, 4, X, X, + X, X, X, X, X, X, X, X, 4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X, + 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X, 4, 0, 3, 7, 4, 3, X, X, + X, X, X, X, X, X, X, X, 4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X, + 9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 11, 9, + 10, X, X, X, X, X, X, X, 0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X, + 3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X, 1, 2, 11, 1, 11, 9, 9, 11, + 8, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X, + 0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X, 3, 2, 11, X, X, X, X, X, + X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X, + 9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 0, 1, + 8, 1, 10, 8, X, X, X, X, 1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X, + 1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X, 0, 9, 1, X, X, X, X, X, + X, X, X, X, X, X, X, X, 0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X, + X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, + + // CELL_SHAPE_WEDGE = 13, 64 cases, 13 edges/case, 832 total entries + X, X, X, X, X, X, X, X, X, X, X, X, X, //0 + 0, 6, 2, X, X, X, X, X, X, X, X, X, X, //1 + 0, 1, 7, X, X, X, X, X, X, X, X, X, X, //2 + 6, 1, 7, 6, 2, 1, X, X, X, X, X, X, X, //3 + 1, 2, 8, X, X, X, X, X, X, X, X, X, X, //4 + 6, 1, 0, 6, 8, 1, X, X, X, X, X, X, X, //5 + 0, 2, 8, 7, 0, 8, X, X, X, X, X, X, X, //6 + 7, 6, 8, X, X, X, X, X, X, X, X, X, X, //7 + 3, 5, 6, X, X, X, X, X, X, X, X, X, X, //8 + 3, 5, 0, 5, 2, 0, X, X, X, X, X, X, X, //9 + 0, 1, 7, 6, 3, 5, X, X, X, X, X, X, X, //10 + 1, 7, 3, 1, 3, 5, 1, 5, 2, X, X, X, X, //11 + 2, 8, 1, 6, 3, 5, X, X, X, X, X, X, X, //12 + 0, 3, 1, 1, 3, 5, 1, 5, 8, X, X, X, X, //13 + 6, 3, 5, 0, 8, 7, 0, 2, 8, X, X, X, X, //14 + 7, 3, 5, 7, 5, 8, X, X, X, X, X, X, X, //15 + 7, 4, 3, X, X, X, X, X, X, X, X, X, X, //16 + 7, 4, 3, 0, 6, 2, X, X, X, X, X, X, X, //17 + 0, 1, 3, 1, 4, 3, X, X, X, X, X, X, X, //18 + 1, 4, 3, 1, 3, 6, 1, 6, 2, X, X, X, X, //19 + 7, 4, 3, 2, 8, 1, X, X, X, X, X, X, X, //20 + 7, 4, 3, 6, 1, 0, 6, 8, 1, X, X, X, X, //21 + 0, 4, 3, 0, 8, 4, 0, 2, 8, X, X, X, X, //22 + 6, 8, 3, 3, 8, 4, X, X, X, X, X, X, X, //23 + 6, 7, 4, 6, 4, 5, X, X, X, X, X, X, X, //24 + 0, 7, 5, 7, 4, 5, 2, 0, 5, X, X, X, X, //25 + 1, 6, 0, 1, 5, 6, 1, 4, 5, X, X, X, X, //26 + 2, 1, 5, 5, 1, 4, X, X, X, X, X, X, X, //27 + 2, 8, 1, 6, 7, 5, 7, 4, 5, X, X, X, X, //28 + 0, 7, 5, 7, 4, 5, 0, 5, 1, 1, 5, 8, X, //29 + 0, 2, 8, 0, 8, 4, 0, 4, 5, 0, 5, 6, X, //30 + 8, 4, 5, X, X, X, X, X, X, X, X, X, X, //31 + 4, 8, 5, X, X, X, X, X, X, X, X, X, X, //32 + 4, 8, 5, 0, 6, 2, X, X, X, X, X, X, X, //33 + 4, 8, 5, 0, 1, 7, X, X, X, X, X, X, X, //34 + 4, 8, 5, 6, 1, 7, 6, 2, 1, X, X, X, X, //35 + 1, 5, 4, 2, 5, 1, X, X, X, X, X, X, X, //36 + 1, 5, 4, 1, 6, 5, 1, 0, 6, X, X, X, X, //37 + 5, 4, 7, 5, 7, 0, 5, 0, 2, X, X, X, X, //38 + 6, 4, 7, 6, 5, 4, X, X, X, X, X, X, X, //39 + 6, 3, 8, 3, 4, 8, X, X, X, X, X, X, X, //40 + 0, 3, 4, 0, 4, 8, 0, 8, 2, X, X, X, X, //41 + 7, 0, 1, 6, 3, 4, 6, 4, 8, X, X, X, X, //42 + 1, 7, 3, 1, 3, 2, 2, 3, 8, 8, 3, 4, X, //43 + 2, 6, 1, 6, 3, 1, 3, 4, 1, X, X, X, X, //44 + 0, 3, 1, 1, 3, 4, X, X, X, X, X, X, X, //45 + 7, 0, 4, 4, 0, 2, 4, 2, 3, 3, 2, 6, X, //46 + 7, 3, 4, X, X, X, X, X, X, X, X, X, X, //47 + 7, 8, 5, 7, 5, 3, X, X, X, X, X, X, X, //48 + 0, 6, 2, 7, 8, 5, 7, 5, 3, X, X, X, X, //49 + 0, 1, 3, 1, 5, 3, 1, 8, 5, X, X, X, X, //50 + 2, 1, 6, 6, 1, 3, 5, 1, 8, 3, 1, 5, X, //51 + 1, 3, 7, 1, 5, 3, 1, 2, 5, X, X, X, X, //52 + 1, 0, 6, 1, 6, 5, 1, 5, 7, 7, 5, 3, X, //53 + 0, 2, 5, 0, 5, 3, X, X, X, X, X, X, X, //54 + 3, 6, 5, X, X, X, X, X, X, X, X, X, X, //55 + 7, 8, 6, X, X, X, X, X, X, X, X, X, X, //56 + 0, 7, 8, 0, 8, 2, X, X, X, X, X, X, X, //57 + 0, 1, 6, 1, 8, 6, X, X, X, X, X, X, X, //58 + 2, 1, 8, X, X, X, X, X, X, X, X, X, X, //59 + 6, 7, 1, 6, 1, 2, X, X, X, X, X, X, X, //60 + 0, 7, 1, X, X, X, X, X, X, X, X, X, X, //61 + 0, 2, 6, X, X, X, X, X, X, X, X, X, X, //62 + X, X, X, X, X, X, X, X, X, X, X, X, X, //63 + + // CELL_SHAPE_PYRAMID = 14, 32 cases, 13 edges/case, 416 total entries + X, X, X, X, X, X, X, X, X, X, X, X, X, //0 + 3, 4, 0, X, X, X, X, X, X, X, X, X, X, //1 + 5, 1, 0, X, X, X, X, X, X, X, X, X, X, //2 + 5, 1, 4, 1, 3, 4, X, X, X, X, X, X, X, //3 + 6, 2, 1, X, X, X, X, X, X, X, X, X, X, //4 + 3, 4, 0, 6, 2, 1, X, X, X, X, X, X, X, //5 + 5, 2, 0, 6, 2, 5, X, X, X, X, X, X, X, //6 + 2, 3, 4, 2, 4, 6, 4, 5, 6, X, X, X, X, //7 + 2, 7, 3, X, X, X, X, X, X, X, X, X, X, //8 + 2, 7, 4, 4, 0, 2, X, X, X, X, X, X, X, //9 + 5, 1, 0, 2, 7, 3, X, X, X, X, X, X, X, //10 + 5, 7, 4, 1, 7, 5, 2, 7, 1, X, X, X, X, //11 + 6, 3, 1, 7, 3, 6, X, X, X, X, X, X, X, //12 + 4, 6, 7, 0, 6, 4, 1, 6, 0, X, X, X, X, //13 + 7, 5, 6, 3, 5, 7, 0, 5, 3, X, X, X, X, //14 + 7, 4, 5, 7, 5, 6, X, X, X, X, X, X, X, //15 + 7, 5, 4, 7, 6, 5, X, X, X, X, X, X, X, //16 + 5, 0, 3, 6, 5, 3, 7, 6, 3, X, X, X, X, //17 + 1, 0, 4, 7, 1, 4, 6, 1, 7, X, X, X, X, //18 + 6, 1, 3, 7, 6, 3, X, X, X, X, X, X, X, //19 + 7, 5, 4, 7, 1, 5, 7, 2, 1, X, X, X, X, //20 + 3, 7, 0, 7, 5, 0, 7, 2, 5, 2, 1, 5, X, //21 + 4, 2, 0, 7, 2, 4, X, X, X, X, X, X, X, //22 + 7, 2, 3, X, X, X, X, X, X, X, X, X, X, //23 + 2, 4, 3, 5, 4, 2, 6, 5, 2, X, X, X, X, //24 + 2, 5, 0, 2, 6, 5, X, X, X, X, X, X, X, //25 + 6, 1, 0, 4, 6, 0, 3, 6, 4, 3, 2, 6, X, //26 + 2, 6, 1, X, X, X, X, X, X, X, X, X, X, //27 + 1, 4, 3, 1, 5, 4, X, X, X, X, X, X, X, //28 + 1, 5, 0, X, X, X, X, X, X, X, X, X, X, //29 + 4, 3, 0, X, X, X, X, X, X, X, X, X, X, //30 + X, X, X, X, X, X, X, X, X, X, X, X, X //31 + +#undef X +}; + +VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent TriangleTableOffset[] = { + 0, // CELL_SHAPE_EMPTY = 0, + 0, // CELL_SHAPE_VERTEX = 1, + 0, // CELL_SHAPE_POLY_VERTEX = 2, + 0, // CELL_SHAPE_LINE = 3, + 0, // CELL_SHAPE_POLY_LINE = 4, + 0, // CELL_SHAPE_TRIANGLE = 5, + 0, // CELL_SHAPE_TRIANGLE_STRIP = 6, + 0, // CELL_SHAPE_POLYGON = 7, + 0, // CELL_SHAPE_PIXEL = 8, + 0, // CELL_SHAPE_QUAD = 9, + 0, // CELL_SHAPE_TETRA = 10, + 0, // CELL_SHAPE_VOXEL = 11, + 112, // CELL_SHAPE_HEXAHEDRON = 12, + 112+4096, // CELL_SHAPE_WEDGE = 13, + 112+4096+832, // CELL_SHAPE_PYRAMID = 14, +}; + +// clang-format on +class CellClassifyTable : public vtkm::cont::ExecutionObjectBase +{ +public: + template + class ExecObject + { + public: + VTKM_EXEC + vtkm::IdComponent GetNumVerticesPerCell(vtkm::Id shape) const + { + return this->NumVerticesPerCellPortal.Get(shape); + } + + VTKM_EXEC + vtkm::IdComponent GetNumTriangles(vtkm::Id shape, vtkm::IdComponent caseNumber) const + { + vtkm::IdComponent offset = this->NumTrianglesTableOffsetPortal.Get(shape); + return this->NumTrianglesTablePortal.Get(offset + caseNumber); + } + + private: + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + NumVerticesPerCellPortal; + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + NumTrianglesTablePortal; + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + NumTrianglesTableOffsetPortal; + + friend class CellClassifyTable; + }; + + CellClassifyTable() + : NumVerticesPerCellArray( + vtkm::cont::make_ArrayHandle(NumVerticesPerCellTable, vtkm::NUMBER_OF_CELL_SHAPES)) + , NumTrianglesTableOffsetArray( + vtkm::cont::make_ArrayHandle(NumTrianglesTableOffset, vtkm::NUMBER_OF_CELL_SHAPES)) + , NumTrianglesTableArray( + vtkm::cont::make_ArrayHandle(NumTrianglesTable, + sizeof(NumTrianglesTable) / sizeof(NumTrianglesTable[0]))) + { + } + + template + ExecObject PrepareForExecution(DeviceAdapter) + { + ExecObject execObject; + execObject.NumVerticesPerCellPortal = + this->NumVerticesPerCellArray.PrepareForInput(DeviceAdapter()); + execObject.NumTrianglesTableOffsetPortal = + this->NumTrianglesTableOffsetArray.PrepareForInput(DeviceAdapter()); + execObject.NumTrianglesTablePortal = + this->NumTrianglesTableArray.PrepareForInput(DeviceAdapter()); + return execObject; + } + +private: + vtkm::cont::ArrayHandle NumVerticesPerCellArray; + vtkm::cont::ArrayHandle NumTrianglesTableOffsetArray; + vtkm::cont::ArrayHandle NumTrianglesTableArray; +}; + +class TriangleGenerationTable : public vtkm::cont::ExecutionObjectBase +{ +public: + template + class ExecObject + { + public: + VTKM_EXEC + vtkm::Pair GetEdgeVertices( + vtkm::Id shape, + vtkm::IdComponent caseNumber, + vtkm::IdComponent triangleNumber, + vtkm::IdComponent vertexNumber) const + { + VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumEntriesPerCase[] = { + 0, // CELL_SHAPE_EMPTY = 0, + 0, // CELL_SHAPE_VERTEX = 1, + 0, // CELL_SHAPE_POLY_VERTEX = 2, + 0, // CELL_SHAPE_LINE = 3, + 0, // CELL_SHAPE_POLY_LINE = 4, + 0, // CELL_SHAPE_TRIANGLE = 5, + 0, // CELL_SHAPE_TRIANGLE_STRIP = 6, + 0, // CELL_SHAPE_POLYGON = 7, + 0, // CELL_SHAPE_PIXEL = 8, + 0, // CELL_SHAPE_QUAD = 9, + 7, // CELL_SHAPE_TETRA = 10, + 0, // CELL_SHAPE_VOXEL = 11, + 16, // CELL_SHAPE_HEXAHEDRON = 12, + 13, // CELL_SHAPE_WEDGE = 13, + 13, // CELL_SHAPE_PYRAMID = 14, + }; + + vtkm::IdComponent triOffset = TriangleTableOffsetPortal.Get(shape) + + NumEntriesPerCase[shape] * caseNumber + triangleNumber * 3; + vtkm::IdComponent edgeIndex = TriangleTablePortal.Get(triOffset + vertexNumber); + vtkm::IdComponent edgeOffset = EdgeTableOffsetPortal.Get(shape); + + return { EdgeTablePortal.Get(edgeOffset + edgeIndex * 2 + 0), + EdgeTablePortal.Get(edgeOffset + edgeIndex * 2 + 1) }; + } + + private: + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + EdgeTablePortal; + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + EdgeTableOffsetPortal; + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + TriangleTablePortal; + typename vtkm::cont::ArrayHandle::ExecutionTypes::PortalConst + TriangleTableOffsetPortal; + friend class TriangleGenerationTable; + }; + + template + ExecObject PrepareForExecution(DeviceAdapter) + { + ExecObject execObject; + execObject.EdgeTablePortal = this->EdgeTableArray.PrepareForInput(DeviceAdapter()); + execObject.EdgeTableOffsetPortal = this->EdgeTableOffsetArray.PrepareForInput(DeviceAdapter()); + execObject.TriangleTablePortal = this->TriangleTableArray.PrepareForInput(DeviceAdapter()); + execObject.TriangleTableOffsetPortal = + this->TriangleTableOffsetArray.PrepareForInput(DeviceAdapter()); + return execObject; + } + + TriangleGenerationTable() + : EdgeTableArray( + vtkm::cont::make_ArrayHandle(EdgeTable, sizeof(EdgeTable) / sizeof(EdgeTable[0]))) + , EdgeTableOffsetArray( + vtkm::cont::make_ArrayHandle(EdgeTableOffset, + sizeof(EdgeTableOffset) / sizeof(EdgeTableOffset[0]))) + , TriangleTableArray( + vtkm::cont::make_ArrayHandle(TriangleTable, + sizeof(TriangleTable) / sizeof(TriangleTable[0]))) + , TriangleTableOffsetArray( + vtkm::cont::make_ArrayHandle(TriangleTableOffset, + sizeof(TriangleTableOffset) / sizeof(TriangleTableOffset[0]))) + { + } + +private: + vtkm::cont::ArrayHandle EdgeTableArray; + vtkm::cont::ArrayHandle EdgeTableOffsetArray; + vtkm::cont::ArrayHandle TriangleTableArray; + vtkm::cont::ArrayHandle TriangleTableOffsetArray; +}; +} +} +} +#endif // vtk_m_ContourTable_h diff --git a/vtkm/worklet/contour/DataTables.h b/vtkm/worklet/contour/DataTables.h deleted file mode 100644 index 97dfaed66..000000000 --- a/vtkm/worklet/contour/DataTables.h +++ /dev/null @@ -1,212 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ - -#include - -namespace vtkm -{ -namespace worklet -{ - -namespace internal -{ - -const vtkm::IdComponent edgeTable[24] = { 0, 1, 1, 2, 3, 2, 0, 3, 4, 5, 5, 6, - 7, 6, 4, 7, 0, 4, 1, 5, 2, 6, 3, 7 }; - -const vtkm::IdComponent numTrianglesTable[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, - 2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, 3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2, 3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1, - 3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0, -}; - -const vtkm::IdComponent triTable[256 * 16] = { -#define X -1 - X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 8, 3, X, X, X, X, X, - X, X, X, X, X, X, X, X, 0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X, - 1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, X, X, X, X, X, - X, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X, - 9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X, 2, 8, 3, 2, 10, 8, 10, 9, - 8, X, X, X, X, X, X, X, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X, - 0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 11, X, X, - X, X, X, X, X, X, X, X, 1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X, - 3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X, 0, 10, 1, 0, 8, 10, 8, 11, - 10, X, X, X, X, X, X, X, 3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X, - 9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X, 4, 7, 8, X, X, X, X, X, - X, X, X, X, X, X, X, X, 4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X, - 0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, 4, 1, 9, 4, 7, 1, 7, 3, - 1, X, X, X, X, X, X, X, 1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, - 3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X, 9, 2, 10, 9, 0, 2, 8, 4, - 7, X, X, X, X, X, X, X, 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X, - 8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, 11, 4, 7, 11, 2, 4, 2, 0, - 4, X, X, X, X, X, X, X, 9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X, - 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X, 3, 10, 1, 3, 11, 10, 7, 8, - 4, X, X, X, X, X, X, X, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X, - 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X, 4, 7, 11, 4, 11, 9, 9, 11, - 10, X, X, X, X, X, X, X, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X, - 9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X, 0, 5, 4, 1, 5, 0, X, X, - X, X, X, X, X, X, X, X, 8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X, - 1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 10, 4, 9, - 5, X, X, X, X, X, X, X, 5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X, - 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X, 9, 5, 4, 2, 3, 11, X, X, - X, X, X, X, X, X, X, X, 0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X, - 0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X, 2, 1, 5, 2, 5, 8, 2, 8, - 11, 4, 8, 5, X, X, X, X, 10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X, - 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X, 5, 4, 0, 5, 0, 11, 5, 11, - 10, 11, 0, 3, X, X, X, X, 5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, - 9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X, 9, 3, 0, 9, 5, 3, 5, 7, - 3, X, X, X, X, X, X, X, 0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X, - 1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X, 9, 7, 8, 9, 5, 7, 10, 1, - 2, X, X, X, X, X, X, X, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X, - 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X, 2, 10, 5, 2, 5, 3, 3, 5, - 7, X, X, X, X, X, X, X, 7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X, - 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X, 2, 3, 11, 0, 1, 8, 1, 7, - 8, 1, 5, 7, X, X, X, X, 11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X, - 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X, 5, 7, 0, 5, 0, 9, 7, 11, - 0, 1, 0, 10, 11, 10, 0, X, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X, - 11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X, 10, 6, 5, X, X, X, X, X, - X, X, X, X, X, X, X, X, 0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, - 9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, 1, 8, 3, 1, 9, 8, 5, 10, - 6, X, X, X, X, X, X, X, 1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X, - 1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X, 9, 6, 5, 9, 0, 6, 0, 2, - 6, X, X, X, X, X, X, X, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X, - 2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X, 11, 0, 8, 11, 2, 0, 10, 6, - 5, X, X, X, X, X, X, X, 0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X, - 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X, 6, 3, 11, 6, 5, 3, 5, 1, - 3, X, X, X, X, X, X, X, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X, - 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X, 6, 5, 9, 6, 9, 11, 11, 9, - 8, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X, - 4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X, 1, 9, 0, 5, 10, 6, 8, 4, - 7, X, X, X, X, X, X, X, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X, - 6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X, 1, 2, 5, 5, 2, 6, 3, 0, - 4, 3, 4, 7, X, X, X, X, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X, - 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X, 3, 11, 2, 7, 8, 4, 10, 6, - 5, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X, - 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X, 9, 2, 1, 9, 11, 2, 9, 4, - 11, 7, 11, 4, 5, 10, 6, X, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X, - 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X, 0, 5, 9, 0, 6, 5, 0, 3, - 6, 11, 6, 3, 8, 4, 7, X, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X, - 10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X, 4, 10, 6, 4, 9, 10, 0, 8, - 3, X, X, X, X, X, X, X, 10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X, - 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X, 1, 4, 9, 1, 2, 4, 2, 6, - 4, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X, - 0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X, 8, 3, 2, 8, 2, 4, 4, 2, - 6, X, X, X, X, X, X, X, 10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X, - 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X, 3, 11, 2, 0, 1, 6, 0, 6, - 4, 6, 1, 10, X, X, X, X, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X, - 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X, 8, 11, 1, 8, 1, 0, 11, 6, - 1, 9, 1, 4, 6, 4, 1, X, 3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X, - 6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X, 7, 10, 6, 7, 8, 10, 8, 9, - 10, X, X, X, X, X, X, X, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X, - 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X, 10, 6, 7, 10, 7, 1, 1, 7, - 3, X, X, X, X, X, X, X, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X, - 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X, 7, 8, 0, 7, 0, 6, 6, 0, - 2, X, X, X, X, X, X, X, 7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X, - 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X, 2, 0, 7, 2, 7, 11, 0, 9, - 7, 6, 7, 10, 9, 10, 7, X, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X, - 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X, 8, 9, 6, 8, 6, 7, 9, 1, - 6, 11, 6, 3, 1, 3, 6, X, 0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X, - 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X, 7, 11, 6, X, X, X, X, X, - X, X, X, X, X, X, X, X, 7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X, - 3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X, 0, 1, 9, 11, 7, 6, X, X, - X, X, X, X, X, X, X, X, 8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X, - 10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 8, 6, 11, - 7, X, X, X, X, X, X, X, 2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X, - 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X, 7, 2, 3, 6, 2, 7, X, X, - X, X, X, X, X, X, X, X, 7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X, - 2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X, 1, 6, 2, 1, 8, 6, 1, 9, - 8, 8, 7, 6, X, X, X, X, 10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X, - 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X, 0, 3, 7, 0, 7, 10, 0, 10, - 9, 6, 10, 7, X, X, X, X, 7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X, - 6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X, 3, 6, 11, 3, 0, 6, 0, 4, - 6, X, X, X, X, X, X, X, 8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X, - 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X, 6, 8, 4, 6, 11, 8, 2, 10, - 1, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X, - 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X, 10, 9, 3, 10, 3, 2, 9, 4, - 3, 11, 3, 6, 4, 6, 3, X, 8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, - 0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 4, 2, 4, - 6, 4, 3, 8, X, X, X, X, 1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X, - 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X, 10, 1, 0, 10, 0, 6, 6, 0, - 4, X, X, X, X, X, X, X, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X, - 10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X, 4, 9, 5, 7, 6, 11, X, X, - X, X, X, X, X, X, X, X, 0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X, - 5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X, 11, 7, 6, 8, 3, 4, 3, 5, - 4, 3, 1, 5, X, X, X, X, 9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X, - 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X, 7, 6, 11, 5, 4, 10, 4, 2, - 10, 4, 0, 2, X, X, X, X, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X, - 7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X, 9, 5, 4, 0, 8, 6, 0, 6, - 2, 6, 8, 7, X, X, X, X, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X, - 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X, 9, 5, 4, 10, 1, 6, 1, 7, - 6, 1, 3, 7, X, X, X, X, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X, - 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X, 7, 6, 10, 7, 10, 8, 5, 4, - 10, 4, 8, 10, X, X, X, X, 6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X, - 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X, 0, 11, 8, 0, 5, 11, 0, 1, - 5, 5, 6, 11, X, X, X, X, 6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X, - 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X, 0, 11, 3, 0, 6, 11, 0, 9, - 6, 5, 6, 9, 1, 2, 10, X, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X, - 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X, 5, 8, 9, 5, 2, 8, 5, 6, - 2, 3, 8, 2, X, X, X, X, 9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X, - 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X, 1, 5, 6, 2, 1, 6, X, X, - X, X, X, X, X, X, X, X, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X, - 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X, 0, 3, 8, 5, 6, 10, X, X, - X, X, X, X, X, X, X, X, 10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X, - 11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X, 11, 5, 10, 11, 7, 5, 8, 3, - 0, X, X, X, X, X, X, X, 5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X, - 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X, 11, 1, 2, 11, 7, 1, 7, 5, - 1, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X, - 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X, 7, 5, 2, 7, 2, 11, 5, 9, - 2, 3, 2, 8, 9, 8, 2, X, 2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, - 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X, 9, 0, 1, 5, 10, 3, 5, 3, - 7, 3, 10, 2, X, X, X, X, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X, - 1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X, 0, 8, 7, 0, 7, 1, 1, 7, - 5, X, X, X, X, X, X, X, 9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X, - 9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X, 5, 8, 4, 5, 10, 8, 10, 11, - 8, X, X, X, X, X, X, X, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X, - 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X, 10, 11, 4, 10, 4, 5, 11, 3, - 4, 9, 4, 1, 3, 1, 4, X, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X, - 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X, 0, 2, 5, 0, 5, 9, 2, 11, - 5, 4, 5, 8, 11, 8, 5, X, 9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X, - 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X, 5, 10, 2, 5, 2, 4, 4, 2, - 0, X, X, X, X, X, X, X, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X, - 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X, 8, 4, 5, 8, 5, 3, 3, 5, - 1, X, X, X, X, X, X, X, 0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X, - 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X, 9, 4, 5, X, X, X, X, X, - X, X, X, X, X, X, X, X, 4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X, - 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X, 1, 10, 11, 1, 11, 4, 1, 4, - 0, 7, 4, 11, X, X, X, X, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X, - 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X, 9, 7, 4, 9, 11, 7, 9, 1, - 11, 2, 11, 1, 0, 8, 3, X, 11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X, - 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X, 2, 9, 10, 2, 7, 9, 2, 3, - 7, 7, 4, 9, X, X, X, X, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X, - 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X, 1, 10, 2, 8, 7, 4, X, X, - X, X, X, X, X, X, X, X, 4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X, - 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X, 4, 0, 3, 7, 4, 3, X, X, - X, X, X, X, X, X, X, X, 4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X, - 9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 11, 9, - 10, X, X, X, X, X, X, X, 0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X, - 3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X, 1, 2, 11, 1, 11, 9, 9, 11, - 8, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X, - 0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X, 3, 2, 11, X, X, X, X, X, - X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X, - 9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 0, 1, - 8, 1, 10, 8, X, X, X, X, 1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X, - 1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X, 0, 9, 1, X, X, X, X, X, - X, X, X, X, X, X, X, X, 0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X, - X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X -#undef X -}; -} -} -} diff --git a/vtkm/worklet/testing/CMakeLists.txt b/vtkm/worklet/testing/CMakeLists.txt index 6514b2e67..cb4af763a 100644 --- a/vtkm/worklet/testing/CMakeLists.txt +++ b/vtkm/worklet/testing/CMakeLists.txt @@ -18,6 +18,7 @@ set(unit_tests UnitTestCellSetDualGraph.cxx UnitTestCellMeasure.cxx UnitTestClipping.cxx + UnitTestContour.cxx UnitTestContourTreeUniform.cxx UnitTestContourTreeUniformAugmented.cxx UnitTestCoordinateSystemTransform.cxx @@ -36,7 +37,6 @@ set(unit_tests UnitTestKdTreeBuildNNS.cxx UnitTestKeys.cxx UnitTestMagnitude.cxx - UnitTestMarchingCubes.cxx UnitTestMask.cxx UnitTestMaskIndices.cxx UnitTestMaskPoints.cxx diff --git a/vtkm/worklet/testing/UnitTestCellSetConnectivity.cxx b/vtkm/worklet/testing/UnitTestCellSetConnectivity.cxx index d47ee0a0d..8784cd92a 100644 --- a/vtkm/worklet/testing/UnitTestCellSetConnectivity.cxx +++ b/vtkm/worklet/testing/UnitTestCellSetConnectivity.cxx @@ -7,7 +7,7 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ -#include +#include #include @@ -117,7 +117,7 @@ public: vtkm::Id3 dims(4, 4, 4); vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims); - vtkm::filter::MarchingCubes filter; + vtkm::filter::Contour filter; filter.SetGenerateNormals(true); filter.SetMergeDuplicatePoints(true); filter.SetIsoValue(0, 0.1); diff --git a/vtkm/worklet/testing/UnitTestCellSetDualGraph.cxx b/vtkm/worklet/testing/UnitTestCellSetDualGraph.cxx index 0bb37e148..7c7ae7981 100644 --- a/vtkm/worklet/testing/UnitTestCellSetDualGraph.cxx +++ b/vtkm/worklet/testing/UnitTestCellSetDualGraph.cxx @@ -9,7 +9,7 @@ //============================================================================ #include #include -#include +#include #include diff --git a/vtkm/worklet/testing/UnitTestMarchingCubes.cxx b/vtkm/worklet/testing/UnitTestContour.cxx similarity index 80% rename from vtkm/worklet/testing/UnitTestMarchingCubes.cxx rename to vtkm/worklet/testing/UnitTestContour.cxx index d7fc11448..bdf8c4482 100644 --- a/vtkm/worklet/testing/UnitTestMarchingCubes.cxx +++ b/vtkm/worklet/testing/UnitTestContour.cxx @@ -15,8 +15,10 @@ #include #include +#include +#include +#include #include -#include namespace vtkm_ut_mc_worklet { @@ -272,9 +274,9 @@ inline vtkm::cont::DataSet MakeRadiantDataSet::Make3DRadiantDataSet(vtkm::IdComp } // vtkm_ut_mc_worklet namespace -void TestMarchingCubesUniformGrid() +void TestContourUniformGrid() { - std::cout << "Testing MarchingCubes worklet on a uniform grid" << std::endl; + std::cout << "Testing Contour worklet on a uniform grid" << std::endl; vtkm::Id3 dims(4, 4, 4); vtkm::cont::DataSet dataSet = vtkm_ut_mc_worklet::MakeIsosurfaceTestDataSet(dims); @@ -286,7 +288,7 @@ void TestMarchingCubesUniformGrid() vtkm::cont::ArrayHandle cellFieldArray; dataSet.GetField("cellvar").GetData().CopyTo(cellFieldArray); - vtkm::worklet::MarchingCubes isosurfaceFilter; + vtkm::worklet::Contour isosurfaceFilter; isosurfaceFilter.SetMergeDuplicatePoints(false); vtkm::Float32 contourValue = 0.5f; @@ -327,9 +329,9 @@ void TestMarchingCubesUniformGrid() "Wrong result for Isosurface filter"); } -void TestMarchingCubesExplicit() +void TestContourExplicit() { - std::cout << "Testing MarchingCubes worklet on explicit data" << std::endl; + std::cout << "Testing Contour worklet on explicit data" << std::endl; using DataSetGenerator = vtkm_ut_mc_worklet::MakeRadiantDataSet; using Vec3Handle = vtkm::cont::ArrayHandle; @@ -351,10 +353,10 @@ void TestMarchingCubesExplicit() Vec3Handle vertices; Vec3Handle normals; - vtkm::worklet::MarchingCubes marchingCubes; - marchingCubes.SetMergeDuplicatePoints(false); + vtkm::worklet::Contour Contour; + Contour.SetMergeDuplicatePoints(false); - auto result = marchingCubes.Run( + auto result = Contour.Run( &contourValue, 1, cellSet, dataSet.GetCoordinateSystem(), contourArray, vertices, normals); DataHandle scalars; @@ -364,13 +366,13 @@ void TestMarchingCubesExplicit() DataSetGenerator::DataArrayHandle projectedArray; projectedField.GetData().CopyTo(projectedArray); - scalars = marchingCubes.ProcessPointField(projectedArray); + scalars = Contour.ProcessPointField(projectedArray); vtkm::cont::ArrayHandle cellFieldArray; dataSet.GetField("cellvar").GetData().CopyTo(cellFieldArray); vtkm::cont::ArrayHandle cellFieldArrayOut; - cellFieldArrayOut = marchingCubes.ProcessCellField(cellFieldArray); + cellFieldArrayOut = Contour.ProcessCellField(cellFieldArray); std::cout << "vertices: "; vtkm::cont::printSummary_ArrayHandle(vertices, std::cout); @@ -388,20 +390,75 @@ void TestMarchingCubesExplicit() VTKM_TEST_ASSERT(result.GetNumberOfCells() == cellFieldArrayOut.GetNumberOfValues(), "Output cell data invalid"); VTKM_TEST_ASSERT(test_equal(vertices.GetNumberOfValues(), 2472), - "Wrong vertices result for MarchingCubes worklet"); + "Wrong vertices result for Contour worklet"); VTKM_TEST_ASSERT(test_equal(normals.GetNumberOfValues(), 2472), - "Wrong normals result for MarchingCubes worklet"); + "Wrong normals result for Contour worklet"); VTKM_TEST_ASSERT(test_equal(scalars.GetNumberOfValues(), 2472), - "Wrong scalars result for MarchingCubes worklet"); + "Wrong scalars result for Contour worklet"); } -void TestMarchingCubes() +void TestContourClipped() { - TestMarchingCubesUniformGrid(); - TestMarchingCubesExplicit(); + std::cout << "Testing Contour worklet on a clipped uniform grid" << std::endl; + + vtkm::Id3 dims(4, 4, 4); + vtkm::cont::DataSet dataSet = vtkm_ut_mc_worklet::MakeIsosurfaceTestDataSet(dims); + + vtkm::Plane plane(vtkm::make_Vec(0.5, 0.5, 0.5), vtkm::make_Vec(1, 1, 1)); + vtkm::filter::ClipWithImplicitFunction clip; + clip.SetImplicitFunction(vtkm::cont::make_ImplicitFunctionHandle(plane)); + vtkm::cont::DataSet clipped = clip.Execute(dataSet); + + vtkm::cont::CellSetExplicit<> cellSet; + clipped.GetCellSet().CopyTo(cellSet); + vtkm::cont::ArrayHandle pointFieldArray; + clipped.GetField("nodevar").GetData().CopyTo(pointFieldArray); + vtkm::cont::ArrayHandle cellFieldArray; + clipped.GetField("cellvar").GetData().CopyTo(cellFieldArray); + + vtkm::Float32 contourValue = 0.5f; + vtkm::cont::ArrayHandle verticesArray; + vtkm::cont::ArrayHandle normalsArray; + vtkm::cont::ArrayHandle scalarsArray; + + vtkm::worklet::Contour isosurfaceFilter; + isosurfaceFilter.SetMergeDuplicatePoints(false); + + auto result = isosurfaceFilter.Run(&contourValue, + 1, + cellSet, + clipped.GetCoordinateSystem(), + pointFieldArray, + verticesArray, + normalsArray); + + scalarsArray = isosurfaceFilter.ProcessPointField(pointFieldArray); + + vtkm::cont::ArrayHandle cellFieldArrayOut; + cellFieldArrayOut = isosurfaceFilter.ProcessCellField(cellFieldArray); + + std::cout << "vertices: "; + vtkm::cont::printSummary_ArrayHandle(verticesArray, std::cout); + std::cout << std::endl; + std::cout << "normals: "; + vtkm::cont::printSummary_ArrayHandle(normalsArray, std::cout); + std::cout << std::endl; + std::cout << "scalars: "; + vtkm::cont::printSummary_ArrayHandle(scalarsArray, std::cout); + std::cout << std::endl; + std::cout << "cell field: "; + vtkm::cont::printSummary_ArrayHandle(cellFieldArrayOut, std::cout); + std::cout << std::endl; } -int UnitTestMarchingCubes(int argc, char* argv[]) +void TestContour() { - return vtkm::cont::testing::Testing::Run(TestMarchingCubes, argc, argv); + TestContourUniformGrid(); + TestContourExplicit(); + TestContourClipped(); +} + +int UnitTestContour(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(TestContour, argc, argv); } diff --git a/vtkm/worklet/testing/UnitTestImageConnectivity.cxx b/vtkm/worklet/testing/UnitTestImageConnectivity.cxx index 1b6b72cd1..b70e399f0 100644 --- a/vtkm/worklet/testing/UnitTestImageConnectivity.cxx +++ b/vtkm/worklet/testing/UnitTestImageConnectivity.cxx @@ -9,7 +9,7 @@ //============================================================================ #include #include -#include +#include #include diff --git a/vtkm/worklet/testing/UnitTestOrientNormals.cxx b/vtkm/worklet/testing/UnitTestOrientNormals.cxx index 3b99a7a50..34c0dc8a8 100644 --- a/vtkm/worklet/testing/UnitTestOrientNormals.cxx +++ b/vtkm/worklet/testing/UnitTestOrientNormals.cxx @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include @@ -66,7 +66,7 @@ vtkm::cont::DataSet CreateDataSet(bool pointNormals, bool cellNormals) auto dataSet = wavelet.GenerateDataSet(); // Cut a contour - vtkm::filter::MarchingCubes contour; + vtkm::filter::Contour contour; contour.SetActiveField("scalars", vtkm::cont::Field::Association::POINTS); contour.SetNumberOfIsoValues(1); contour.SetIsoValue(192); diff --git a/vtkm/worklet/testing/UnitTestPointGradient.cxx b/vtkm/worklet/testing/UnitTestPointGradient.cxx index 88be96ed2..8b0c471ac 100644 --- a/vtkm/worklet/testing/UnitTestPointGradient.cxx +++ b/vtkm/worklet/testing/UnitTestPointGradient.cxx @@ -182,12 +182,12 @@ void TestPointGradientUniform3DWithVectorField2() } } -void TestPointGradientExplicit() +void TestPointGradientExplicit3D() { - std::cout << "Testing PointGradient Worklet on Explicit data" << std::endl; + std::cout << "Testing PointGradient Worklet on Explicit 3D data" << std::endl; vtkm::cont::testing::MakeTestDataSet testDataSet; - vtkm::cont::DataSet dataSet = testDataSet.Make3DExplicitDataSet0(); + vtkm::cont::DataSet dataSet = testDataSet.Make3DExplicitDataSet5(); vtkm::cont::ArrayHandle fieldArray; dataSet.GetField("pointvar").GetData().CopyTo(fieldArray); @@ -195,21 +195,59 @@ void TestPointGradientExplicit() vtkm::worklet::PointGradient gradient; auto result = gradient.Run(dataSet.GetCellSet(), dataSet.GetCoordinateSystem(), fieldArray); - vtkm::Vec3f_32 expected[2] = { { 10.f, 10.1f, 0.0f }, { 10.f, 10.1f, 0.0f } }; - for (int i = 0; i < 2; ++i) + //vtkm::cont::printSummary_ArrayHandle(result, std::cout, true); + const int nVerts = 11; + vtkm::Vec3f_32 expected[nVerts] = { + { 10.0f, 40.2f, 30.1f }, { 27.4f, 40.1f, 10.1f }, { 17.425f, 40.0f, 10.1f }, + { -10.0f, 40.1f, 30.1f }, { 9.9f, -0.0500011f, 30.0f }, { 16.2125f, -4.55f, 10.0f }, + { 6.2f, -4.6f, 10.0f }, { -10.1f, -0.0999985f, 30.0f }, { 22.5125f, -4.575f, 10.025f }, + { 1.0f, -40.3f, 30.0f }, { 0.6f, -49.2f, 10.0f } + }; + for (int i = 0; i < nVerts; ++i) { VTKM_TEST_ASSERT(test_equal(result.GetPortalConstControl().Get(i), expected[i]), "Wrong result for PointGradient worklet on 3D explicit data"); } } +void TestPointGradientExplicit2D() +{ + std::cout << "Testing PointGradient Worklet on Explicit 3D data" << std::endl; + + vtkm::cont::testing::MakeTestDataSet testDataSet; + vtkm::cont::DataSet dataSet = testDataSet.Make2DExplicitDataSet0(); + + vtkm::cont::ArrayHandle fieldArray; + dataSet.GetField("pointvar").GetData().CopyTo(fieldArray); + + vtkm::worklet::PointGradient gradient; + auto result = gradient.Run(dataSet.GetCellSet(), dataSet.GetCoordinateSystem(), fieldArray); + + //vtkm::cont::printSummary_ArrayHandle(result, std::cout, true); + const int nVerts = 16; + vtkm::Vec3f_32 expected[nVerts] = { { -22.0f, -7.0f, 0.0f }, { -25.5f, -7.0f, 0.0f }, + { -30.5f, 7.0f, 0.0f }, { -32.0f, 16.0f, 0.0f }, + { -23.0f, -42.0f, 0.0f }, { -23.25f, -17.0f, 0.0f }, + { -20.6667f, 1.33333f, 0.0f }, { -23.0f, 14.0f, 0.0f }, + { -8.0f, -42.0f, 0.0f }, { 1.33333f, -19.7222f, 0.0f }, + { -6.2963f, -4.03704f, 0.0f }, { -5.0f, 12.0f, 0.0f }, + { 22.5556f, -13.4444f, 0.0f }, { -19.8889f, 59.1111f, 0.0f }, + { 22.5556f, 15.4444f, 0.0f }, { 45.0f, 26.6667f, 0.0f } }; + for (int i = 0; i < nVerts; ++i) + { + VTKM_TEST_ASSERT(test_equal(result.GetPortalConstControl().Get(i), expected[i]), + "Wrong result for PointGradient worklet on 2D explicit data"); + } +} + void TestPointGradient() { TestPointGradientUniform2D(); TestPointGradientUniform3D(); TestPointGradientUniform3DWithVectorField(); TestPointGradientUniform3DWithVectorField2(); - TestPointGradientExplicit(); + TestPointGradientExplicit2D(); + TestPointGradientExplicit3D(); } } diff --git a/vtkm/worklet/tetrahedralize/TetrahedralizeExplicit.h b/vtkm/worklet/tetrahedralize/TetrahedralizeExplicit.h index ac5e5f447..d03a85e83 100644 --- a/vtkm/worklet/tetrahedralize/TetrahedralizeExplicit.h +++ b/vtkm/worklet/tetrahedralize/TetrahedralizeExplicit.h @@ -110,39 +110,38 @@ public: return outCellSet; } + + vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetExplicit<>& cellSet, + vtkm::cont::ArrayHandle& outCellsPerCell) + { + vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName()); + + // Input topology + auto inShapes = + cellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); + auto inNumIndices = + cellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); + + // Output topology + vtkm::cont::ArrayHandle outConnectivity; + + vtkm::worklet::internal::TetrahedralizeTables tables; + + // Determine the number of output cells each input cell will generate + vtkm::worklet::DispatcherMapField tetPerCellDispatcher; + tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell); + + // Build new cells + vtkm::worklet::DispatcherMapTopology tetrahedralizeDispatcher( + TetrahedralizeCell::MakeScatter(outCellsPerCell)); + tetrahedralizeDispatcher.Invoke( + cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity)); + + // Add cells to output cellset + outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity); + return outCellSet; + } }; -template <> -vtkm::cont::CellSetSingleType<> TetrahedralizeExplicit::Run( - const vtkm::cont::CellSetExplicit<>& cellSet, - vtkm::cont::ArrayHandle& outCellsPerCell) -{ - vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName()); - - // Input topology - auto inShapes = - cellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); - auto inNumIndices = - cellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint()); - - // Output topology - vtkm::cont::ArrayHandle outConnectivity; - - vtkm::worklet::internal::TetrahedralizeTables tables; - - // Determine the number of output cells each input cell will generate - vtkm::worklet::DispatcherMapField tetPerCellDispatcher; - tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell); - - // Build new cells - vtkm::worklet::DispatcherMapTopology tetrahedralizeDispatcher( - TetrahedralizeCell::MakeScatter(outCellsPerCell)); - tetrahedralizeDispatcher.Invoke( - cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity)); - - // Add cells to output cellset - outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity); - return outCellSet; -} } } // namespace vtkm::worklet