diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e9c796e90..519d1e97e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -164,8 +164,9 @@ stages: interruptible: true before_script: - *install_cmake - - .gitlab/ci/config/sccache.sh + - "cmake -VV -P .gitlab/ci/config/ninja.cmake" - export PATH=$PWD/.gitlab:$PATH + - .gitlab/ci/config/sccache.sh - SCCACHE_IDLE_TIMEOUT=0 sccache --start-server - sccache --show-stats - .gitlab/ci/config/google_benchmarks.sh @@ -185,6 +186,8 @@ stages: interruptible: true before_script: - *install_cmake + - "cmake -VV -P .gitlab/ci/config/ninja.cmake" + - export PATH=$PWD/.gitlab:$PATH script: - "ctest $CTEST_TIMEOUT -VV -S .gitlab/ci/ctest_test.cmake" extends: diff --git a/.gitlab/ci/config/ccache.cmake b/.gitlab/ci/config/ccache.cmake new file mode 100644 index 000000000..375bfce3c --- /dev/null +++ b/.gitlab/ci/config/ccache.cmake @@ -0,0 +1,61 @@ +##============================================================================ +## 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. +##============================================================================ + +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +set(version 4.6.1) +set(arch x86_64) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(sha256sum da1e1781bc1c4b019216fa16391af3e1daaee7e7f49a8ec9b0cdc8a1d05c50e2) + set(base_url https://github.com/ccache/ccache/releases/download) + set(platform linux) + set(extension tar.xz) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(sha256sum 3e36ba8c80fbf7f2b95fe0227b9dd1ca6143d721aab052caf0d5729769138059) + set(full_url https://gitlab.kitware.com/utils/ci-utilities/-/package_files/534/download) + set(filename ccache) + set(extension tar.gz) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(sha256sum a6c6311973aa3d2aae22424895f2f968e5d661be003b25f1bd854a5c0cd57563) + set(base_url https://github.com/ccache/ccache/releases/download) + set(platform windows) + set(extension zip) +else() + message(FATAL_ERROR "Unrecognized platform ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +if(NOT DEFINED filename) + set(filename "ccache-${version}-${platform}-${arch}") +endif() + +set(tarball "${filename}.${extension}") + +if(NOT DEFINED full_url) + set(full_url "${base_url}/v${version}/${tarball}") +endif() + +file(DOWNLOAD + "${full_url}" .gitlab/${tarball} + EXPECTED_HASH SHA256=${sha256sum} + SHOW_PROGRESS + ) + +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xf ${tarball} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.gitlab + RESULT_VARIABLE extract_results + ) + +if(extract_results) + message(FATAL_ERROR "Extracting `${tarball}` failed: ${extract_results}.") +endif() + +file(RENAME .gitlab/${filename} .gitlab/ccache) diff --git a/.gitlab/ci/config/ninja.cmake b/.gitlab/ci/config/ninja.cmake new file mode 100644 index 000000000..8d7d141c8 --- /dev/null +++ b/.gitlab/ci/config/ninja.cmake @@ -0,0 +1,44 @@ +##============================================================================ +## Copyright (c) Kitware, Inc. +## All rights reserved. +## See LICENSE.txt for details. +## +## This software is distributed WITHOUT ANY WARRANTY; without even +## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the above copyright notice for more information. +##============================================================================ + +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +set(version 1.11.0) + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") + set(sha256sum 9726e730d5b8599f82654dc80265e64a10a8a817552c34153361ed0c017f9f02) + set(platform linux) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + set(sha256sum 21915277db59756bfc61f6f281c1f5e3897760b63776fd3d360f77dd7364137f) + set(platform mac) +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + set(sha256sum d0ee3da143211aa447e750085876c9b9d7bcdd637ab5b2c5b41349c617f22f3b) + set(platform win) +else() + message(FATAL_ERROR "Unrecognized platform ${CMAKE_HOST_SYSTEM_NAME}") +endif() + +set(tarball "ninja-${platform}.zip") + +file(DOWNLOAD + "https://github.com/ninja-build/ninja/releases/download/v${version}/${tarball}" .gitlab/${tarball} + EXPECTED_HASH SHA256=${sha256sum} + SHOW_PROGRESS + ) + +execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xf ${tarball} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.gitlab + RESULT_VARIABLE extract_results + ) + +if(extract_results) + message(FATAL_ERROR "Extracting `${tarball}` failed: ${extract_results}.") +endif() diff --git a/.gitlab/ci/macos.yml b/.gitlab/ci/macos.yml index 682f0e2e8..6badbab88 100644 --- a/.gitlab/ci/macos.yml +++ b/.gitlab/ci/macos.yml @@ -42,7 +42,13 @@ test:macos_xcode13: before_script: - .gitlab/ci/config/cmake.sh - export PATH=$PWD/.gitlab/cmake/bin:$PATH + - "cmake -VV -P .gitlab/ci/config/ccache.cmake" + - export PATH=$PWD/.gitlab/ccache:$PATH + - "cmake -VV -P .gitlab/ci/config/ninja.cmake" + - export PATH=$PWD/.gitlab:$PATH - "cmake --version" + - "ccache --version" + - "ninja --version" - "cmake -V -P .gitlab/ci/config/fetch_vtkm_tags.cmake" - "cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake" - "ctest -VV -S .gitlab/ci/ctest_configure.cmake" @@ -59,8 +65,11 @@ test:macos_xcode13: interruptible: true before_script: - .gitlab/ci/config/cmake.sh - - export PATH=$PWD/.gitlab/cmake/bin:$PATH + - export PATH=.gitlab/cmake/bin:$PATH + - "cmake -VV -P .gitlab/ci/config/ninja.cmake" + - export PATH=$PWD/.gitlab:$PATH - cmake --version + - ninja --version script: - "ctest $CTEST_TIMEOUT -VV -S .gitlab/ci/ctest_test.cmake" extends: diff --git a/.gitlab/ci/windows10.yml b/.gitlab/ci/windows10.yml index f96dbf007..7d8b278a7 100644 --- a/.gitlab/ci/windows10.yml +++ b/.gitlab/ci/windows10.yml @@ -29,8 +29,12 @@ - Invoke-Expression -Command .gitlab/ci/config/cmake.ps1 - Invoke-Expression -Command .gitlab/ci/config/vcvarsall.ps1 - $pwdpath = $pwd.Path - - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$pwdpath\.gitlab\cmake\bin;$env:PATH" + - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\cmake\bin;$env:PATH" - "cmake --version" + - "cmake -V -P .gitlab/ci/config/ccache.cmake" + - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\ccache;$env:PATH" + - "cmake -V -P .gitlab/ci/config/ninja.cmake" + - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$env:PATH" - "cmake -V -P .gitlab/ci/config/gitlab_ci_setup.cmake" - "ctest -VV -S .gitlab/ci/ctest_configure.cmake" script: @@ -67,7 +71,10 @@ - Invoke-Expression -Command .gitlab/ci/config/cmake.ps1 - Invoke-Expression -Command .gitlab/ci/config/vcvarsall.ps1 - $pwdpath = $pwd.Path - - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$pwdpath\.gitlab\cmake\bin;$env:PATH" + - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\cmake\bin;$env:PATH" + - "cmake --version" + - "cmake -V -P .gitlab/ci/config/ninja.cmake" + - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$env:PATH" script: - "ctest -VV -S .gitlab/ci/ctest_test.cmake" diff --git a/CMake/FindTBB.cmake b/CMake/FindTBB.cmake index 95cc79586..bd7563131 100644 --- a/CMake/FindTBB.cmake +++ b/CMake/FindTBB.cmake @@ -70,32 +70,29 @@ # Use TBBConfig.cmake if possible. -# Disabling this as it running the TBBConfig.cmake on dragnipur is -# causing a CMake error. I don't know if this is an install problem -# or an issue with version 2018.0. -# set(_tbb_find_quiet) -# if (TBB_FIND_QUIETLY) -# set(_tbb_find_quiet QUIET) -# endif () -# set(_tbb_find_components) -# set(_tbb_find_optional_components) -# foreach (_tbb_find_component IN LISTS TBB_FIND_COMPONENTS) -# if (TBB_FIND_REQUIRED_${_tbb_find_component}) -# list(APPEND _tbb_find_components "${_tbb_find_component}") -# else () -# list(APPEND _tbb_find_optional_components "${_tbb_find_component}") -# endif () -# endforeach () -# unset(_tbb_find_component) -# find_package(TBB CONFIG ${_tbb_find_quiet} -# COMPONENTS ${_tbb_find_components} -# OPTIONAL_COMPONENTS ${_tbb_find_optional_components}) -# unset(_tbb_find_quiet) -# unset(_tbb_find_components) -# unset(_tbb_find_optional_components) -# if (TBB_FOUND) -# return () -# endif () +set(_tbb_find_quiet) +if (TBB_FIND_QUIETLY) + set(_tbb_find_quiet QUIET) +endif () +set(_tbb_find_components) +set(_tbb_find_optional_components) +foreach (_tbb_find_component IN LISTS TBB_FIND_COMPONENTS) + if (TBB_FIND_REQUIRED_${_tbb_find_component}) + list(APPEND _tbb_find_components "${_tbb_find_component}") + else () + list(APPEND _tbb_find_optional_components "${_tbb_find_component}") + endif () +endforeach () +unset(_tbb_find_component) +find_package(TBB CONFIG ${_tbb_find_quiet} + COMPONENTS ${_tbb_find_components} + OPTIONAL_COMPONENTS ${_tbb_find_optional_components}) +unset(_tbb_find_quiet) +unset(_tbb_find_components) +unset(_tbb_find_optional_components) +if (TBB_FOUND) + return () +endif () #==================================================== # Fix the library path in case it is a linker script diff --git a/CMake/VTKmDeviceAdapters.cmake b/CMake/VTKmDeviceAdapters.cmake index a73a30ba2..e9ac03967 100644 --- a/CMake/VTKmDeviceAdapters.cmake +++ b/CMake/VTKmDeviceAdapters.cmake @@ -42,7 +42,11 @@ function(vtkm_extract_real_library library real_library) endfunction() if(VTKm_ENABLE_TBB AND NOT TARGET vtkm::tbb) - find_package(TBB REQUIRED) + # Skip find_package(TBB) if we already have it + if (NOT TARGET TBB::tbb) + find_package(TBB REQUIRED) + endif() + add_library(vtkmTBB INTERFACE) add_library(vtkm::tbb ALIAS vtkmTBB) target_link_libraries(vtkmTBB INTERFACE TBB::tbb) diff --git a/benchmarking/BenchmarkInSitu.cxx b/benchmarking/BenchmarkInSitu.cxx index 6118db06c..721f53b6e 100644 --- a/benchmarking/BenchmarkInSitu.cxx +++ b/benchmarking/BenchmarkInSitu.cxx @@ -14,7 +14,10 @@ #include #include +#include +#include +#include #include #include #include @@ -25,9 +28,9 @@ #include -#include #include #include +#include #include #include #include @@ -423,7 +426,7 @@ void AddField(vtkm::cont::PartitionedDataSet& input, } template -DataSetType RunStreamlinesHelper(vtkm::filter::Streamline& filter, const DataSetType& input) +DataSetType RunStreamlinesHelper(vtkm::filter::flow::Streamline& filter, const DataSetType& input) { auto dataSetBounds = vtkm::cont::BoundsCompute(input); vtkm::cont::ArrayHandle seedArray; @@ -457,7 +460,7 @@ void BenchStreamlines(::benchmark::State& state) BuildInputDataSet(cycle, isStructured, isMultiBlock, DataSetDim); inputGenTimer.Stop(); - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(0.1f); streamline.SetNumberOfSteps(1000); streamline.SetActiveField(PointVectorsName); diff --git a/benchmarking/BenchmarkODEIntegrators.cxx b/benchmarking/BenchmarkODEIntegrators.cxx index 87d9c6ddb..c3848a289 100644 --- a/benchmarking/BenchmarkODEIntegrators.cxx +++ b/benchmarking/BenchmarkODEIntegrators.cxx @@ -10,17 +10,14 @@ #include "Benchmarker.h" +#include #include #include -#include #include #include #include #include -#include -#include -#include - +#include namespace { @@ -50,7 +47,7 @@ void BenchParticleAdvection(::benchmark::State& state) vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1), vtkm::Particle(vtkm::Vec3f(.2f, 3.0f, .2f), 2) }); - vtkm::filter::ParticleAdvection particleAdvection; + vtkm::filter::flow::ParticleAdvection particleAdvection; particleAdvection.SetStepSize(vtkm::FloatDefault(1) / state.range(0)); particleAdvection.SetNumberOfSteps(static_cast(state.range(0))); diff --git a/examples/contour_tree_augmented/ContourTreeApp.cxx b/examples/contour_tree_augmented/ContourTreeApp.cxx index 96aca16a8..2ac66b8a1 100644 --- a/examples/contour_tree_augmented/ContourTreeApp.cxx +++ b/examples/contour_tree_augmented/ContourTreeApp.cxx @@ -548,14 +548,8 @@ int main(int argc, char* argv[]) static_cast(dims[1]), static_cast(0)); vtkm::cont::ArrayHandle localBlockIndices; - vtkm::cont::ArrayHandle localBlockOrigins; - vtkm::cont::ArrayHandle localBlockSizes; localBlockIndices.Allocate(blocksPerRank); - localBlockOrigins.Allocate(blocksPerRank); - localBlockSizes.Allocate(blocksPerRank); auto localBlockIndicesPortal = localBlockIndices.WritePortal(); - auto localBlockOriginsPortal = localBlockOrigins.WritePortal(); - auto localBlockSizesPortal = localBlockSizes.WritePortal(); { vtkm::Id lastDimSize = @@ -604,30 +598,29 @@ int main(int argc, char* argv[]) vtkm::Vec origin(0, blockIndex * blockSize); vtkm::Vec spacing(1, 1); ds = dsb.Create(vdims, origin, spacing); + vtkm::cont::CellSetStructured<2> cs; + cs.SetPointDimensions(vdims); + cs.SetGlobalPointDimensions(vtkm::Id2{ globalSize[0], globalSize[1] }); + cs.SetGlobalPointIndexStart(vtkm::Id2{ 0, blockIndex * blockSize }); + ds.SetCellSet(cs); - localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(blockIndex, 0, 0)); - localBlockOriginsPortal.Set(localBlockIndex, - vtkm::Id3((blockStart / blockSliceSize), 0, 0)); - localBlockSizesPortal.Set(localBlockIndex, - vtkm::Id3(currBlockSize, static_cast(dims[0]), 0)); + localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, blockIndex, 0)); } // 3D data else { vtkm::Id3 vdims; - vdims[0] = static_cast(dims[1]); - vdims[1] = static_cast(dims[0]); + vdims[0] = static_cast(dims[0]); + vdims[1] = static_cast(dims[1]); vdims[2] = static_cast(currBlockSize); - vtkm::Vec origin(0, 0, (blockIndex * blockSize)); + vtkm::Vec origin(0, 0, blockIndex * blockSize); vtkm::Vec spacing(1, 1, 1); ds = dsb.Create(vdims, origin, spacing); - - localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, 0, blockIndex)); - localBlockOriginsPortal.Set(localBlockIndex, - vtkm::Id3(0, 0, (blockStart / blockSliceSize))); - localBlockSizesPortal.Set( - localBlockIndex, - vtkm::Id3(static_cast(dims[0]), static_cast(dims[1]), currBlockSize)); + vtkm::cont::CellSetStructured<3> cs; + cs.SetPointDimensions(vdims); + cs.SetGlobalPointDimensions(globalSize); + cs.SetGlobalPointIndexStart(vtkm::Id3{ 0, 0, blockIndex * blockSize }); + ds.SetCellSet(cs); } std::vector subValues((values.begin() + blockStart), @@ -648,8 +641,7 @@ int main(int argc, char* argv[]) computeRegularStructure); #ifdef WITH_MPI - filter.SetSpatialDecomposition( - blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes); + filter.SetBlockIndices(blocksPerDim, localBlockIndices); #endif filter.SetActiveField("values"); diff --git a/examples/contour_tree_distributed/ContourTreeApp.cxx b/examples/contour_tree_distributed/ContourTreeApp.cxx index 2a0fabd47..a2cb3c4d7 100644 --- a/examples/contour_tree_distributed/ContourTreeApp.cxx +++ b/examples/contour_tree_distributed/ContourTreeApp.cxx @@ -401,14 +401,8 @@ int main(int argc, char* argv[]) vtkm::Id3 globalSize; vtkm::Id3 blocksPerDim; vtkm::cont::ArrayHandle localBlockIndices; - vtkm::cont::ArrayHandle localBlockOrigins; - vtkm::cont::ArrayHandle localBlockSizes; localBlockIndices.Allocate(blocksPerRank); - localBlockOrigins.Allocate(blocksPerRank); - localBlockSizes.Allocate(blocksPerRank); auto localBlockIndicesPortal = localBlockIndices.WritePortal(); - auto localBlockOriginsPortal = localBlockOrigins.WritePortal(); - auto localBlockSizesPortal = localBlockSizes.WritePortal(); // Read the pre-split data files if (preSplitFiles) @@ -595,6 +589,11 @@ int main(int argc, char* argv[]) static_cast(offset[1]) }; const vtkm::Vec v_spacing{ 1, 1 }; ds = dsb.Create(v_dims, v_origin, v_spacing); + vtkm::cont::CellSetStructured<2> cs; + cs.SetPointDimensions(v_dims); + cs.SetGlobalPointDimensions(vtkm::Id2{ globalSize[0], globalSize[1] }); + cs.SetGlobalPointIndexStart(vtkm::Id2{ offset[0], offset[1] }); + ds.SetCellSet(cs); } else { @@ -607,6 +606,11 @@ int main(int argc, char* argv[]) static_cast(offset[2]) }; vtkm::Vec v_spacing(1, 1, 1); ds = dsb.Create(v_dims, v_origin, v_spacing); + vtkm::cont::CellSetStructured<3> cs; + cs.SetPointDimensions(v_dims); + cs.SetGlobalPointDimensions(globalSize); + cs.SetGlobalPointIndexStart(vtkm::Id3{ offset[0], offset[1], offset[2] }); + ds.SetCellSet(cs); } ds.AddPointField("values", values); // and add to partition @@ -617,14 +621,6 @@ int main(int argc, char* argv[]) vtkm::Id3{ static_cast(blockIndex[0]), static_cast(blockIndex[1]), static_cast(nDims == 3 ? blockIndex[2] : 0) }); - localBlockOriginsPortal.Set(blockNo, - vtkm::Id3{ static_cast(offset[0]), - static_cast(offset[1]), - static_cast(nDims == 3 ? offset[2] : 0) }); - localBlockSizesPortal.Set(blockNo, - vtkm::Id3{ static_cast(dims[0]), - static_cast(dims[1]), - static_cast(nDims == 3 ? dims[2] : 0) }); if (blockNo == 0) { @@ -753,7 +749,6 @@ int main(int argc, char* argv[]) : vtkm::Id3(static_cast(dims[0]), static_cast(dims[1]), static_cast(1)); - std::cout << blocksPerDim << " " << globalSize << std::endl; { vtkm::Id lastDimSize = (nDims == 2) ? static_cast(dims[1]) : static_cast(dims[2]); @@ -801,12 +796,12 @@ int main(int argc, char* argv[]) vtkm::Vec origin(0, blockIndex * blockSize); vtkm::Vec spacing(1, 1); ds = dsb.Create(vdims, origin, spacing); - + vtkm::cont::CellSetStructured<2> cs; + cs.SetPointDimensions(vdims); + cs.SetGlobalPointDimensions(vtkm::Id2{ globalSize[0], globalSize[1] }); + cs.SetGlobalPointIndexStart(vtkm::Id2{ 0, (blockStart / blockSliceSize) }); + ds.SetCellSet(cs); localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, blockIndex, 0)); - localBlockOriginsPortal.Set(localBlockIndex, - vtkm::Id3(0, (blockStart / blockSliceSize), 0)); - localBlockSizesPortal.Set(localBlockIndex, - vtkm::Id3(static_cast(dims[0]), currBlockSize, 0)); } // 3D data else @@ -818,14 +813,12 @@ int main(int argc, char* argv[]) vtkm::Vec origin(0, 0, (blockIndex * blockSize)); vtkm::Vec spacing(1, 1, 1); ds = dsb.Create(vdims, origin, spacing); - + vtkm::cont::CellSetStructured<3> cs; + cs.SetPointDimensions(vdims); + cs.SetGlobalPointDimensions(globalSize); + cs.SetGlobalPointIndexStart(vtkm::Id3(0, 0, blockStart / blockSliceSize)); + ds.SetCellSet(cs); localBlockIndicesPortal.Set(localBlockIndex, vtkm::Id3(0, 0, blockIndex)); - localBlockOriginsPortal.Set(localBlockIndex, - vtkm::Id3(0, 0, (blockStart / blockSliceSize))); - localBlockSizesPortal.Set(localBlockIndex, - vtkm::Id3(static_cast(dims[0]), - static_cast(dims[1]), - currBlockSize)); } std::vector subValues((values.begin() + blockStart), @@ -863,13 +856,9 @@ int main(int argc, char* argv[]) prevTime = currTime; // Convert the mesh of values into contour tree, pairs of vertex ids - vtkm::filter::ContourTreeUniformDistributed filter(blocksPerDim, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes, - timingsLogLevel, - treeLogLevel); + vtkm::filter::scalar_topology::ContourTreeUniformDistributed filter(timingsLogLevel, + treeLogLevel); + filter.SetBlockIndices(blocksPerDim, localBlockIndices); filter.SetUseBoundaryExtremaOnly(useBoundaryExtremaOnly); filter.SetUseMarchingCubes(useMarchingCubes); filter.SetAugmentHierarchicalTree(augmentHierarchicalTree); @@ -895,8 +884,7 @@ int main(int argc, char* argv[]) { if (computeHierarchicalVolumetricBranchDecomposition) { - vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter( - blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes); + vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter bd_filter; auto bd_result = bd_filter.Execute(result); for (vtkm::Id ds_no = 0; ds_no < result.GetNumberOfPartitions(); ++ds_no) diff --git a/examples/particle_advection/CMakeLists.txt b/examples/particle_advection/CMakeLists.txt index 7866c56c6..12a8ef3b3 100644 --- a/examples/particle_advection/CMakeLists.txt +++ b/examples/particle_advection/CMakeLists.txt @@ -14,10 +14,4 @@ project(ParticleAdvection CXX) find_package(VTKm REQUIRED QUIET) add_executable(Particle_Advection ParticleAdvection.cxx) -target_link_libraries(Particle_Advection PRIVATE vtkm_filter vtkm_io) -vtkm_add_target_information(Particle_Advection - DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS - DEVICE_SOURCES ParticleAdvection.cxx) -if(TARGET vtkm::tbb) - target_compile_definitions(Particle_Advection PRIVATE BUILDING_TBB_VERSION) -endif() +target_link_libraries(Particle_Advection PRIVATE vtkm_filter_flow vtkm_io) diff --git a/examples/particle_advection/ParticleAdvection.cxx b/examples/particle_advection/ParticleAdvection.cxx index e2e4a1695..64172d152 100644 --- a/examples/particle_advection/ParticleAdvection.cxx +++ b/examples/particle_advection/ParticleAdvection.cxx @@ -8,9 +8,10 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include #include -#include +#include #include #include @@ -74,7 +75,7 @@ int main(int argc, char** argv) auto seedArray = vtkm::cont::make_ArrayHandle(seeds, vtkm::CopyFlag::Off); //compute streamlines - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(stepSize); streamline.SetNumberOfSteps(numSteps); diff --git a/examples/streamline_mpi/CMakeLists.txt b/examples/streamline_mpi/CMakeLists.txt index c65f29474..5ce083ae3 100644 --- a/examples/streamline_mpi/CMakeLists.txt +++ b/examples/streamline_mpi/CMakeLists.txt @@ -16,12 +16,5 @@ find_package(VTKm REQUIRED QUIET) if (VTKm_ENABLE_MPI) add_executable(StreamlineMPI StreamlineMPI.cxx) target_compile_definitions(StreamlineMPI PRIVATE "MPI_ENABLED") - target_link_libraries(StreamlineMPI PRIVATE vtkm_filter vtkm_io MPI::MPI_CXX) - vtkm_add_target_information(StreamlineMPI - DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS - DEVICE_SOURCES StreamlineMPI.cxx) + target_link_libraries(StreamlineMPI PRIVATE vtkm_filter_flow vtkm_io MPI::MPI_CXX) endif() - -#if(TARGET vtkm::tbb) -# target_compile_definitions(streamline_mpi PRIVATE BUILDING_TBB_VERSION) -#endif() diff --git a/examples/streamline_mpi/StreamlineMPI.cxx b/examples/streamline_mpi/StreamlineMPI.cxx index 2cc2ffe8a..aec518cec 100644 --- a/examples/streamline_mpi/StreamlineMPI.cxx +++ b/examples/streamline_mpi/StreamlineMPI.cxx @@ -8,13 +8,14 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -23,12 +24,6 @@ #include #include - -#include -#include -#include - - void LoadData(std::string& fname, std::vector& dataSets, int rank, int nRanks) { std::string buff; @@ -99,7 +94,7 @@ int main(int argc, char** argv) std::vector dataSets; LoadData(dataFile, dataSets, rank, size); - vtkm::filter::ParticleAdvection pa; + vtkm::filter::flow::ParticleAdvection pa; vtkm::cont::ArrayHandle seedArray; seedArray = vtkm::cont::make_ArrayHandle({ vtkm::Particle(vtkm::Vec3f(.1f, .1f, .9f), 0), diff --git a/examples/temporal_advection/TemporalAdvection.cxx b/examples/temporal_advection/TemporalAdvection.cxx index d4501f475..141833e6b 100644 --- a/examples/temporal_advection/TemporalAdvection.cxx +++ b/examples/temporal_advection/TemporalAdvection.cxx @@ -12,11 +12,14 @@ #include #include +#include +//#include +#include #include #include -#include +//#include -#include +#include #include #include @@ -91,7 +94,7 @@ int main(int argc, char** argv) // Instantiate the filter by providing necessary parameters. // Necessary parameters are : - vtkm::filter::Pathline pathlineFilter; + vtkm::filter::flow::Pathline pathlineFilter; pathlineFilter.SetActiveField(fieldName); // 1. The current and next time slice. The current time slice is passed // through the parameter to the Execute method. diff --git a/vtkm/Particle.h b/vtkm/Particle.h index 32ae7b214..027df2878 100644 --- a/vtkm/Particle.h +++ b/vtkm/Particle.h @@ -142,6 +142,17 @@ public: vtkm::Id NumSteps = 0; vtkm::ParticleStatus Status; vtkm::FloatDefault Time = 0; + + static size_t Sizeof() + { + constexpr std::size_t sz = sizeof(vtkm::Vec3f) // Pos + + sizeof(vtkm::Id) // ID + + sizeof(vtkm::Id) // NumSteps + + sizeof(vtkm::UInt8) // Status + + sizeof(vtkm::FloatDefault); // Time + + return sz; + } }; class ChargedParticle @@ -228,6 +239,14 @@ public: return this->Pos + translation; } + inline VTKM_CONT friend std::ostream& operator<<(std::ostream& out, + const vtkm::ChargedParticle& p) + { + out << "v(" << p.Time << ") = " << p.Pos << ", ID: " << p.ID << ", NumSteps: " << p.NumSteps + << ", Status: " << p.Status; + return out; + } + vtkm::Vec3f Pos; vtkm::Id ID = -1; vtkm::Id NumSteps = 0; @@ -243,6 +262,23 @@ private: static_cast(2.99792458e8); friend struct mangled_diy_namespace::Serialization; + +public: + static size_t Sizeof() + { + constexpr std::size_t sz = sizeof(vtkm::Vec3f) // Pos + + sizeof(vtkm::Id) // ID + + sizeof(vtkm::Id) // NumSteps + + sizeof(vtkm::UInt8) // Status + + sizeof(vtkm::FloatDefault) // Time + + sizeof(vtkm::FloatDefault) //Mass + + sizeof(vtkm::FloatDefault) //Charge + + sizeof(vtkm::FloatDefault) //Weighting + + sizeof(vtkm::Vec3f) //Momentum + + sizeof(vtkm::FloatDefault); //Speed_of_light + + return sz; + } }; } //namespace vtkm diff --git a/vtkm/cont/CellSetStructured.h b/vtkm/cont/CellSetStructured.h index 26475b46e..6399c4ee4 100644 --- a/vtkm/cont/CellSetStructured.h +++ b/vtkm/cont/CellSetStructured.h @@ -51,6 +51,11 @@ public: this->Structure.SetPointDimensions(dimensions); } + void SetGlobalPointDimensions(SchedulingRangeType dimensions) + { + this->Structure.SetGlobalPointDimensions(dimensions); + } + void SetGlobalPointIndexStart(SchedulingRangeType start) { this->Structure.SetGlobalPointIndexStart(start); @@ -58,8 +63,18 @@ public: SchedulingRangeType GetPointDimensions() const { return this->Structure.GetPointDimensions(); } + SchedulingRangeType GetGlobalPointDimensions() const + { + return this->Structure.GetGlobalPointDimensions(); + } + SchedulingRangeType GetCellDimensions() const { return this->Structure.GetCellDimensions(); } + SchedulingRangeType GetGlobalCellDimensions() const + { + return this->Structure.GetGlobalCellDimensions(); + } + SchedulingRangeType GetGlobalPointIndexStart() const { return this->Structure.GetGlobalPointIndexStart(); @@ -225,17 +240,20 @@ public: static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs) { vtkmdiy::save(bb, cs.GetPointDimensions()); + vtkmdiy::save(bb, cs.GetGlobalPointDimensions()); vtkmdiy::save(bb, cs.GetGlobalPointIndexStart()); } static VTKM_CONT void load(BinaryBuffer& bb, Type& cs) { - typename Type::SchedulingRangeType dims, start; + typename Type::SchedulingRangeType dims, gdims, start; vtkmdiy::load(bb, dims); + vtkmdiy::load(bb, gdims); vtkmdiy::load(bb, start); cs = Type{}; cs.SetPointDimensions(dims); + cs.SetGlobalPointDimensions(gdims); cs.SetGlobalPointIndexStart(start); } }; diff --git a/vtkm/cont/DataSet.cxx b/vtkm/cont/DataSet.cxx index 819b4f312..155bfbe1f 100644 --- a/vtkm/cont/DataSet.cxx +++ b/vtkm/cont/DataSet.cxx @@ -14,6 +14,23 @@ namespace vtkm { namespace cont { + +VTKM_CONT std::string& GlobalGhostCellFieldName() noexcept +{ + static std::string GhostCellName("vtkGhostCells"); + return GhostCellName; +} + +VTKM_CONT const std::string& GetGlobalGhostCellFieldName() noexcept +{ + return GlobalGhostCellFieldName(); +} + +VTKM_CONT void SetGlobalGhostCellFieldName(const std::string& name) noexcept +{ + GlobalGhostCellFieldName() = name; +} + void DataSet::Clear() { this->CoordSystems.clear(); @@ -39,6 +56,7 @@ void DataSet::CopyStructure(const vtkm::cont::DataSet& source) { this->CoordSystems = source.CoordSystems; this->CellSet = source.CellSet; + this->GhostCellName = source.GhostCellName; } const vtkm::cont::Field& DataSet::GetField(vtkm::Id index) const @@ -59,16 +77,35 @@ vtkm::cont::Field& DataSet::GetField(vtkm::Id index) vtkm::Id DataSet::GetFieldIndex(const std::string& name, vtkm::cont::Field::Association assoc) const { - bool found; - vtkm::Id index = this->FindFieldIndex(name, assoc, found); - if (found) + const auto it = this->Fields.find({ name, assoc }); + if (it != this->Fields.end()) { - return index; + return static_cast(std::distance(this->Fields.begin(), it)); } - else + return -1; +} + +const vtkm::cont::Field& DataSet::GetField(const std::string& name, + vtkm::cont::Field::Association assoc) const +{ + auto idx = this->GetFieldIndex(name, assoc); + if (idx == -1) { throw vtkm::cont::ErrorBadValue("No field with requested name: " + name); } + + return this->GetField(idx); +} + +vtkm::cont::Field& DataSet::GetField(const std::string& name, vtkm::cont::Field::Association assoc) +{ + auto idx = this->GetFieldIndex(name, assoc); + if (idx == -1) + { + throw vtkm::cont::ErrorBadValue("No field with requested name: " + name); + } + + return this->GetField(idx); } const vtkm::cont::CoordinateSystem& DataSet::GetCoordinateSystem(vtkm::Id index) const @@ -150,21 +187,6 @@ void DataSet::PrintSummary(std::ostream& out) const out.flush(); } -vtkm::Id DataSet::FindFieldIndex(const std::string& name, - vtkm::cont::Field::Association association, - bool& found) const -{ - const auto it = this->Fields.find({ name, association }); - if (it != this->Fields.end()) - { - found = true; - return static_cast(std::distance(this->Fields.begin(), it)); - } - - found = false; - return -1; -} - VTKM_CONT void DataSet::AddField(const Field& field) { // map::insert will not replace the duplicated element diff --git a/vtkm/cont/DataSet.h b/vtkm/cont/DataSet.h index 80d90cda5..c445549de 100644 --- a/vtkm/cont/DataSet.h +++ b/vtkm/cont/DataSet.h @@ -24,9 +24,25 @@ namespace vtkm namespace cont { +VTKM_CONT_EXPORT VTKM_CONT std::string& GlobalGhostCellFieldName() noexcept; + +VTKM_CONT_EXPORT VTKM_CONT const std::string& GetGlobalGhostCellFieldName() noexcept; + +VTKM_CONT_EXPORT VTKM_CONT void SetGlobalGhostCellFieldName(const std::string& name) noexcept; + class VTKM_CONT_EXPORT DataSet { public: + DataSet() = default; + + DataSet(vtkm::cont::DataSet&&) = default; + + DataSet(const vtkm::cont::DataSet&) = default; + + vtkm::cont::DataSet& operator=(vtkm::cont::DataSet&&) = default; + + vtkm::cont::DataSet& operator=(const vtkm::cont::DataSet&) = default; + VTKM_CONT void Clear(); /// Get the number of cells contained in this DataSet @@ -50,25 +66,45 @@ public: bool HasField(const std::string& name, vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::Any) const { - bool found = false; - this->FindFieldIndex(name, assoc, found); - return found; + return (this->GetFieldIndex(name, assoc) != -1); } VTKM_CONT bool HasCellField(const std::string& name) const { - bool found = false; - this->FindFieldIndex(name, vtkm::cont::Field::Association::Cells, found); - return found; + return (this->GetFieldIndex(name, vtkm::cont::Field::Association::Cells) != -1); + } + + VTKM_CONT + bool HasGhostCellField() const + { + if (this->GhostCellName) + { + return this->HasCellField(*this->GhostCellName); + } + else + { + return false; + } + } + + VTKM_CONT + const std::string& GetGhostCellFieldName() const + { + if (this->HasGhostCellField()) + { + return *this->GhostCellName; + } + else + { + throw vtkm::cont::ErrorBadValue("No Ghost Cell Field Name"); + } } VTKM_CONT bool HasPointField(const std::string& name) const { - bool found = false; - this->FindFieldIndex(name, vtkm::cont::Field::Association::Points, found); - return found; + return (this->GetFieldIndex(name, vtkm::cont::Field::Association::Points) != -1); } @@ -85,18 +121,12 @@ public: VTKM_CONT const vtkm::cont::Field& GetField( const std::string& name, - vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::Any) const - { - return this->GetField(this->GetFieldIndex(name, assoc)); - } + vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::Any) const; VTKM_CONT vtkm::cont::Field& GetField( const std::string& name, - vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::Any) - { - return this->GetField(this->GetFieldIndex(name, assoc)); - } + vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::Any); //@} /// Returns the first cell field that matches the provided name. @@ -115,6 +145,23 @@ public: } //@} + /// Returns the first cell field that matches the provided name. + /// Will throw an exception if no match is found + //@{ + VTKM_CONT + const vtkm::cont::Field& GetGhostCellField() const + { + if (this->HasGhostCellField()) + { + return this->GetCellField(*(this->GhostCellName)); + } + else + { + throw vtkm::cont::ErrorBadValue("No Ghost Cell Field"); + } + } + //@} + /// Returns the first point field that matches the provided name. /// Will throw an exception if no match is found //@{ @@ -165,6 +212,25 @@ public: this->AddField(make_FieldCell(fieldName, field)); } + VTKM_CONT + void AddGhostCellField(const std::string& fieldName, const vtkm::cont::UnknownArrayHandle& field) + { + this->GhostCellName.reset(new std::string(fieldName)); + this->AddField(make_FieldCell(fieldName, field)); + } + + VTKM_CONT + void AddGhostCellField(const vtkm::cont::UnknownArrayHandle& field) + { + this->AddGhostCellField(GetGlobalGhostCellFieldName(), field); + } + + VTKM_CONT + void AddGhostCellField(const vtkm::cont::Field& field) + { + this->AddGhostCellField(field.GetName(), field.GetData()); + } + template VTKM_CONT void AddCellField(const std::string& fieldName, const vtkm::cont::ArrayHandle& field) @@ -296,11 +362,7 @@ private: std::vector CoordSystems; std::map Fields; vtkm::cont::UnknownCellSet CellSet; - - VTKM_CONT - vtkm::Id FindFieldIndex(const std::string& name, - vtkm::cont::Field::Association association, - bool& found) const; + std::shared_ptr GhostCellName; }; } // namespace cont diff --git a/vtkm/cont/PartitionedDataSet.cxx b/vtkm/cont/PartitionedDataSet.cxx index 9dbcb6e0d..761bde302 100644 --- a/vtkm/cont/PartitionedDataSet.cxx +++ b/vtkm/cont/PartitionedDataSet.cxx @@ -15,6 +15,13 @@ #include #include #include +#include + +// clang-format off +VTKM_THIRDPARTY_PRE_INCLUDE +#include +VTKM_THIRDPARTY_POST_INCLUDE +// clang-format on namespace vtkm { @@ -73,6 +80,19 @@ vtkm::Id PartitionedDataSet::GetNumberOfPartitions() const return static_cast(this->Partitions.size()); } +VTKM_CONT +vtkm::Id PartitionedDataSet::GetGlobalNumberOfPartitions() const +{ +#ifdef VTKM_ENABLE_MPI + auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); + vtkm::Id globalSize = 0; + vtkmdiy::mpi::all_reduce(comm, GetNumberOfPartitions(), globalSize, std::plus{}); + return globalSize; +#else + return GetNumberOfPartitions(); +#endif +} + VTKM_CONT const vtkm::cont::DataSet& PartitionedDataSet::GetPartition(vtkm::Id blockId) const { diff --git a/vtkm/cont/PartitionedDataSet.h b/vtkm/cont/PartitionedDataSet.h index 7152939ac..e2f4f465a 100644 --- a/vtkm/cont/PartitionedDataSet.h +++ b/vtkm/cont/PartitionedDataSet.h @@ -32,16 +32,16 @@ public: using reference = typename StorageVec::reference; using const_reference = typename StorageVec::const_reference; - /// create a new PartitionedDataSet containng a single DataSet @a ds + /// Create a new PartitionedDataSet containng a single DataSet @a ds. VTKM_CONT PartitionedDataSet(const vtkm::cont::DataSet& ds); - /// create a new PartitionedDataSet with the existing one @a src + /// Create a new PartitionedDataSet with the existing one @a src. VTKM_CONT PartitionedDataSet(const vtkm::cont::PartitionedDataSet& src); - /// create a new PartitionedDataSet with a DataSet vector @a partitions. + /// Create a new PartitionedDataSet with a DataSet vector @a partitions. VTKM_CONT explicit PartitionedDataSet(const std::vector& partitions); - /// create a new PartitionedDataSet with the capacity set to be @a size + /// Create a new PartitionedDataSet with the capacity set to be @a size. VTKM_CONT explicit PartitionedDataSet(vtkm::Id size); @@ -53,33 +53,41 @@ public: VTKM_CONT ~PartitionedDataSet(); - /// get the field @a field_name from partition @a partition_index + /// Get the field @a field_name from partition @a partition_index. VTKM_CONT vtkm::cont::Field GetField(const std::string& field_name, int partition_index) const; + /// Get number of DataSet objects stored in this PartitionedDataSet. VTKM_CONT vtkm::Id GetNumberOfPartitions() const; + /// Get number of partations across all MPI ranks. + /// @warning This method requires global communication (MPI_Allreduce) if MPI is enabled. + VTKM_CONT + vtkm::Id GetGlobalNumberOfPartitions() const; + + /// Get the DataSet @a partId. VTKM_CONT const vtkm::cont::DataSet& GetPartition(vtkm::Id partId) const; + /// Get an STL vector of all DataSet objects stored in PartitionedDataSet. VTKM_CONT const std::vector& GetPartitions() const; - /// add DataSet @a ds to the end of the contained DataSet vector + /// Add DataSet @a ds to the end of the contained DataSet vector. VTKM_CONT void AppendPartition(const vtkm::cont::DataSet& ds); - /// add DataSet @a ds to position @a index of the contained DataSet vector + /// Add DataSet @a ds to position @a index of the contained DataSet vector. VTKM_CONT void InsertPartition(vtkm::Id index, const vtkm::cont::DataSet& ds); - /// replace the @a index positioned element of the contained DataSet vector - /// with @a ds + /// Replace the @a index positioned element of the contained DataSet vector + /// with @a ds. VTKM_CONT void ReplacePartition(vtkm::Id index, const vtkm::cont::DataSet& ds); - /// append the DataSet vector "partitions" to the end of the contained one + /// Append the DataSet vector @a partitions to the end of the contained one. VTKM_CONT void AppendPartitions(const std::vector& partitions); diff --git a/vtkm/cont/UnknownArrayHandle.cxx b/vtkm/cont/UnknownArrayHandle.cxx index 3cde57a99..4fcfb555d 100644 --- a/vtkm/cont/UnknownArrayHandle.cxx +++ b/vtkm/cont/UnknownArrayHandle.cxx @@ -95,7 +95,17 @@ bool UnknownAHComponentInfo::operator==(const UnknownAHComponentInfo& rhs) else { // Needs optimization based on platform. OSX cannot compare typeid across translation units? - return this->Type == rhs.Type; + bool typesEqual = (this->Type == rhs.Type); + + // Could use optimization based on platform. OSX cannot compare typeid across translation + // units, so we have to also check the names. (Why doesn't the == operator above do that?) + // Are there other platforms that behave similarly? + if (!typesEqual) + { + typesEqual = (std::strcmp(this->Type.name(), rhs.Type.name()) == 0); + } + + return typesEqual; } } @@ -151,7 +161,7 @@ VTKM_CONT bool UnknownArrayHandle::IsBaseComponentTypeImpl( return false; } - // Needs optimization based on platform. OSX cannot compare typeid across translation units? + // Note that detail::UnknownAHComponentInfo has a custom operator== return this->Container->BaseComponentType == type; } diff --git a/vtkm/cont/testing/UnitTestParticleArrayCopy.cxx b/vtkm/cont/testing/UnitTestParticleArrayCopy.cxx index 09c495383..4054270cf 100644 --- a/vtkm/cont/testing/UnitTestParticleArrayCopy.cxx +++ b/vtkm/cont/testing/UnitTestParticleArrayCopy.cxx @@ -9,6 +9,7 @@ //============================================================================ #include +#include #include #include diff --git a/vtkm/exec/internal/testing/UnitTestVariant.cxx b/vtkm/exec/internal/testing/UnitTestVariant.cxx index 93b1f0379..5fbc9d6c5 100644 --- a/vtkm/exec/internal/testing/UnitTestVariant.cxx +++ b/vtkm/exec/internal/testing/UnitTestVariant.cxx @@ -21,6 +21,7 @@ namespace test_variant template struct TypePlaceholder { + vtkm::IdComponent Value = Index; }; // A class that is trivially copiable but not totally trivial. @@ -313,6 +314,17 @@ struct TestFunctor } }; +struct TestFunctorModify +{ + template + void operator()(TypePlaceholder& object, vtkm::Id expectedValue) + { + VTKM_TEST_ASSERT(Index == expectedValue, "Index = ", Index, ", expected = ", expectedValue); + VTKM_TEST_ASSERT(object.Value == expectedValue); + ++object.Value; + } +}; + void TestGet() { std::cout << "Test Get" << std::endl; @@ -431,6 +443,11 @@ void TestCastAndCall() VariantType variant26{ TypePlaceholder<26>{} }; result = variant26.CastAndCall(TestFunctor(), 26); VTKM_TEST_ASSERT(test_equal(result, TestValue(26, vtkm::FloatDefault{}))); + + variant1.CastAndCall(TestFunctorModify{}, 1); + VTKM_TEST_ASSERT(variant1.Get<1>().Value == 2, "Variant object not updated."); + + variant1.CastAndCall([](auto& object) { ++object.Value; }); } void TestCopyInvalid() diff --git a/vtkm/filter/CMakeLists.txt b/vtkm/filter/CMakeLists.txt index 136b8ab93..3f09fe818 100644 --- a/vtkm/filter/CMakeLists.txt +++ b/vtkm/filter/CMakeLists.txt @@ -81,11 +81,11 @@ set(common_headers FilterDataSetWithField.h FilterField.h Filter.h - FilterParticleAdvection.h - FilterTemporalParticleAdvection.h FilterTraits.h PolicyBase.h PolicyDefault.h + Lagrangian.h + LagrangianStructures.h ) vtkm_declare_headers(${common_headers}) @@ -95,37 +95,12 @@ set(common_header_template_sources FilterDataSetWithField.hxx FilterField.hxx Filter.hxx - FilterParticleAdvection.hxx - FilterTemporalParticleAdvection.hxx + Lagrangian.hxx + LagrangianStructures.hxx ) vtkm_declare_headers(${common_header_template_sources}) -set(extra_headers - Lagrangian.h - LagrangianStructures.h - ParticleAdvection.h - Pathline.h - PathParticle.h - Streamline.h - StreamSurface.h - ) - -set(extra_header_template_sources - Lagrangian.hxx - LagrangianStructures.hxx - ParticleAdvection.hxx - Pathline.hxx - PathParticle.hxx - Streamline.hxx - StreamSurface.hxx - ) - -set(extra_sources_device - particleadvection/Messenger.cxx - particleadvection/ParticleMessenger.cxx - ) - set(core_headers FieldSelection.h NewFilter.h @@ -153,30 +128,16 @@ vtkm_library( add_library(vtkm_filter INTERFACE) -vtkm_library( - NAME vtkm_filter_extra - TEMPLATE_SOURCES ${extra_header_template_sources} - HEADERS ${extra_headers} - DEVICE_SOURCES ${extra_sources_device} - USE_VTKM_JOB_POOL -) - set_target_properties( vtkm_filter_core - vtkm_filter_extra PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE BATCH ) target_link_libraries(vtkm_filter_core PUBLIC vtkm_cont vtkm_worklet) -target_link_libraries(vtkm_filter_extra PUBLIC vtkm_cont vtkm_worklet) -if (VTKm_ENABLE_MPI) - target_link_libraries(vtkm_filter_extra PUBLIC MPI::MPI_CXX) -endif() target_link_libraries(vtkm_filter PUBLIC INTERFACE - vtkm_filter_extra vtkm_filter_core ) @@ -187,9 +148,9 @@ add_subdirectory(connected_components) add_subdirectory(contour) add_subdirectory(density_estimate) add_subdirectory(entity_extraction) +add_subdirectory(flow) add_subdirectory(image_processing) add_subdirectory(internal) -add_subdirectory(particleadvection) add_subdirectory(field_conversion) add_subdirectory(field_transform) add_subdirectory(geometry_refinement) diff --git a/vtkm/filter/FilterParticleAdvection.h b/vtkm/filter/FilterParticleAdvection.h deleted file mode 100644 index 8567ca494..000000000 --- a/vtkm/filter/FilterParticleAdvection.h +++ /dev/null @@ -1,92 +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. -//============================================================================ - -#ifndef vtk_m_filter_FilterParticleAdvection_h -#define vtk_m_filter_FilterParticleAdvection_h - -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief base class for advecting particles in a vector field. - -/// Takes as input a vector field and seed locations and advects the seeds -/// through the flow field. - -template -class FilterParticleAdvection : public vtkm::filter::FilterDataSetWithField -{ -public: - using SupportedTypes = vtkm::TypeListFieldVec3; - - VTKM_CONT - FilterParticleAdvection(); - - VTKM_CONT - void SetStepSize(vtkm::FloatDefault s) { this->StepSize = s; } - - VTKM_CONT - void SetNumberOfSteps(vtkm::Id n) { this->NumberOfSteps = n; } - - VTKM_CONT - void SetSeeds(const std::vector& seeds, - vtkm::CopyFlag copyFlag = vtkm::CopyFlag::On) - { - this->Seeds = vtkm::cont::make_ArrayHandle(seeds, copyFlag); - } - - VTKM_CONT - void SetSeeds(vtkm::cont::ArrayHandle& seeds) { this->Seeds = seeds; } - - VTKM_CONT - bool GetUseThreadedAlgorithm() { return this->UseThreadedAlgorithm; } - - VTKM_CONT - void SetUseThreadedAlgorithm(bool val) { this->UseThreadedAlgorithm = val; } - - template - VTKM_CONT vtkm::cont::DataSet PrepareForExecution(const vtkm::cont::DataSet& input, - vtkm::filter::PolicyBase policy); - - template - VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet&, - const vtkm::cont::Field&, - vtkm::filter::PolicyBase) - { - return false; - } - -protected: - VTKM_CONT virtual void ValidateOptions() const; - - VTKM_CONT std::vector - CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::particleadvection::BoundsMap& boundsMap) const; - - vtkm::Id NumberOfSteps; - vtkm::FloatDefault StepSize; - vtkm::cont::ArrayHandle Seeds; - bool UseThreadedAlgorithm; - -private: -}; -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_FilterParticleAdvection_hxx -#include -#endif - -#endif // vtk_m_filter_FilterParticleAdvection_h diff --git a/vtkm/filter/FilterParticleAdvection.hxx b/vtkm/filter/FilterParticleAdvection.hxx deleted file mode 100644 index dee896cda..000000000 --- a/vtkm/filter/FilterParticleAdvection.hxx +++ /dev/null @@ -1,83 +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. -//============================================================================ -#ifndef vtk_m_filter_FilterParticleAdvection_hxx -#define vtk_m_filter_FilterParticleAdvection_hxx - -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT FilterParticleAdvection::FilterParticleAdvection() - : vtkm::filter::FilterDataSetWithField() - , NumberOfSteps(0) - , StepSize(0) - , UseThreadedAlgorithm(false) -{ -} - -template -void FilterParticleAdvection::ValidateOptions() const -{ - if (this->GetUseCoordinateSystemAsField()) - throw vtkm::cont::ErrorFilterExecution("Coordinate system as field not supported"); - if (this->Seeds.GetNumberOfValues() == 0) - throw vtkm::cont::ErrorFilterExecution("No seeds provided."); - if (this->NumberOfSteps == 0) - throw vtkm::cont::ErrorFilterExecution("Number of steps not specified."); - if (this->StepSize == 0) - throw vtkm::cont::ErrorFilterExecution("Step size not specified."); -} - -template -std::vector -FilterParticleAdvection::CreateDataSetIntegrators( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::particleadvection::BoundsMap& boundsMap) const -{ - using DSIType = vtkm::filter::particleadvection::DataSetIntegrator; - - std::vector dsi; - - if (boundsMap.GetTotalNumBlocks() == 0) - throw vtkm::cont::ErrorFilterExecution("No input datasets."); - - std::string activeField = this->GetActiveFieldName(); - - for (vtkm::Id i = 0; i < input.GetNumberOfPartitions(); i++) - { - vtkm::Id blockId = boundsMap.GetLocalBlockId(i); - auto ds = input.GetPartition(i); - if (!ds.HasPointField(activeField) && !ds.HasCellField(activeField)) - throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation"); - dsi.push_back(DSIType(ds, blockId, activeField)); - } - - return dsi; -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::DataSet -FilterParticleAdvection::PrepareForExecution( - const vtkm::cont::DataSet& input, - vtkm::filter::PolicyBase policy) -{ - return (static_cast(this))->DoExecute(input, policy); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/FilterTemporalParticleAdvection.h b/vtkm/filter/FilterTemporalParticleAdvection.h deleted file mode 100644 index 988de3e93..000000000 --- a/vtkm/filter/FilterTemporalParticleAdvection.h +++ /dev/null @@ -1,75 +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. -//============================================================================ - -#ifndef vtk_m_filter_TemporalFilterParticleAdvection_h -#define vtk_m_filter_TemporalFilterParticleAdvection_h - -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief base class for advecting particles in a vector field. - -/// Takes as input a vector field and seed locations and advects the seeds -/// through the flow field. - -template -class FilterTemporalParticleAdvection - : public vtkm::filter::FilterParticleAdvection -{ -public: - VTKM_CONT - FilterTemporalParticleAdvection(); - - VTKM_CONT - void SetPreviousTime(vtkm::FloatDefault t) { this->PreviousTime = t; } - VTKM_CONT - void SetNextTime(vtkm::FloatDefault t) { this->NextTime = t; } - - VTKM_CONT - void SetNextDataSet(const vtkm::cont::DataSet& ds) - { - this->NextDataSet = vtkm::cont::PartitionedDataSet(ds); - } - - VTKM_CONT - void SetNextDataSet(const vtkm::cont::PartitionedDataSet& pds) { this->NextDataSet = pds; } - - template - VTKM_CONT vtkm::cont::DataSet PrepareForExecution(const vtkm::cont::DataSet& input, - vtkm::filter::PolicyBase policy); - -protected: - VTKM_CONT void ValidateOptions(const vtkm::cont::PartitionedDataSet& input) const; - using vtkm::filter::FilterParticleAdvection::ValidateOptions; - - VTKM_CONT std::vector - CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::particleadvection::BoundsMap& boundsMap) const; - - vtkm::FloatDefault PreviousTime; - vtkm::FloatDefault NextTime; - vtkm::cont::PartitionedDataSet NextDataSet; - -private: -}; -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_FilterTemporalParticleAdvection_hxx -#include -#endif - -#endif // vtk_m_filter_FilterTemporalParticleAdvection_h diff --git a/vtkm/filter/FilterTemporalParticleAdvection.hxx b/vtkm/filter/FilterTemporalParticleAdvection.hxx deleted file mode 100644 index fa1e5b36c..000000000 --- a/vtkm/filter/FilterTemporalParticleAdvection.hxx +++ /dev/null @@ -1,83 +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. -//============================================================================ -#ifndef vtk_m_filter_FilterTemporalParticleAdvection_hxx -#define vtk_m_filter_FilterTemporalParticleAdvection_hxx - -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT -FilterTemporalParticleAdvection::FilterTemporalParticleAdvection() - : vtkm::filter::FilterParticleAdvection() - , PreviousTime(0) - , NextTime(0) -{ -} - -template -void FilterTemporalParticleAdvection::ValidateOptions( - const vtkm::cont::PartitionedDataSet& input) const -{ - this->vtkm::filter::FilterParticleAdvection::ValidateOptions(); - - if (this->NextDataSet.GetNumberOfPartitions() != input.GetNumberOfPartitions()) - throw vtkm::cont::ErrorFilterExecution("Number of partitions do not match"); - if (!(this->PreviousTime < this->NextTime)) - throw vtkm::cont::ErrorFilterExecution("Previous time must be less than Next time."); -} - -template -std::vector -FilterTemporalParticleAdvection::CreateDataSetIntegrators( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::particleadvection::BoundsMap& boundsMap) const -{ - using DSIType = vtkm::filter::particleadvection::TemporalDataSetIntegrator; - std::vector dsi; - std::string activeField = this->GetActiveFieldName(); - - if (boundsMap.GetTotalNumBlocks() == 0) - throw vtkm::cont::ErrorFilterExecution("No input datasets."); - - for (vtkm::Id i = 0; i < input.GetNumberOfPartitions(); i++) - { - vtkm::Id blockId = boundsMap.GetLocalBlockId(i); - auto dsPrev = input.GetPartition(i); - auto dsNext = this->NextDataSet.GetPartition(i); - if (!(dsPrev.HasPointField(activeField) || dsPrev.HasCellField(activeField)) || - !(dsNext.HasPointField(activeField) || dsNext.HasCellField(activeField))) - throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation"); - dsi.push_back( - DSIType(dsPrev, this->PreviousTime, dsNext, this->NextTime, blockId, activeField)); - } - - return dsi; -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::DataSet -FilterTemporalParticleAdvection::PrepareForExecution( - const vtkm::cont::DataSet& input, - vtkm::filter::PolicyBase policy) -{ - return (static_cast(this))->DoExecute(input, policy); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/Lagrangian.hxx b/vtkm/filter/Lagrangian.hxx index 260b63c7e..f0bd02539 100644 --- a/vtkm/filter/Lagrangian.hxx +++ b/vtkm/filter/Lagrangian.hxx @@ -21,13 +21,13 @@ #include #include #include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include #include #include @@ -274,13 +274,13 @@ inline VTKM_CONT vtkm::cont::DataSet Lagrangian::DoExecute( vtkm::Bounds bounds = input.GetCoordinateSystem().GetBounds(); using FieldHandle = vtkm::cont::ArrayHandle, StorageType>; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; - vtkm::worklet::ParticleAdvection particleadvection; - vtkm::worklet::ParticleAdvectionResult res; + vtkm::worklet::flow::ParticleAdvection particleadvection; + vtkm::worklet::flow::ParticleAdvectionResult res; FieldType velocities(field, fieldMeta.GetAssociation()); GridEvalType gridEval(coords, cells, velocities); diff --git a/vtkm/filter/LagrangianDummy.cxx b/vtkm/filter/LagrangianDummy.cxx new file mode 100644 index 000000000..f7ff44da2 --- /dev/null +++ b/vtkm/filter/LagrangianDummy.cxx @@ -0,0 +1,9 @@ +//============================================================================ +// 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. +//============================================================================ diff --git a/vtkm/filter/LagrangianStructures.h b/vtkm/filter/LagrangianStructures.h index 9d1c2293c..0b7bff84f 100644 --- a/vtkm/filter/LagrangianStructures.h +++ b/vtkm/filter/LagrangianStructures.h @@ -15,9 +15,9 @@ #include -#include -#include -#include +#include +#include +#include namespace vtkm { diff --git a/vtkm/filter/LagrangianStructures.hxx b/vtkm/filter/LagrangianStructures.hxx index ed2cafad8..24f747392 100644 --- a/vtkm/filter/LagrangianStructures.hxx +++ b/vtkm/filter/LagrangianStructures.hxx @@ -14,11 +14,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include @@ -79,10 +79,10 @@ inline VTKM_CONT vtkm::cont::DataSet LagrangianStructures::DoExecute( using Structured3DType = vtkm::cont::CellSetStructured<3>; using FieldHandle = vtkm::cont::ArrayHandle, StorageType>; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvaluator = vtkm::worklet::particleadvection::GridEvaluator; - using IntegratorType = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvaluator = vtkm::worklet::flow::GridEvaluator; + using IntegratorType = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; vtkm::FloatDefault stepSize = this->GetStepSize(); vtkm::Id numberOfSteps = this->GetNumberOfSteps(); @@ -135,8 +135,8 @@ inline VTKM_CONT vtkm::cont::DataSet LagrangianStructures::DoExecute( FieldType velocities(field, fieldMeta.GetAssociation()); GridEvaluator evaluator(input.GetCoordinateSystem(), input.GetCellSet(), velocities); Stepper integrator(evaluator, stepSize); - vtkm::worklet::ParticleAdvection particles; - vtkm::worklet::ParticleAdvectionResult advectionResult; + vtkm::worklet::flow::ParticleAdvection particles; + vtkm::worklet::flow::ParticleAdvectionResult advectionResult; vtkm::cont::ArrayHandle advectionPoints; invoke(detail::MakeParticles{}, lcsInputPoints, advectionPoints); advectionResult = particles.Run(integrator, advectionPoints, numberOfSteps); diff --git a/vtkm/filter/ParticleAdvection.h b/vtkm/filter/ParticleAdvection.h deleted file mode 100644 index e43deb087..000000000 --- a/vtkm/filter/ParticleAdvection.h +++ /dev/null @@ -1,47 +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. -//============================================================================ - -#ifndef vtk_m_filter_ParticleAdvection_h -#define vtk_m_filter_ParticleAdvection_h - -#include -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief Advect particles in a vector field. - -/// Takes as input a vector field and seed locations and generates the -/// end points for each seed through the vector field. - -template -class ParticleAdvectionBase - : public vtkm::filter::FilterParticleAdvection, ParticleType> -{ -public: - VTKM_CONT ParticleAdvectionBase(); - - template - vtkm::cont::PartitionedDataSet PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase& policy); -}; - -using ParticleAdvection = ParticleAdvectionBase; -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_ParticleAdvection_hxx -#include -#endif - -#endif // vtk_m_filter_ParticleAdvection_h diff --git a/vtkm/filter/ParticleAdvection.hxx b/vtkm/filter/ParticleAdvection.hxx deleted file mode 100644 index 3b910b592..000000000 --- a/vtkm/filter/ParticleAdvection.hxx +++ /dev/null @@ -1,57 +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. -//============================================================================ -#ifndef vtk_m_filter_ParticleAdvection_hxx -#define vtk_m_filter_ParticleAdvection_hxx - -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT ParticleAdvectionBase::ParticleAdvectionBase() - : vtkm::filter::FilterParticleAdvection, ParticleType>() -{ -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::PartitionedDataSet -ParticleAdvectionBase::PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase&) -{ - using AlgorithmType = vtkm::filter::particleadvection::ParticleAdvectionAlgorithm; - using ThreadedAlgorithmType = vtkm::filter::particleadvection::ParticleAdvectionThreadedAlgorithm; - using DSIType = vtkm::filter::particleadvection::DataSetIntegrator; - - this->ValidateOptions(); - vtkm::filter::particleadvection::BoundsMap boundsMap(input); - auto dsi = this->CreateDataSetIntegrators(input, boundsMap); - - if (this->GetUseThreadedAlgorithm()) - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); - else - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/PathParticle.h b/vtkm/filter/PathParticle.h deleted file mode 100644 index fbf449a55..000000000 --- a/vtkm/filter/PathParticle.h +++ /dev/null @@ -1,51 +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. -//============================================================================ - -#ifndef vtk_m_filter_PathParticle_h -#define vtk_m_filter_PathParticle_h - -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief Advect particles in a time varying vector field. - -/// Takes as input a vector field and seed locations and generates the -/// paths taken by the seeds through the vector field. -template -class PathParticleBase - : public vtkm::filter::FilterTemporalParticleAdvection, - ParticleType> -{ -public: - VTKM_CONT - PathParticleBase(); - - template - vtkm::cont::PartitionedDataSet PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase& policy); - -protected: -private: -}; - -using PathParticle = PathParticleBase; - -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_PathParticle_hxx -#include -#endif - -#endif // vtk_m_filter_PathParticle_h diff --git a/vtkm/filter/PathParticle.hxx b/vtkm/filter/PathParticle.hxx deleted file mode 100644 index aa82da0ef..000000000 --- a/vtkm/filter/PathParticle.hxx +++ /dev/null @@ -1,58 +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. -//============================================================================ - -#ifndef vtk_m_filter_PathParticle_hxx -#define vtk_m_filter_PathParticle_hxx - -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT PathParticleBase::PathParticleBase() - : vtkm::filter::FilterTemporalParticleAdvection, ParticleType>() -{ -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::PartitionedDataSet PathParticleBase::PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase&) -{ - using AlgorithmType = vtkm::filter::particleadvection::PathParticleAlgorithm; - using ThreadedAlgorithmType = vtkm::filter::particleadvection::PathParticleThreadedAlgorithm; - using TDSIType = vtkm::filter::particleadvection::TemporalDataSetIntegrator; - - this->ValidateOptions(input); - - vtkm::filter::particleadvection::BoundsMap boundsMap(input); - auto dsi = this->CreateDataSetIntegrators(input, boundsMap); - - if (this->GetUseThreadedAlgorithm()) - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); - else - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/Pathline.h b/vtkm/filter/Pathline.h deleted file mode 100644 index 87193eb9c..000000000 --- a/vtkm/filter/Pathline.h +++ /dev/null @@ -1,50 +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. -//============================================================================ - -#ifndef vtk_m_filter_Pathline_h -#define vtk_m_filter_Pathline_h - -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief generate pathlines from a time sequence of vector fields. - -/// Takes as input a vector field and seed locations and generates the -/// paths taken by the seeds through the vector field. -template -class PathlineBase - : public vtkm::filter::FilterTemporalParticleAdvection, ParticleType> -{ -public: - VTKM_CONT - PathlineBase(); - - template - vtkm::cont::PartitionedDataSet PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase& policy); - -protected: -private: -}; - -using Pathline = PathlineBase; - -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_Pathline_hxx -#include -#endif - -#endif // vtk_m_filter_Pathline_h diff --git a/vtkm/filter/Pathline.hxx b/vtkm/filter/Pathline.hxx deleted file mode 100644 index a25476b7c..000000000 --- a/vtkm/filter/Pathline.hxx +++ /dev/null @@ -1,58 +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. -//============================================================================ - -#ifndef vtk_m_filter_Pathline_hxx -#define vtk_m_filter_Pathline_hxx - -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT PathlineBase::PathlineBase() - : vtkm::filter::FilterTemporalParticleAdvection, ParticleType>() -{ -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::PartitionedDataSet PathlineBase::PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase&) -{ - using AlgorithmType = vtkm::filter::particleadvection::PathlineAlgorithm; - using ThreadedAlgorithmType = vtkm::filter::particleadvection::PathlineThreadedAlgorithm; - using TDSIType = vtkm::filter::particleadvection::TemporalDataSetIntegrator; - - this->ValidateOptions(input); - - vtkm::filter::particleadvection::BoundsMap boundsMap(input); - auto dsi = this->CreateDataSetIntegrators(input, boundsMap); - - if (this->GetUseThreadedAlgorithm()) - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); - else - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/StreamSurface.h b/vtkm/filter/StreamSurface.h deleted file mode 100644 index bfb2dcdc4..000000000 --- a/vtkm/filter/StreamSurface.h +++ /dev/null @@ -1,70 +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. -//============================================================================ - -#ifndef vtk_m_filter_StreamSurface_h -#define vtk_m_filter_StreamSurface_h - -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief generate streamlines from a vector field. - -/// Takes as input a vector field and seed locations and generates the -/// paths taken by the seeds through the vector field. -class StreamSurface : public vtkm::filter::FilterDataSetWithField -{ -public: - using SupportedTypes = vtkm::TypeListFieldVec3; - - VTKM_CONT - StreamSurface(); - - VTKM_CONT - void SetStepSize(vtkm::FloatDefault s) { this->StepSize = s; } - - VTKM_CONT - void SetNumberOfSteps(vtkm::Id n) { this->NumberOfSteps = n; } - - VTKM_CONT - void SetSeeds(vtkm::cont::ArrayHandle& seeds) { this->Seeds = seeds; } - - template - VTKM_CONT vtkm::cont::DataSet DoExecute( - const vtkm::cont::DataSet& input, - const vtkm::cont::ArrayHandle, StorageType>& field, - const vtkm::filter::FieldMetadata& fieldMeta, - const vtkm::filter::PolicyBase& policy); - - template - VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result, - const vtkm::cont::Field& field, - vtkm::filter::PolicyBase policy); - -private: - vtkm::Id NumberOfSteps; - vtkm::cont::ArrayHandle Seeds; - vtkm::FloatDefault StepSize; - vtkm::worklet::StreamSurface Worklet; -}; -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_StreamSurface_hxx -#include -#endif - -#endif // vtk_m_filter_StreamSurface_h diff --git a/vtkm/filter/StreamSurface.hxx b/vtkm/filter/StreamSurface.hxx deleted file mode 100644 index 6e21f6452..000000000 --- a/vtkm/filter/StreamSurface.hxx +++ /dev/null @@ -1,95 +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. -//============================================================================ - -#ifndef vtk_m_filter_StreamSurface_hxx -#define vtk_m_filter_StreamSurface_hxx - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -inline VTKM_CONT StreamSurface::StreamSurface() - : vtkm::filter::FilterDataSetWithField() - , Worklet() -{ -} - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT vtkm::cont::DataSet StreamSurface::DoExecute( - const vtkm::cont::DataSet& input, - const vtkm::cont::ArrayHandle, StorageType>& field, - const vtkm::filter::FieldMetadata& fieldMeta, - const vtkm::filter::PolicyBase&) -{ - //Check for some basics. - if (this->Seeds.GetNumberOfValues() == 0) - throw vtkm::cont::ErrorFilterExecution("No seeds provided."); - - const vtkm::cont::UnknownCellSet& cells = input.GetCellSet(); - const vtkm::cont::CoordinateSystem& coords = - input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()); - - using FieldHandle = vtkm::cont::ArrayHandle, StorageType>; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; - - //compute streamlines - FieldType velocities(field, fieldMeta.GetAssociation()); - GridEvalType eval(coords, cells, velocities); - Stepper rk4(eval, this->StepSize); - - vtkm::worklet::Streamline streamline; - - vtkm::cont::ArrayHandle seedArray; - vtkm::cont::ArrayCopy(this->Seeds, seedArray); - auto res = streamline.Run(rk4, seedArray, this->NumberOfSteps); - - //compute surface from streamlines - vtkm::cont::ArrayHandle srfPoints; - vtkm::cont::CellSetSingleType<> srfCells; - vtkm::cont::CoordinateSystem slCoords("coordinates", res.Positions); - this->Worklet.Run(slCoords, res.PolyLines, srfPoints, srfCells); - - vtkm::cont::DataSet outData; - vtkm::cont::CoordinateSystem outputCoords("coordinates", srfPoints); - outData.AddCoordinateSystem(outputCoords); - outData.SetCellSet(srfCells); - - return outData; -} - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT bool StreamSurface::MapFieldOntoOutput(vtkm::cont::DataSet&, - const vtkm::cont::Field&, - vtkm::filter::PolicyBase) -{ - return false; -} -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/Streamline.h b/vtkm/filter/Streamline.h deleted file mode 100644 index d6b7c01ef..000000000 --- a/vtkm/filter/Streamline.h +++ /dev/null @@ -1,48 +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. -//============================================================================ - -#ifndef vtk_m_filter_Streamline_h -#define vtk_m_filter_Streamline_h - -#include - -namespace vtkm -{ -namespace filter -{ -/// \brief Generate streamlines from a vector field. - -/// Takes as input a vector field and seed locations and generates the -/// paths taken by the seeds through the vector field. -template -class StreamlineBase - : public vtkm::filter::FilterParticleAdvection, ParticleType> -{ -public: - VTKM_CONT - StreamlineBase(); - - template - vtkm::cont::PartitionedDataSet PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase& policy); - -private: -}; - -using Streamline = StreamlineBase; -} -} // namespace vtkm::filter - -#ifndef vtk_m_filter_Streamline_hxx -#include -#endif - -#endif // vtk_m_filter_Streamline_h diff --git a/vtkm/filter/Streamline.hxx b/vtkm/filter/Streamline.hxx deleted file mode 100644 index 86316193a..000000000 --- a/vtkm/filter/Streamline.hxx +++ /dev/null @@ -1,56 +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. -//============================================================================ -#ifndef vtk_m_filter_Streamline_hxx -#define vtk_m_filter_Streamline_hxx - -#include -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ - -//----------------------------------------------------------------------------- -template -inline VTKM_CONT StreamlineBase::StreamlineBase() - : vtkm::filter::FilterParticleAdvection, ParticleType>() -{ -} - -//----------------------------------------------------------------------------- -template -template -inline VTKM_CONT vtkm::cont::PartitionedDataSet StreamlineBase::PrepareForExecution( - const vtkm::cont::PartitionedDataSet& input, - const vtkm::filter::PolicyBase&) -{ - using AlgorithmType = vtkm::filter::particleadvection::StreamlineAlgorithm; - using ThreadedAlgorithmType = vtkm::filter::particleadvection::StreamlineThreadedAlgorithm; - using DSIType = vtkm::filter::particleadvection::DataSetIntegrator; - - this->ValidateOptions(); - vtkm::filter::particleadvection::BoundsMap boundsMap(input); - auto dsi = this->CreateDataSetIntegrators(input, boundsMap); - - if (this->GetUseThreadedAlgorithm()) - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); - else - return vtkm::filter::particleadvection::RunAlgo( - boundsMap, dsi, this->NumberOfSteps, this->StepSize, this->Seeds); -} - -} -} // namespace vtkm::filter -#endif diff --git a/vtkm/filter/entity_extraction/GhostCellRemove.cxx b/vtkm/filter/entity_extraction/GhostCellRemove.cxx index e6eadd9e3..576d0cf51 100644 --- a/vtkm/filter/entity_extraction/GhostCellRemove.cxx +++ b/vtkm/filter/entity_extraction/GhostCellRemove.cxx @@ -308,8 +308,9 @@ namespace entity_extraction //----------------------------------------------------------------------------- VTKM_CONT GhostCellRemove::GhostCellRemove() { - this->SetActiveField("vtkmGhostCells"); - this->SetFieldsToPass("vtkmGhostCells", vtkm::filter::FieldSelection::Mode::Exclude); + this->SetActiveField(vtkm::cont::GetGlobalGhostCellFieldName()); + this->SetFieldsToPass(vtkm::cont::GetGlobalGhostCellFieldName(), + vtkm::filter::FieldSelection::Mode::Exclude); } //----------------------------------------------------------------------------- diff --git a/vtkm/filter/entity_extraction/testing/UnitTestGhostCellRemove.cxx b/vtkm/filter/entity_extraction/testing/UnitTestGhostCellRemove.cxx index 0d2f0354e..c05912251 100644 --- a/vtkm/filter/entity_extraction/testing/UnitTestGhostCellRemove.cxx +++ b/vtkm/filter/entity_extraction/testing/UnitTestGhostCellRemove.cxx @@ -94,7 +94,7 @@ vtkm::cont::DataSet MakeUniform(vtkm::Id numI, ds = vtkm::cont::DataSetBuilderUniform::Create(vtkm::Id3(numI + 1, numJ + 1, numK + 1)); auto ghosts = StructuredGhostCellArray(numI, numJ, numK, numLayers, addMidGhost); - ds.AddCellField("vtkmGhostCells", ghosts); + ds.AddGhostCellField(ghosts); return ds; } @@ -128,7 +128,7 @@ vtkm::cont::DataSet MakeRectilinear(vtkm::Id numI, auto ghosts = StructuredGhostCellArray(numI, numJ, numK, numLayers, addMidGhost); - ds.AddCellField("vtkmGhostCells", ghosts); + ds.AddGhostCellField(ghosts); return ds; } @@ -205,7 +205,7 @@ vtkm::cont::DataSet MakeExplicit(vtkm::Id numI, vtkm::Id numJ, vtkm::Id numK, in auto ghosts = StructuredGhostCellArray(numI, numJ, numK, numLayers); - ds.AddCellField("vtkmGhostCells", ghosts); + ds.AddGhostCellField(ghosts); return ds; } diff --git a/vtkm/filter/flow/CMakeLists.txt b/vtkm/filter/flow/CMakeLists.txt new file mode 100644 index 000000000..7eb390a4b --- /dev/null +++ b/vtkm/filter/flow/CMakeLists.txt @@ -0,0 +1,57 @@ +##============================================================================ +## 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. +##============================================================================ +set(flow_headers + FlowTypes.h + NewFilterParticleAdvection.h + NewFilterParticleAdvectionSteadyState.h + NewFilterParticleAdvectionUnsteadyState.h + ParticleAdvection.h + Pathline.h + PathParticle.h + Streamline.h + StreamSurface.h + ) + +set(flow_sources + internal/Messenger.cxx + NewFilterParticleAdvection.cxx + ParticleAdvection.cxx + Pathline.cxx + PathParticle.cxx + Streamline.cxx + ) + +set(flow_device_sources + NewFilterParticleAdvectionSteadyState.cxx + NewFilterParticleAdvectionUnsteadyState.cxx + StreamSurface.cxx + ) + +vtkm_library( + NAME vtkm_filter_flow + HEADERS ${flow_headers} + SOURCES ${flow_sources} + DEVICE_SOURCES ${flow_device_sources} + USE_VTKM_JOB_POOL +) + +target_link_libraries(vtkm_filter_flow PUBLIC vtkm_worklet vtkm_filter_core) +target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_flow) +if (VTKm_ENABLE_MPI) + target_link_libraries(vtkm_filter_flow PUBLIC MPI::MPI_CXX) +endif() + +add_subdirectory(internal) +add_subdirectory(worklet) + +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +if (VTKm_ENABLE_TESTING) + add_subdirectory(testing) +endif () diff --git a/vtkm/filter/flow/FlowTypes.h b/vtkm/filter/flow/FlowTypes.h new file mode 100644 index 000000000..237f32fb4 --- /dev/null +++ b/vtkm/filter/flow/FlowTypes.h @@ -0,0 +1,42 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_filter_flow_FlowTypes_h +#define vtk_m_filter_flow_FlowTypes_h + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +enum class IntegrationSolverType +{ + RK4_TYPE = 0, + EULER_TYPE, +}; + +enum class VectorFieldType +{ + VELOCITY_FIELD_TYPE = 0, + ELECTRO_MAGNETIC_FIELD_TYPE, +}; + +enum FlowResultType +{ + UNKNOWN_TYPE = -1, + PARTICLE_ADVECT_TYPE, + STREAMLINE_TYPE, +}; + +} +} +} + +#endif // vtk_m_filter_flow_FlowTypes_h diff --git a/vtkm/filter/flow/NewFilterParticleAdvection.cxx b/vtkm/filter/flow/NewFilterParticleAdvection.cxx new file mode 100644 index 000000000..3ef938356 --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvection.cxx @@ -0,0 +1,54 @@ +//============================================================================ +// 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 +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +VTKM_CONT vtkm::cont::DataSet NewFilterParticleAdvection::DoExecute( + const vtkm::cont::DataSet& inData) +{ + auto out = this->DoExecutePartitions(inData); + if (out.GetNumberOfPartitions() != 1) + throw vtkm::cont::ErrorFilterExecution("Wrong number of results"); + + return out.GetPartition(0); +} + +VTKM_CONT void NewFilterParticleAdvection::ValidateOptions() const +{ + if (this->GetUseCoordinateSystemAsField()) + throw vtkm::cont::ErrorFilterExecution("Coordinate system as field not supported"); + if (this->Seeds.GetNumberOfValues() == 0) + throw vtkm::cont::ErrorFilterExecution("No seeds provided."); + if (!this->Seeds.IsBaseComponentType() && + this->Seeds.IsBaseComponentType()) + throw vtkm::cont::ErrorFilterExecution("Unsupported particle type in seed array."); + if (this->NumberOfSteps == 0) + throw vtkm::cont::ErrorFilterExecution("Number of steps not specified."); + if (this->StepSize == 0) + throw vtkm::cont::ErrorFilterExecution("Step size not specified."); + if (this->NumberOfSteps < 0) + throw vtkm::cont::ErrorFilterExecution("NumberOfSteps cannot be negative"); + if (this->StepSize < 0) + throw vtkm::cont::ErrorFilterExecution("StepSize cannot be negative"); +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/NewFilterParticleAdvection.h b/vtkm/filter/flow/NewFilterParticleAdvection.h new file mode 100644 index 000000000..ee18f6dbb --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvection.h @@ -0,0 +1,88 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_NewFilterParticleAdvection_h +#define vtk_m_filter_flow_NewFilterParticleAdvection_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief base class for advecting particles in a vector field. + +/// Takes as input a vector field and seed locations and advects the seeds +/// through the flow field. + +class VTKM_FILTER_FLOW_EXPORT NewFilterParticleAdvection : public vtkm::filter::NewFilterField +{ +public: + VTKM_CONT + void SetStepSize(vtkm::FloatDefault s) { this->StepSize = s; } + + VTKM_CONT + void SetNumberOfSteps(vtkm::Id n) { this->NumberOfSteps = n; } + + template + VTKM_CONT void SetSeeds(vtkm::cont::ArrayHandle& seeds) + { + this->Seeds = seeds; + } + + template + VTKM_CONT void SetSeeds(const std::vector& seeds, + vtkm::CopyFlag copyFlag = vtkm::CopyFlag::On) + { + this->Seeds = vtkm::cont::make_ArrayHandle(seeds, copyFlag); + } + + VTKM_CONT + void SetSolverRK4() { this->SolverType = vtkm::filter::flow::IntegrationSolverType::RK4_TYPE; } + VTKM_CONT + void SetSolverEuler() + { + this->SolverType = vtkm::filter::flow::IntegrationSolverType::EULER_TYPE; + } + + VTKM_CONT + bool GetUseThreadedAlgorithm() { return this->UseThreadedAlgorithm; } + + VTKM_CONT + void SetUseThreadedAlgorithm(bool val) { this->UseThreadedAlgorithm = val; } + +protected: + VTKM_CONT virtual void ValidateOptions() const; + + VTKM_CONT virtual vtkm::filter::flow::FlowResultType GetResultType() const = 0; + + vtkm::Id NumberOfSteps = 0; + vtkm::cont::UnknownArrayHandle Seeds; + vtkm::filter::flow::IntegrationSolverType SolverType = + vtkm::filter::flow::IntegrationSolverType::RK4_TYPE; + vtkm::FloatDefault StepSize = 0; + bool UseThreadedAlgorithm = false; + vtkm::filter::flow::VectorFieldType VecFieldType = + vtkm::filter::flow::VectorFieldType::VELOCITY_FIELD_TYPE; + +private: + VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_NewFilterParticleAdvection_h diff --git a/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.cxx b/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.cxx new file mode 100644 index 000000000..fbee0fa1c --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.cxx @@ -0,0 +1,73 @@ +//============================================================================ +// 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 +#include + +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +namespace +{ +VTKM_CONT std::vector +CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input, + const std::string& activeField, + const vtkm::filter::flow::internal::BoundsMap& boundsMap, + const vtkm::filter::flow::IntegrationSolverType solverType, + const vtkm::filter::flow::VectorFieldType vecFieldType, + const vtkm::filter::flow::FlowResultType resultType) +{ + using DSIType = vtkm::filter::flow::internal::DataSetIntegratorSteadyState; + + std::vector dsi; + for (vtkm::Id i = 0; i < input.GetNumberOfPartitions(); i++) + { + vtkm::Id blockId = boundsMap.GetLocalBlockId(i); + auto ds = input.GetPartition(i); + if (!ds.HasPointField(activeField) && !ds.HasCellField(activeField)) + throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation"); + + dsi.emplace_back(ds, blockId, activeField, solverType, vecFieldType, resultType); + } + + return dsi; +} +} //anonymous namespace + +VTKM_CONT vtkm::cont::PartitionedDataSet NewFilterParticleAdvectionSteadyState::DoExecutePartitions( + const vtkm::cont::PartitionedDataSet& input) +{ + using DSIType = vtkm::filter::flow::internal::DataSetIntegratorSteadyState; + this->ValidateOptions(); + + vtkm::filter::flow::internal::BoundsMap boundsMap(input); + auto dsi = CreateDataSetIntegrators(input, + this->GetActiveFieldName(), + boundsMap, + this->SolverType, + this->VecFieldType, + this->GetResultType()); + + vtkm::filter::flow::internal::ParticleAdvector pav( + boundsMap, dsi, this->UseThreadedAlgorithm, this->GetResultType()); + + return pav.Execute(this->NumberOfSteps, this->StepSize, this->Seeds); +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.h b/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.h new file mode 100644 index 000000000..ed0731301 --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvectionSteadyState.h @@ -0,0 +1,36 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_NewFilterParticleAdvectionSteadyState_h +#define vtk_m_filter_flow_NewFilterParticleAdvectionSteadyState_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +class VTKM_FILTER_FLOW_EXPORT NewFilterParticleAdvectionSteadyState + : public NewFilterParticleAdvection +{ +private: + VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions( + const vtkm::cont::PartitionedDataSet& inData) override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_NewFilterParticleAdvectionSteadyState_h diff --git a/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.cxx b/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.cxx new file mode 100644 index 000000000..b2df0b8e4 --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.cxx @@ -0,0 +1,87 @@ +//============================================================================ +// 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 +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace +{ +VTKM_CONT std::vector +CreateDataSetIntegrators(const vtkm::cont::PartitionedDataSet& input, + const vtkm::cont::PartitionedDataSet& input2, + const std::string& activeField, + const vtkm::FloatDefault timer1, + const vtkm::FloatDefault timer2, + const vtkm::filter::flow::internal::BoundsMap& boundsMap, + const vtkm::filter::flow::IntegrationSolverType solverType, + const vtkm::filter::flow::VectorFieldType vecFieldType, + const vtkm::filter::flow::FlowResultType resultType) +{ + using DSIType = vtkm::filter::flow::internal::DataSetIntegratorUnsteadyState; + + std::vector dsi; + for (vtkm::Id i = 0; i < input.GetNumberOfPartitions(); i++) + { + vtkm::Id blockId = boundsMap.GetLocalBlockId(i); + auto ds1 = input.GetPartition(i); + auto ds2 = input2.GetPartition(i); + if ((!ds1.HasPointField(activeField) && !ds1.HasCellField(activeField)) || + (!ds2.HasPointField(activeField) && !ds2.HasCellField(activeField))) + throw vtkm::cont::ErrorFilterExecution("Unsupported field assocation"); + + dsi.emplace_back( + ds1, ds2, timer1, timer2, blockId, activeField, solverType, vecFieldType, resultType); + } + + return dsi; +} +} // anonymous namespace + +VTKM_CONT void NewFilterParticleAdvectionUnsteadyState::ValidateOptions() const +{ + this->NewFilterParticleAdvection::ValidateOptions(); + if (this->Time1 >= this->Time2) + throw vtkm::cont::ErrorFilterExecution("PreviousTime must be less than NextTime"); +} + +VTKM_CONT vtkm::cont::PartitionedDataSet +NewFilterParticleAdvectionUnsteadyState::DoExecutePartitions( + const vtkm::cont::PartitionedDataSet& input) +{ + using DSIType = vtkm::filter::flow::internal::DataSetIntegratorUnsteadyState; + this->ValidateOptions(); + + vtkm::filter::flow::internal::BoundsMap boundsMap(input); + auto dsi = CreateDataSetIntegrators(input, + this->Input2, + this->GetActiveFieldName(), + this->Time1, + this->Time2, + boundsMap, + this->SolverType, + this->VecFieldType, + this->GetResultType()); + + vtkm::filter::flow::internal::ParticleAdvector pav( + boundsMap, dsi, this->UseThreadedAlgorithm, this->GetResultType()); + + return pav.Execute(this->NumberOfSteps, this->StepSize, this->Seeds); +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.h b/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.h new file mode 100644 index 000000000..d1d959329 --- /dev/null +++ b/vtkm/filter/flow/NewFilterParticleAdvectionUnsteadyState.h @@ -0,0 +1,52 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_NewFilterParticleAdvectionUnsteadyState_h +#define vtk_m_filter_flow_NewFilterParticleAdvectionUnsteadyState_h + +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +class VTKM_FILTER_FLOW_EXPORT NewFilterParticleAdvectionUnsteadyState + : public NewFilterParticleAdvection +{ +public: + VTKM_CONT void SetPreviousTime(vtkm::FloatDefault t1) { this->Time1 = t1; } + + VTKM_CONT void SetNextTime(vtkm::FloatDefault t2) { this->Time2 = t2; } + + VTKM_CONT void SetNextDataSet(const vtkm::cont::DataSet& ds) { this->Input2 = { ds }; } + + VTKM_CONT void SetNextDataSet(const vtkm::cont::PartitionedDataSet& pds) { this->Input2 = pds; } + +protected: + VTKM_CONT virtual void ValidateOptions() const override; + +private: + VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions( + const vtkm::cont::PartitionedDataSet& inData) override; + + vtkm::cont::PartitionedDataSet Input2; + vtkm::FloatDefault Time1 = -1; + vtkm::FloatDefault Time2 = -1; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_NewFilterParticleAdvectionUnsteadyState_h diff --git a/vtkm/filter/flow/ParticleAdvection.cxx b/vtkm/filter/flow/ParticleAdvection.cxx new file mode 100644 index 000000000..d833b2289 --- /dev/null +++ b/vtkm/filter/flow/ParticleAdvection.cxx @@ -0,0 +1,27 @@ +//============================================================================ +// 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 filter +{ +namespace flow +{ + +VTKM_CONT vtkm::filter::flow::FlowResultType ParticleAdvection::GetResultType() const +{ + return vtkm::filter::flow::FlowResultType::PARTICLE_ADVECT_TYPE; +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/ParticleAdvection.h b/vtkm/filter/flow/ParticleAdvection.h new file mode 100644 index 000000000..12f5aaf3d --- /dev/null +++ b/vtkm/filter/flow/ParticleAdvection.h @@ -0,0 +1,42 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_ParticleAdvection_h +#define vtk_m_filter_flow_ParticleAdvection_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief Advect particles in a vector field. + +/// Takes as input a vector field and seed locations and generates the +/// end points for each seed through the vector field. + +class VTKM_FILTER_FLOW_EXPORT ParticleAdvection + : public vtkm::filter::flow::NewFilterParticleAdvectionSteadyState +{ +public: +private: + VTKM_CONT vtkm::filter::flow::FlowResultType GetResultType() const override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_ParticleAdvection_h diff --git a/vtkm/filter/flow/PathParticle.cxx b/vtkm/filter/flow/PathParticle.cxx new file mode 100644 index 000000000..f6c0f63a1 --- /dev/null +++ b/vtkm/filter/flow/PathParticle.cxx @@ -0,0 +1,27 @@ +//============================================================================ +// 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 filter +{ +namespace flow +{ + +VTKM_CONT vtkm::filter::flow::FlowResultType PathParticle::GetResultType() const +{ + return vtkm::filter::flow::FlowResultType::PARTICLE_ADVECT_TYPE; +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/PathParticle.h b/vtkm/filter/flow/PathParticle.h new file mode 100644 index 000000000..8f2c99c37 --- /dev/null +++ b/vtkm/filter/flow/PathParticle.h @@ -0,0 +1,41 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_PathParticle_h +#define vtk_m_filter_PathParticle_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief Advect particles in a vector field. + +/// Takes as input a vector field and seed locations and generates the +/// end points for each seed through the vector field. + +class VTKM_FILTER_FLOW_EXPORT PathParticle + : public vtkm::filter::flow::NewFilterParticleAdvectionUnsteadyState +{ +private: + VTKM_CONT vtkm::filter::flow::FlowResultType GetResultType() const override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_PathParticle_h diff --git a/vtkm/filter/flow/Pathline.cxx b/vtkm/filter/flow/Pathline.cxx new file mode 100644 index 000000000..ada93727f --- /dev/null +++ b/vtkm/filter/flow/Pathline.cxx @@ -0,0 +1,27 @@ +//============================================================================ +// 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 filter +{ +namespace flow +{ + +VTKM_CONT vtkm::filter::flow::FlowResultType Pathline::GetResultType() const +{ + return vtkm::filter::flow::FlowResultType::STREAMLINE_TYPE; +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/Pathline.h b/vtkm/filter/flow/Pathline.h new file mode 100644 index 000000000..e92cc5dc0 --- /dev/null +++ b/vtkm/filter/flow/Pathline.h @@ -0,0 +1,41 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_Pathline_h +#define vtk_m_filter_Pathline_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief Advect particles in a vector field. + +/// Takes as input a vector field and seed locations and generates the +/// end points for each seed through the vector field. + +class VTKM_FILTER_FLOW_EXPORT Pathline + : public vtkm::filter::flow::NewFilterParticleAdvectionUnsteadyState +{ +private: + VTKM_CONT vtkm::filter::flow::FlowResultType GetResultType() const override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_Pathline_h diff --git a/vtkm/filter/flow/StreamSurface.cxx b/vtkm/filter/flow/StreamSurface.cxx new file mode 100644 index 000000000..23fec8b93 --- /dev/null +++ b/vtkm/filter/flow/StreamSurface.cxx @@ -0,0 +1,92 @@ +//============================================================================ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +VTKM_CONT vtkm::cont::DataSet StreamSurface::DoExecute(const vtkm::cont::DataSet& input) +{ + //Validate inputs. + if (this->GetUseCoordinateSystemAsField()) + throw vtkm::cont::ErrorFilterExecution("Coordinate system as field not supported"); + if (this->Seeds.GetNumberOfValues() == 0) + throw vtkm::cont::ErrorFilterExecution("No seeds provided."); + if (!this->Seeds.IsBaseComponentType() && + this->Seeds.IsBaseComponentType()) + throw vtkm::cont::ErrorFilterExecution("Unsupported particle type in seed array."); + if (this->NumberOfSteps == 0) + throw vtkm::cont::ErrorFilterExecution("Number of steps not specified."); + if (this->StepSize == 0) + throw vtkm::cont::ErrorFilterExecution("Step size not specified."); + if (this->NumberOfSteps < 0) + throw vtkm::cont::ErrorFilterExecution("NumberOfSteps cannot be negative"); + if (this->StepSize < 0) + throw vtkm::cont::ErrorFilterExecution("StepSize cannot be negative"); + + if (!this->Seeds.IsBaseComponentType()) + throw vtkm::cont::ErrorFilterExecution("Unsupported seed type in StreamSurface filter."); + + const vtkm::cont::UnknownCellSet& cells = input.GetCellSet(); + const vtkm::cont::CoordinateSystem& coords = + input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()); + + using FieldHandle = vtkm::cont::ArrayHandle; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; + + //compute streamlines + const auto& field = input.GetField(this->GetActiveFieldName()); + FieldHandle arr; + vtkm::cont::ArrayCopyShallowIfPossible(field.GetData(), arr); + FieldType velocities(arr, field.GetAssociation()); + GridEvalType eval(coords, cells, velocities); + Stepper rk4(eval, this->StepSize); + + vtkm::worklet::flow::Streamline streamline; + + using ParticleArray = vtkm::cont::ArrayHandle; + vtkm::cont::ArrayHandle seedArray; + vtkm::cont::ArrayCopy(this->Seeds.AsArrayHandle(), seedArray); + auto res = streamline.Run(rk4, seedArray, this->NumberOfSteps); + + //compute surface from streamlines + vtkm::worklet::flow::StreamSurface streamSurface; + vtkm::cont::ArrayHandle srfPoints; + vtkm::cont::CellSetSingleType<> srfCells; + vtkm::cont::CoordinateSystem slCoords("coordinates", res.Positions); + streamSurface.Run(slCoords, res.PolyLines, srfPoints, srfCells); + + vtkm::cont::DataSet outData; + vtkm::cont::CoordinateSystem outputCoords("coordinates", srfPoints); + outData.AddCoordinateSystem(outputCoords); + outData.SetCellSet(srfCells); + + return outData; +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/StreamSurface.h b/vtkm/filter/flow/StreamSurface.h new file mode 100644 index 000000000..b1c56a37b --- /dev/null +++ b/vtkm/filter/flow/StreamSurface.h @@ -0,0 +1,64 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_StreamSurface_h +#define vtk_m_filter_flow_StreamSurface_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief generate streamlines from a vector field. + +/// Takes as input a vector field and seed locations and generates the +/// paths taken by the seeds through the vector field. + +class VTKM_FILTER_FLOW_EXPORT StreamSurface : public vtkm::filter::NewFilterField +{ +public: + VTKM_CONT + void SetStepSize(vtkm::FloatDefault s) { this->StepSize = s; } + + VTKM_CONT + void SetNumberOfSteps(vtkm::Id n) { this->NumberOfSteps = n; } + + template + VTKM_CONT void SetSeeds(vtkm::cont::ArrayHandle& seeds) + { + this->Seeds = seeds; + } + + template + VTKM_CONT void SetSeeds(const std::vector& seeds, + vtkm::CopyFlag copyFlag = vtkm::CopyFlag::On) + { + this->Seeds = vtkm::cont::make_ArrayHandle(seeds, copyFlag); + } + +private: + VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) override; + + vtkm::Id NumberOfSteps = 0; + vtkm::cont::UnknownArrayHandle Seeds; + vtkm::FloatDefault StepSize = 0; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_StreamSurface_h diff --git a/vtkm/filter/flow/Streamline.cxx b/vtkm/filter/flow/Streamline.cxx new file mode 100644 index 000000000..d5789f197 --- /dev/null +++ b/vtkm/filter/flow/Streamline.cxx @@ -0,0 +1,27 @@ +//============================================================================ +// 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 filter +{ +namespace flow +{ + +VTKM_CONT vtkm::filter::flow::FlowResultType Streamline::GetResultType() const +{ + return vtkm::filter::flow::FlowResultType::STREAMLINE_TYPE; +} + +} +} +} // namespace vtkm::filter::flow diff --git a/vtkm/filter/flow/Streamline.h b/vtkm/filter/flow/Streamline.h new file mode 100644 index 000000000..d4633f0e0 --- /dev/null +++ b/vtkm/filter/flow/Streamline.h @@ -0,0 +1,41 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_Streamline_h +#define vtk_m_filter_flow_Streamline_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ + +/// \brief Advect particles in a vector field. + +/// Takes as input a vector field and seed locations and generates the +/// end points for each seed through the vector field. + +class VTKM_FILTER_FLOW_EXPORT Streamline + : public vtkm::filter::flow::NewFilterParticleAdvectionSteadyState +{ +private: + VTKM_CONT vtkm::filter::flow::FlowResultType GetResultType() const override; +}; + +} +} +} // namespace vtkm::filter::flow + +#endif // vtk_m_filter_flow_Streamline_h diff --git a/vtkm/filter/flow/internal/AdvectAlgorithm.h b/vtkm/filter/flow/internal/AdvectAlgorithm.h new file mode 100644 index 000000000..33d38d4b5 --- /dev/null +++ b/vtkm/filter/flow/internal/AdvectAlgorithm.h @@ -0,0 +1,284 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_AdvectAlgorithm_h +#define vtk_m_filter_flow_internal_AdvectAlgorithm_h + +#include +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +template class ResultType, typename ParticleType> +class AdvectAlgorithm +{ +public: + AdvectAlgorithm(const vtkm::filter::flow::internal::BoundsMap& bm, std::vector& blocks) + : Blocks(blocks) + , BoundsMap(bm) + , NumRanks(this->Comm.size()) + , Rank(this->Comm.rank()) + { + } + + void Execute(vtkm::Id numSteps, + vtkm::FloatDefault stepSize, + const vtkm::cont::ArrayHandle& seeds) + { + this->SetNumberOfSteps(numSteps); + this->SetStepSize(stepSize); + this->SetSeeds(seeds); + this->Go(); + } + + vtkm::cont::PartitionedDataSet GetOutput() const + { + vtkm::cont::PartitionedDataSet output; + + for (const auto& b : this->Blocks) + { + vtkm::cont::DataSet ds; + if (b.template GetOutput(ds)) + output.AppendPartition(ds); + } + + return output; + } + + void SetStepSize(vtkm::FloatDefault stepSize) { this->StepSize = stepSize; } + void SetNumberOfSteps(vtkm::Id numSteps) { this->NumberOfSteps = numSteps; } + void SetSeeds(const vtkm::cont::ArrayHandle& seeds) + { + this->ClearParticles(); + + vtkm::Id n = seeds.GetNumberOfValues(); + auto portal = seeds.ReadPortal(); + + std::vector> blockIDs; + std::vector particles; + for (vtkm::Id i = 0; i < n; i++) + { + const ParticleType p = portal.Get(i); + std::vector ids = this->BoundsMap.FindBlocks(p.Pos); + + if (!ids.empty() && this->BoundsMap.FindRank(ids[0]) == this->Rank) + { + particles.emplace_back(p); + blockIDs.emplace_back(ids); + } + } + + this->SetSeedArray(particles, blockIDs); + } + + //Advect all the particles. + virtual void Go() + { + vtkm::filter::flow::internal::ParticleMessenger messenger( + this->Comm, this->BoundsMap, 1, 128); + + vtkm::Id nLocal = static_cast(this->Active.size() + this->Inactive.size()); + this->ComputeTotalNumParticles(nLocal); + + while (this->TotalNumTerminatedParticles < this->TotalNumParticles) + { + std::vector v; + vtkm::Id numTerm = 0, blockId = -1; + if (this->GetActiveParticles(v, blockId)) + { + //make this a pointer to avoid the copy? + auto& block = this->GetDataSet(blockId); + DSIHelperInfoType bb = + DSIHelperInfo(v, this->BoundsMap, this->ParticleBlockIDsMap); + block.Advect(bb, this->StepSize, this->NumberOfSteps); + numTerm = this->UpdateResult(bb.Get>()); + } + + vtkm::Id numTermMessages = 0; + this->Communicate(messenger, numTerm, numTermMessages); + + this->TotalNumTerminatedParticles += (numTerm + numTermMessages); + if (this->TotalNumTerminatedParticles > this->TotalNumParticles) + throw vtkm::cont::ErrorFilterExecution("Particle count error"); + } + } + + + virtual void ClearParticles() + { + this->Active.clear(); + this->Inactive.clear(); + this->ParticleBlockIDsMap.clear(); + } + + void ComputeTotalNumParticles(const vtkm::Id& numLocal) + { + long long total = static_cast(numLocal); +#ifdef VTKM_ENABLE_MPI + MPI_Comm mpiComm = vtkmdiy::mpi::mpi_cast(this->Comm.handle()); + MPI_Allreduce(MPI_IN_PLACE, &total, 1, MPI_LONG_LONG, MPI_SUM, mpiComm); +#endif + this->TotalNumParticles = static_cast(total); + } + + DataSetIntegrator& GetDataSet(vtkm::Id id) + { + for (auto& it : this->Blocks) + if (it.GetID() == id) + return it; + + throw vtkm::cont::ErrorFilterExecution("Bad block"); + } + + virtual void SetSeedArray(const std::vector& particles, + const std::vector>& blockIds) + { + VTKM_ASSERT(particles.size() == blockIds.size()); + + auto pit = particles.begin(); + auto bit = blockIds.begin(); + while (pit != particles.end() && bit != blockIds.end()) + { + this->ParticleBlockIDsMap[pit->ID] = *bit; + pit++; + bit++; + } + + this->Active.insert(this->Active.end(), particles.begin(), particles.end()); + } + + virtual bool GetActiveParticles(std::vector& particles, vtkm::Id& blockId) + { + particles.clear(); + blockId = -1; + if (this->Active.empty()) + return false; + + blockId = this->ParticleBlockIDsMap[this->Active.front().ID][0]; + auto it = this->Active.begin(); + while (it != this->Active.end()) + { + auto p = *it; + if (blockId == this->ParticleBlockIDsMap[p.ID][0]) + { + particles.emplace_back(p); + it = this->Active.erase(it); + } + else + it++; + } + + return !particles.empty(); + } + + virtual void Communicate(vtkm::filter::flow::internal::ParticleMessenger& messenger, + vtkm::Id numLocalTerminations, + vtkm::Id& numTermMessages) + { + std::vector incoming; + std::unordered_map> incomingIDs; + numTermMessages = 0; + messenger.Exchange(this->Inactive, + this->ParticleBlockIDsMap, + numLocalTerminations, + incoming, + incomingIDs, + numTermMessages, + this->GetBlockAndWait(numLocalTerminations)); + + this->Inactive.clear(); + this->UpdateActive(incoming, incomingIDs); + } + + virtual void UpdateActive(const std::vector& particles, + const std::unordered_map>& idsMap) + { + this->Update(this->Active, particles, idsMap); + } + + virtual void UpdateInactive(const std::vector& particles, + const std::unordered_map>& idsMap) + { + this->Update(this->Inactive, particles, idsMap); + } + + void Update(std::vector& arr, + const std::vector& particles, + const std::unordered_map>& idsMap) + { + VTKM_ASSERT(particles.size() == idsMap.size()); + + arr.insert(arr.end(), particles.begin(), particles.end()); + for (const auto& it : idsMap) + this->ParticleBlockIDsMap[it.first] = it.second; + } + + vtkm::Id UpdateResult(const DSIHelperInfo& stuff) + { + this->UpdateActive(stuff.A, stuff.IdMapA); + this->UpdateInactive(stuff.I, stuff.IdMapI); + + vtkm::Id numTerm = static_cast(stuff.TermID.size()); + //Update terminated particles. + if (numTerm > 0) + { + for (const auto& id : stuff.TermID) + this->ParticleBlockIDsMap.erase(id); + } + + return numTerm; + } + + virtual bool GetBlockAndWait(const vtkm::Id& numLocalTerm) + { + //There are only two cases where blocking would deadlock. + //1. There are active particles. + //2. numLocalTerm + this->TotalNumberOfTerminatedParticles == this->TotalNumberOfParticles + //So, if neither are true, we can safely block and wait for communication to come in. + + if (this->Active.empty() && this->Inactive.empty() && + (numLocalTerm + this->TotalNumTerminatedParticles < this->TotalNumParticles)) + { + return true; + } + + return false; + } + + //Member data + std::vector Active; + std::vector Blocks; + vtkm::filter::flow::internal::BoundsMap BoundsMap; + vtkmdiy::mpi::communicator Comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); + std::vector Inactive; + vtkm::Id NumberOfSteps; + vtkm::Id NumRanks; + std::unordered_map> ParticleBlockIDsMap; + vtkm::Id Rank; + vtkm::FloatDefault StepSize; + vtkm::Id TotalNumParticles = 0; + vtkm::Id TotalNumTerminatedParticles = 0; +}; + +} +} +} +} //vtkm::filter::flow::internal + +#endif //vtk_m_filter_flow_internal_AdvectAlgorithm_h diff --git a/vtkm/filter/particleadvection/AdvectorBaseThreadedAlgorithm.h b/vtkm/filter/flow/internal/AdvectAlgorithmThreaded.h similarity index 59% rename from vtkm/filter/particleadvection/AdvectorBaseThreadedAlgorithm.h rename to vtkm/filter/flow/internal/AdvectAlgorithmThreaded.h index 5421a1f4b..3417defaf 100644 --- a/vtkm/filter/particleadvection/AdvectorBaseThreadedAlgorithm.h +++ b/vtkm/filter/flow/internal/AdvectAlgorithmThreaded.h @@ -8,10 +8,14 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_filter_particleadvection_AdvectorBaseThreadedAlgorithm_h -#define vtk_m_filter_particleadvection_AdvectorBaseThreadedAlgorithm_h +#ifndef vtk_m_filter_flow_internal_AdvectAlgorithmThreaded_h +#define vtk_m_filter_flow_internal_AdvectAlgorithmThreaded_h -#include +#include +#include +#include +#include +#include #include @@ -19,17 +23,18 @@ namespace vtkm { namespace filter { -namespace particleadvection +namespace flow +{ +namespace internal { -template -class VTKM_ALWAYS_EXPORT AdvectorBaseThreadedAlgorithm - : public AdvectorBaseAlgorithm +template class ResultType, typename ParticleType> +class AdvectAlgorithmThreaded : public AdvectAlgorithm { public: - AdvectorBaseThreadedAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseAlgorithm(bm, blocks) + AdvectAlgorithmThreaded(const vtkm::filter::flow::internal::BoundsMap& bm, + std::vector& blocks) + : AdvectAlgorithm(bm, blocks) , Done(false) , WorkerActivate(false) { @@ -46,30 +51,32 @@ public: this->ComputeTotalNumParticles(nLocal); std::vector workerThreads; - workerThreads.push_back(std::thread(AdvectorBaseThreadedAlgorithm::Worker, this)); + workerThreads.emplace_back(std::thread(AdvectAlgorithmThreaded::Worker, this)); this->Manage(); + + //This will only work for 1 thread. For > 1, the Blocks will need a mutex. + VTKM_ASSERT(workerThreads.size() == 1); for (auto& t : workerThreads) t.join(); } protected: - bool GetActiveParticles(std::vector& particles, vtkm::Id& blockId) override + bool GetActiveParticles(std::vector& particles, vtkm::Id& blockId) override { std::lock_guard lock(this->Mutex); - bool val = this->AdvectorBaseAlgorithm::GetActiveParticles( + bool val = this->AdvectAlgorithm::GetActiveParticles( particles, blockId); this->WorkerActivate = val; return val; } - void UpdateActive(const std::vector& particles, + void UpdateActive(const std::vector& particles, const std::unordered_map>& idsMap) override { if (!particles.empty()) { std::lock_guard lock(this->Mutex); - this->AdvectorBaseAlgorithm::UpdateActive(particles, - idsMap); + this->AdvectAlgorithm::UpdateActive(particles, idsMap); //Let workers know there is new work this->WorkerActivateCondition.notify_all(); @@ -90,7 +97,7 @@ protected: this->WorkerActivateCondition.notify_all(); } - static void Worker(AdvectorBaseThreadedAlgorithm* algo) { algo->Work(); } + static void Worker(AdvectAlgorithmThreaded* algo) { algo->Work(); } void WorkerWait() { @@ -98,18 +105,26 @@ protected: this->WorkerActivateCondition.wait(lock, [this] { return WorkerActivate || Done; }); } + void UpdateWorkerResult(vtkm::Id blockId, DSIHelperInfoType& b) + { + std::lock_guard lock(this->Mutex); + auto& it = this->WorkerResults[blockId]; + it.emplace_back(b); + } + void Work() { while (!this->CheckDone()) { - std::vector v; + std::vector v; vtkm::Id blockId = -1; if (this->GetActiveParticles(v, blockId)) { - const auto& block = this->GetDataSet(blockId); - ResultType r; - block.Advect(v, this->StepSize, this->NumberOfSteps, r); - this->UpdateWorkerResult(blockId, r); + auto& block = this->GetDataSet(blockId); + DSIHelperInfoType bb = + DSIHelperInfo(v, this->BoundsMap, this->ParticleBlockIDsMap); + block.Advect(bb, this->StepSize, this->NumberOfSteps); + this->UpdateWorkerResult(blockId, bb); } else this->WorkerWait(); @@ -118,20 +133,19 @@ protected: void Manage() { - vtkm::filter::particleadvection::ParticleMessenger messenger( + vtkm::filter::flow::internal::ParticleMessenger messenger( this->Comm, this->BoundsMap, 1, 128); while (this->TotalNumTerminatedParticles < this->TotalNumParticles) { - std::unordered_map> workerResults; + std::unordered_map> workerResults; this->GetWorkerResults(workerResults); vtkm::Id numTerm = 0; for (auto& it : workerResults) { - vtkm::Id blockId = it.first; for (auto& r : it.second) - numTerm += this->UpdateResult(r, blockId); + numTerm += this->UpdateResult(r.Get>()); } vtkm::Id numTermMessages = 0; @@ -150,12 +164,12 @@ protected: { std::lock_guard lock(this->Mutex); - return (this->AdvectorBaseAlgorithm::GetBlockAndWait( - numLocalTerm) && - !this->WorkerActivate && this->WorkerResults.empty()); + return ( + this->AdvectAlgorithm::GetBlockAndWait(numLocalTerm) && + !this->WorkerActivate && this->WorkerResults.empty()); } - void GetWorkerResults(std::unordered_map>& results) + void GetWorkerResults(std::unordered_map>& results) { results.clear(); @@ -167,23 +181,16 @@ protected: } } - void UpdateWorkerResult(vtkm::Id blockId, const ResultType& result) - { - std::lock_guard lock(this->Mutex); - - auto& it = this->WorkerResults[blockId]; - it.push_back(result); - } - std::atomic Done; std::mutex Mutex; bool WorkerActivate; std::condition_variable WorkerActivateCondition; - std::unordered_map> WorkerResults; + std::unordered_map> WorkerResults; }; } } -} // namespace vtkm::filter::particleadvection +} +} //vtkm::filter::flow::internal -#endif +#endif //vtk_m_filter_flow_internal_AdvectAlgorithmThreaded_h diff --git a/vtkm/filter/particleadvection/BoundsMap.h b/vtkm/filter/flow/internal/BoundsMap.h similarity index 93% rename from vtkm/filter/particleadvection/BoundsMap.h rename to vtkm/filter/flow/internal/BoundsMap.h index 705aba99a..70368026c 100644 --- a/vtkm/filter/particleadvection/BoundsMap.h +++ b/vtkm/filter/flow/internal/BoundsMap.h @@ -8,8 +8,8 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_filter_BoundsMap_h -#define vtk_m_filter_BoundsMap_h +#ifndef vtk_m_filter_flow_internal_BoundsMap_h +#define vtk_m_filter_flow_internal_BoundsMap_h #include #include @@ -31,7 +31,9 @@ namespace vtkm { namespace filter { -namespace particleadvection +namespace flow +{ +namespace internal { class VTKM_ALWAYS_EXPORT BoundsMap @@ -96,7 +98,7 @@ public: for (auto& it : this->BlockBounds) { if (blockId != ignoreBlock && it.Contains(p)) - blockIDs.push_back(blockId); + blockIDs.emplace_back(blockId); blockId++; } } @@ -117,7 +119,7 @@ private: vtkmdiy::mpi::communicator Comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); assigner.local_gids(Comm.rank(), ids); for (const auto& i : ids) - this->LocalIDs.push_back(static_cast(i)); + this->LocalIDs.emplace_back(static_cast(i)); for (vtkm::Id id = 0; id < this->TotalNumBlocks; id++) this->BlockToRankMap[id] = assigner.rank(static_cast(id)); @@ -174,8 +176,10 @@ private: std::vector BlockBounds; vtkm::Bounds GlobalBounds; }; -} -} -} // namespace vtkm::filter::particleadvection -#endif +} +} +} +} // namespace vtkm::filter::flow::internal + +#endif //vtk_m_filter_flow_internal_BoundsMap_h diff --git a/vtkm/filter/particleadvection/CMakeLists.txt b/vtkm/filter/flow/internal/CMakeLists.txt similarity index 69% rename from vtkm/filter/particleadvection/CMakeLists.txt rename to vtkm/filter/flow/internal/CMakeLists.txt index 765954149..0f192e284 100644 --- a/vtkm/filter/particleadvection/CMakeLists.txt +++ b/vtkm/filter/flow/internal/CMakeLists.txt @@ -9,16 +9,18 @@ ##============================================================================ set(headers - AdvectorBaseAlgorithm.h - AdvectorBaseAlgorithm.hxx - AdvectorBaseThreadedAlgorithm.h + AdvectAlgorithm.h + AdvectAlgorithmThreaded.h BoundsMap.h DataSetIntegrator.h - DataSetIntegrator.hxx + DataSetIntegratorSteadyState.h + DataSetIntegratorUnsteadyState.h Messenger.h - ParticleAdvectionAlgorithm.h + ParticleAdvector.h ParticleMessenger.h -) + ) + +# Note: The C++ source files are added to the flow library +# in the CMakeLists.txt in the parent directory. -#----------------------------------------------------------------------------- vtkm_declare_headers(${headers}) diff --git a/vtkm/filter/flow/internal/DataSetIntegrator.h b/vtkm/filter/flow/internal/DataSetIntegrator.h new file mode 100644 index 000000000..b3974cda7 --- /dev/null +++ b/vtkm/filter/flow/internal/DataSetIntegrator.h @@ -0,0 +1,375 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_DataSetIntegrator_h +#define vtk_m_filter_flow_internal_DataSetIntegrator_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +template +class DSIHelperInfo +{ +public: + DSIHelperInfo(const std::vector& v, + const vtkm::filter::flow::internal::BoundsMap& boundsMap, + const std::unordered_map>& particleBlockIDsMap) + : BoundsMap(boundsMap) + , ParticleBlockIDsMap(particleBlockIDsMap) + , V(v) + { + } + + const vtkm::filter::flow::internal::BoundsMap BoundsMap; + const std::unordered_map> ParticleBlockIDsMap; + + std::vector A, I, V; + std::unordered_map> IdMapA, IdMapI; + std::vector TermIdx, TermID; +}; + +using DSIHelperInfoType = vtkm::cont::internal::Variant, + DSIHelperInfo>; + +template +class DataSetIntegrator +{ +protected: + using VelocityFieldNameType = std::string; + using ElectroMagneticFieldNameType = std::pair; + using FieldNameType = + vtkm::cont::internal::Variant; + + using RType = vtkm::cont::internal::Variant< + vtkm::worklet::flow::ParticleAdvectionResult, + vtkm::worklet::flow::ParticleAdvectionResult, + vtkm::worklet::flow::StreamlineResult, + vtkm::worklet::flow::StreamlineResult>; + +public: + DataSetIntegrator(vtkm::Id id, + const FieldNameType& fieldName, + vtkm::filter::flow::IntegrationSolverType solverType, + vtkm::filter::flow::VectorFieldType vecFieldType, + vtkm::filter::flow::FlowResultType resultType) + : FieldName(fieldName) + , Id(id) + , SolverType(solverType) + , VecFieldType(vecFieldType) + , AdvectionResType(resultType) + , Rank(this->Comm.rank()) + { + //check that things are valid. + } + + VTKM_CONT vtkm::Id GetID() const { return this->Id; } + VTKM_CONT void SetCopySeedFlag(bool val) { this->CopySeedArray = val; } + + VTKM_CONT + void Advect(DSIHelperInfoType& b, + vtkm::FloatDefault stepSize, //move these to member data(?) + vtkm::Id maxSteps) + { + Derived* inst = static_cast(this); + + //Cast the DSIHelperInfo to the concrete type and call DoAdvect. + b.CastAndCall([&](auto& concrete) { inst->DoAdvect(concrete, stepSize, maxSteps); }); + } + + template + VTKM_CONT bool GetOutput(vtkm::cont::DataSet& ds) const; + + +protected: + template class ResultType> + VTKM_CONT void UpdateResult(const ResultType& result, + DSIHelperInfo& dsiInfo); + + VTKM_CONT bool IsParticleAdvectionResult() const + { + return this->AdvectionResType == FlowResultType::PARTICLE_ADVECT_TYPE; + } + + VTKM_CONT bool IsStreamlineResult() const + { + return this->AdvectionResType == FlowResultType::STREAMLINE_TYPE; + } + + template + VTKM_CONT inline void ClassifyParticles(const vtkm::cont::ArrayHandle& particles, + DSIHelperInfo& dsiInfo) const; + + //Data members. + vtkm::cont::internal::Variant FieldName; + + vtkm::Id Id; + vtkm::filter::flow::IntegrationSolverType SolverType; + vtkm::filter::flow::VectorFieldType VecFieldType; + vtkm::filter::flow::FlowResultType AdvectionResType = + vtkm::filter::flow::FlowResultType::UNKNOWN_TYPE; + + vtkmdiy::mpi::communicator Comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); + vtkm::Id Rank; + bool CopySeedArray = false; + std::vector Results; +}; + +template +template +VTKM_CONT inline void DataSetIntegrator::ClassifyParticles( + const vtkm::cont::ArrayHandle& particles, + DSIHelperInfo& dsiInfo) const +{ + dsiInfo.A.clear(); + dsiInfo.I.clear(); + dsiInfo.TermID.clear(); + dsiInfo.TermIdx.clear(); + dsiInfo.IdMapI.clear(); + dsiInfo.IdMapA.clear(); + + auto portal = particles.WritePortal(); + vtkm::Id n = portal.GetNumberOfValues(); + + for (vtkm::Id i = 0; i < n; i++) + { + auto p = portal.Get(i); + + if (p.Status.CheckTerminate()) + { + dsiInfo.TermIdx.emplace_back(i); + dsiInfo.TermID.emplace_back(p.ID); + } + else + { + const auto& it = dsiInfo.ParticleBlockIDsMap.find(p.ID); + VTKM_ASSERT(it != dsiInfo.ParticleBlockIDsMap.end()); + auto currBIDs = it->second; + VTKM_ASSERT(!currBIDs.empty()); + + std::vector newIDs; + if (p.Status.CheckSpatialBounds() && !p.Status.CheckTookAnySteps()) + newIDs.assign(std::next(currBIDs.begin(), 1), currBIDs.end()); + else + newIDs = dsiInfo.BoundsMap.FindBlocks(p.Pos, currBIDs); + + //reset the particle status. + p.Status = vtkm::ParticleStatus(); + + if (newIDs.empty()) //No blocks, we're done. + { + p.Status.SetTerminate(); + dsiInfo.TermIdx.emplace_back(i); + dsiInfo.TermID.emplace_back(p.ID); + } + else + { + //If we have more than blockId, we want to minimize communication + //and put any blocks owned by this rank first. + if (newIDs.size() > 1) + { + for (auto idit = newIDs.begin(); idit != newIDs.end(); idit++) + { + vtkm::Id bid = *idit; + if (dsiInfo.BoundsMap.FindRank(bid) == this->Rank) + { + newIDs.erase(idit); + newIDs.insert(newIDs.begin(), bid); + break; + } + } + } + + int dstRank = dsiInfo.BoundsMap.FindRank(newIDs[0]); + if (dstRank == this->Rank) + { + dsiInfo.A.emplace_back(p); + dsiInfo.IdMapA[p.ID] = newIDs; + } + else + { + dsiInfo.I.emplace_back(p); + dsiInfo.IdMapI[p.ID] = newIDs; + } + } + portal.Set(i, p); + } + } + + //Make sure we didn't miss anything. Every particle goes into a single bucket. + VTKM_ASSERT(static_cast(n) == + (dsiInfo.A.size() + dsiInfo.I.size() + dsiInfo.TermIdx.size())); + VTKM_ASSERT(dsiInfo.TermIdx.size() == dsiInfo.TermID.size()); +} + +template +template class ResultType> +VTKM_CONT inline void DataSetIntegrator::UpdateResult( + const ResultType& result, + DSIHelperInfo& dsiInfo) +{ + this->ClassifyParticles(result.Particles, dsiInfo); + + if (this->IsParticleAdvectionResult()) + { + if (dsiInfo.TermIdx.empty()) + return; + + using ResType = vtkm::worklet::flow::ParticleAdvectionResult; + auto indicesAH = vtkm::cont::make_ArrayHandle(dsiInfo.TermIdx, vtkm::CopyFlag::Off); + auto termPerm = vtkm::cont::make_ArrayHandlePermutation(indicesAH, result.Particles); + + vtkm::cont::ArrayHandle termParticles; + vtkm::cont::Algorithm::Copy(termPerm, termParticles); + + ResType termRes(termParticles); + this->Results.emplace_back(termRes); + } + else if (this->IsStreamlineResult()) + this->Results.emplace_back(result); +} + +template +template +VTKM_CONT inline bool DataSetIntegrator::GetOutput(vtkm::cont::DataSet& ds) const +{ + std::size_t nResults = this->Results.size(); + if (nResults == 0) + return false; + + if (this->IsParticleAdvectionResult()) + { + using ResType = vtkm::worklet::flow::ParticleAdvectionResult; + + std::vector> allParticles; + allParticles.reserve(nResults); + for (const auto& vres : this->Results) + allParticles.emplace_back(vres.template Get().Particles); + + vtkm::cont::ArrayHandle pts; + vtkm::cont::ParticleArrayCopy(allParticles, pts); + + vtkm::Id numPoints = pts.GetNumberOfValues(); + if (numPoints > 0) + { + //Create coordinate system and vertex cell set. + ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", pts)); + + vtkm::cont::CellSetSingleType<> cells; + vtkm::cont::ArrayHandleIndex conn(numPoints); + vtkm::cont::ArrayHandle connectivity; + + vtkm::cont::ArrayCopy(conn, connectivity); + cells.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity); + ds.SetCellSet(cells); + } + } + else if (this->IsStreamlineResult()) + { + using ResType = vtkm::worklet::flow::StreamlineResult; + + //Easy case with one result. + if (nResults == 1) + { + const auto& res = this->Results[0].template Get(); + ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", res.Positions)); + ds.SetCellSet(res.PolyLines); + } + else + { + std::vector posOffsets(nResults, 0); + vtkm::Id totalNumCells = 0, totalNumPts = 0; + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = this->Results[i].template Get(); + if (i == 0) + posOffsets[i] = 0; + else + posOffsets[i] = totalNumPts; + + totalNumPts += res.Positions.GetNumberOfValues(); + totalNumCells += res.PolyLines.GetNumberOfCells(); + } + + //Append all the points together. + vtkm::cont::ArrayHandle appendPts; + appendPts.Allocate(totalNumPts); + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = this->Results[i].template Get(); + // copy all values into appendPts starting at offset. + vtkm::cont::Algorithm::CopySubRange( + res.Positions, 0, res.Positions.GetNumberOfValues(), appendPts, posOffsets[i]); + } + ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", appendPts)); + + //Create polylines. + std::vector numPtsPerCell(static_cast(totalNumCells)); + std::size_t off = 0; + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = this->Results[i].template Get(); + vtkm::Id nCells = res.PolyLines.GetNumberOfCells(); + for (vtkm::Id j = 0; j < nCells; j++) + numPtsPerCell[off++] = static_cast(res.PolyLines.GetNumberOfPointsInCell(j)); + } + + auto numPointsPerCellArray = vtkm::cont::make_ArrayHandle(numPtsPerCell, vtkm::CopyFlag::Off); + + vtkm::cont::ArrayHandle cellIndex; + vtkm::Id connectivityLen = + vtkm::cont::Algorithm::ScanExclusive(numPointsPerCellArray, cellIndex); + vtkm::cont::ArrayHandleIndex connCount(connectivityLen); + vtkm::cont::ArrayHandle connectivity; + vtkm::cont::ArrayCopy(connCount, connectivity); + + vtkm::cont::ArrayHandle cellTypes; + auto polyLineShape = vtkm::cont::make_ArrayHandleConstant( + vtkm::CELL_SHAPE_POLY_LINE, totalNumCells); + vtkm::cont::ArrayCopy(polyLineShape, cellTypes); + auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPointsPerCellArray); + + vtkm::cont::CellSetExplicit<> polyLines; + polyLines.Fill(totalNumPts, cellTypes, connectivity, offsets); + ds.SetCellSet(polyLines); + } + } + else + { + throw vtkm::cont::ErrorFilterExecution("Unsupported ParticleAdvectionResultType"); + } + + return true; +} + +} +} +} +} //vtkm::filter::flow::internal + +#endif //vtk_m_filter_flow_internal_DataSetIntegrator_h diff --git a/vtkm/filter/flow/internal/DataSetIntegratorSteadyState.h b/vtkm/filter/flow/internal/DataSetIntegratorSteadyState.h new file mode 100644 index 000000000..6e4bd5712 --- /dev/null +++ b/vtkm/filter/flow/internal/DataSetIntegratorSteadyState.h @@ -0,0 +1,214 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_DataSetIntegratorSteadyState_h +#define vtk_m_filter_flow_internal_DataSetIntegratorSteadyState_h + +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +class DataSetIntegratorSteadyState + : public vtkm::filter::flow::internal::DataSetIntegrator +{ +public: + DataSetIntegratorSteadyState(const vtkm::cont::DataSet& ds, + vtkm::Id id, + const FieldNameType& fieldName, + vtkm::filter::flow::IntegrationSolverType solverType, + vtkm::filter::flow::VectorFieldType vecFieldType, + vtkm::filter::flow::FlowResultType resultType) + : vtkm::filter::flow::internal::DataSetIntegrator(id, + fieldName, + solverType, + vecFieldType, + resultType) + , DataSet(ds) + { + } + + VTKM_CONT inline void DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps); + + VTKM_CONT inline void DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps); + +protected: + template + VTKM_CONT void GetVelocityField( + vtkm::worklet::flow::VelocityField& velocityField) const + { + if (this->FieldName.GetIndex() == this->FieldName.GetIndexOf()) + { + const auto& fieldNm = this->FieldName.Get(); + auto assoc = this->DataSet.GetField(fieldNm).GetAssociation(); + ArrayType arr; + vtkm::cont::ArrayCopyShallowIfPossible(this->DataSet.GetField(fieldNm).GetData(), arr); + + velocityField = vtkm::worklet::flow::VelocityField(arr, assoc); + } + else + throw vtkm::cont::ErrorFilterExecution("Velocity field vector type not available"); + } + +private: + vtkm::cont::DataSet DataSet; +}; + + +namespace internal +{ +using ArrayType = vtkm::cont::ArrayHandle; +using VelocityFieldType = vtkm::worklet::flow::VelocityField; +using SteadyStateGridEvalType = vtkm::worklet::flow::GridEvaluator; + +template +class AdvectHelper; + +template +class AdvectHelper +{ +public: + static void Advect(const VelocityFieldType& velField, + const vtkm::cont::DataSet& ds, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + const IntegrationSolverType& solverType, + vtkm::worklet::flow::ParticleAdvectionResult& result) + { + if (solverType == IntegrationSolverType::RK4_TYPE) + { + DoAdvect( + velField, ds, seedArray, stepSize, maxSteps, result); + } + else if (solverType == IntegrationSolverType::EULER_TYPE) + { + DoAdvect( + velField, ds, seedArray, stepSize, maxSteps, result); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported Integrator type"); + } + + static void Advect(const VelocityFieldType& velField, + const vtkm::cont::DataSet& ds, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + const IntegrationSolverType& solverType, + vtkm::worklet::flow::StreamlineResult& result) + { + if (solverType == IntegrationSolverType::RK4_TYPE) + { + DoAdvect( + velField, ds, seedArray, stepSize, maxSteps, result); + } + else if (solverType == IntegrationSolverType::EULER_TYPE) + { + DoAdvect( + velField, ds, seedArray, stepSize, maxSteps, result); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported Integrator type"); + } + + template + class ResultType, + template + class SolverType> + static void DoAdvect(const VelocityFieldType& velField, + const vtkm::cont::DataSet& ds, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + ResultType& result) + { + using StepperType = + vtkm::worklet::flow::Stepper, SteadyStateGridEvalType>; + + WorkletType worklet; + SteadyStateGridEvalType eval(ds, velField); + StepperType stepper(eval, stepSize); + result = worklet.Run(stepper, seedArray, maxSteps); + } +}; +} + +VTKM_CONT inline void DataSetIntegratorSteadyState::DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps) +{ + using ArrayType = vtkm::cont::ArrayHandle; + + auto copyFlag = (this->CopySeedArray ? vtkm::CopyFlag::On : vtkm::CopyFlag::Off); + auto seedArray = vtkm::cont::make_ArrayHandle(b.V, copyFlag); + + if (this->VecFieldType == VectorFieldType::VELOCITY_FIELD_TYPE) + { + using FieldType = vtkm::worklet::flow::VelocityField; + FieldType velField; + this->GetVelocityField(velField); + + using AHType = internal::AdvectHelper; + + if (this->IsParticleAdvectionResult()) + { + vtkm::worklet::flow::ParticleAdvectionResult result; + AHType::Advect( + velField, this->DataSet, seedArray, stepSize, maxSteps, this->SolverType, result); + this->UpdateResult(result, b); + } + else if (this->IsStreamlineResult()) + { + vtkm::worklet::flow::StreamlineResult result; + AHType::Advect( + velField, this->DataSet, seedArray, stepSize, maxSteps, this->SolverType, result); + this->UpdateResult(result, b); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported result type"); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported vector field type"); +} + +VTKM_CONT inline void DataSetIntegratorSteadyState::DoAdvect( + DSIHelperInfo& vtkmNotUsed(b), + vtkm::FloatDefault vtkmNotUsed(stepSize), + vtkm::Id vtkmNotUsed(maxSteps)) +{ +} + +} +} +} +} //vtkm::filter::flow::internal + +#endif //vtk_m_filter_flow_internal_DataSetIntegratorSteadyState_h diff --git a/vtkm/filter/flow/internal/DataSetIntegratorUnsteadyState.h b/vtkm/filter/flow/internal/DataSetIntegratorUnsteadyState.h new file mode 100644 index 000000000..de4a9d540 --- /dev/null +++ b/vtkm/filter/flow/internal/DataSetIntegratorUnsteadyState.h @@ -0,0 +1,265 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_DataSetIntegratorUnsteadyState_h +#define vtk_m_filter_flow_internal_DataSetIntegratorUnsteadyState_h + +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +class DataSetIntegratorUnsteadyState + : public vtkm::filter::flow::internal::DataSetIntegrator +{ +public: + DataSetIntegratorUnsteadyState(const vtkm::cont::DataSet& ds1, + const vtkm::cont::DataSet& ds2, + vtkm::FloatDefault t1, + vtkm::FloatDefault t2, + vtkm::Id id, + const vtkm::filter::flow::internal::DataSetIntegrator< + DataSetIntegratorUnsteadyState>::FieldNameType& fieldName, + vtkm::filter::flow::IntegrationSolverType solverType, + vtkm::filter::flow::VectorFieldType vecFieldType, + vtkm::filter::flow::FlowResultType resultType) + : vtkm::filter::flow::internal::DataSetIntegrator(id, + fieldName, + solverType, + vecFieldType, + resultType) + , DataSet1(ds1) + , DataSet2(ds2) + , Time1(t1) + , Time2(t2) + { + } + + VTKM_CONT inline void DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps); + + VTKM_CONT inline void DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps); + +protected: + template + VTKM_CONT void GetVelocityFields( + vtkm::worklet::flow::VelocityField& velocityField1, + vtkm::worklet::flow::VelocityField& velocityField2) const + { + if (this->FieldName.GetIndex() == this->FieldName.GetIndexOf()) + { + const auto& fieldNm = this->FieldName.Get(); + auto assoc = this->DataSet1.GetField(fieldNm).GetAssociation(); + if (assoc != this->DataSet2.GetField(fieldNm).GetAssociation()) + throw vtkm::cont::ErrorFilterExecution( + "Unsteady state velocity fields have differnt associations"); + + ArrayType arr1, arr2; + vtkm::cont::ArrayCopyShallowIfPossible(this->DataSet1.GetField(fieldNm).GetData(), arr1); + vtkm::cont::ArrayCopyShallowIfPossible(this->DataSet2.GetField(fieldNm).GetData(), arr2); + + velocityField1 = vtkm::worklet::flow::VelocityField(arr1, assoc); + velocityField2 = vtkm::worklet::flow::VelocityField(arr2, assoc); + } + else + throw vtkm::cont::ErrorFilterExecution("Velocity field vector type not available"); + } + +private: + vtkm::cont::DataSet DataSet1; + vtkm::cont::DataSet DataSet2; + vtkm::FloatDefault Time1; + vtkm::FloatDefault Time2; +}; + + + +namespace internal +{ +using ArrayType = vtkm::cont::ArrayHandle; +using VelocityFieldType = vtkm::worklet::flow::VelocityField; +using UnsteadyStateGridEvalType = vtkm::worklet::flow::TemporalGridEvaluator; + +template +class AdvectHelper; + +template +class AdvectHelper +{ +public: + static void Advect(const VelocityFieldType& velField1, + const vtkm::cont::DataSet& ds1, + vtkm::FloatDefault t1, + const VelocityFieldType& velField2, + const vtkm::cont::DataSet& ds2, + vtkm::FloatDefault t2, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + const IntegrationSolverType& solverType, + vtkm::worklet::flow::ParticleAdvectionResult& result) + { + if (solverType == IntegrationSolverType::RK4_TYPE) + { + DoAdvect( + velField1, ds1, t1, velField2, ds2, t2, seedArray, stepSize, maxSteps, result); + } + else if (solverType == IntegrationSolverType::EULER_TYPE) + { + DoAdvect( + velField1, ds1, t1, velField2, ds2, t2, seedArray, stepSize, maxSteps, result); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported Integrator type"); + } + + static void Advect(const VelocityFieldType& velField1, + const vtkm::cont::DataSet& ds1, + vtkm::FloatDefault t1, + const VelocityFieldType& velField2, + const vtkm::cont::DataSet& ds2, + vtkm::FloatDefault t2, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + const IntegrationSolverType& solverType, + vtkm::worklet::flow::StreamlineResult& result) + { + if (solverType == IntegrationSolverType::RK4_TYPE) + { + DoAdvect( + velField1, ds1, t1, velField2, ds2, t2, seedArray, stepSize, maxSteps, result); + } + else if (solverType == IntegrationSolverType::EULER_TYPE) + { + DoAdvect( + velField1, ds1, t1, velField2, ds2, t2, seedArray, stepSize, maxSteps, result); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported Integrator type"); + } + + template + class ResultType, + template + class SolverType> + static void DoAdvect(const VelocityFieldType& velField1, + const vtkm::cont::DataSet& ds1, + vtkm::FloatDefault t1, + const VelocityFieldType& velField2, + const vtkm::cont::DataSet& ds2, + vtkm::FloatDefault t2, + vtkm::cont::ArrayHandle& seedArray, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps, + ResultType& result) + { + using StepperType = vtkm::worklet::flow::Stepper, + UnsteadyStateGridEvalType>; + + WorkletType worklet; + UnsteadyStateGridEvalType eval(ds1, t1, velField1, ds2, t2, velField2); + StepperType stepper(eval, stepSize); + result = worklet.Run(stepper, seedArray, maxSteps); + } +}; + +} + +VTKM_CONT inline void DataSetIntegratorUnsteadyState::DoAdvect(DSIHelperInfo& b, + vtkm::FloatDefault stepSize, + vtkm::Id maxSteps) +{ + using ArrayType = vtkm::cont::ArrayHandle; + + auto copyFlag = (this->CopySeedArray ? vtkm::CopyFlag::On : vtkm::CopyFlag::Off); + auto seedArray = vtkm::cont::make_ArrayHandle(b.V, copyFlag); + + using AHType = internal::AdvectHelper; + + if (this->VecFieldType == VectorFieldType::VELOCITY_FIELD_TYPE) + { + using FieldType = vtkm::worklet::flow::VelocityField; + FieldType velField1, velField2; + this->GetVelocityFields(velField1, velField2); + + if (this->IsParticleAdvectionResult()) + { + vtkm::worklet::flow::ParticleAdvectionResult result; + AHType::Advect(velField1, + this->DataSet1, + this->Time1, + velField2, + this->DataSet2, + this->Time2, + seedArray, + stepSize, + maxSteps, + this->SolverType, + result); + this->UpdateResult(result, b); + } + else if (this->IsStreamlineResult()) + { + vtkm::worklet::flow::StreamlineResult result; + AHType::Advect(velField1, + this->DataSet1, + this->Time1, + velField2, + this->DataSet2, + this->Time2, + seedArray, + stepSize, + maxSteps, + this->SolverType, + result); + this->UpdateResult(result, b); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported result type"); + } + else + throw vtkm::cont::ErrorFilterExecution("Unsupported vector field type"); +} + +VTKM_CONT inline void DataSetIntegratorUnsteadyState::DoAdvect( + DSIHelperInfo& vtkmNotUsed(b), + vtkm::FloatDefault vtkmNotUsed(stepSize), + vtkm::Id vtkmNotUsed(maxSteps)) +{ +} + + +} +} +} +} //vtkm::filter::flow::internal + +#endif //vtk_m_filter_flow_internal_DataSetIntegratorUnsteadyState_h diff --git a/vtkm/filter/particleadvection/Messenger.cxx b/vtkm/filter/flow/internal/Messenger.cxx similarity index 94% rename from vtkm/filter/particleadvection/Messenger.cxx rename to vtkm/filter/flow/internal/Messenger.cxx index 86397c454..71ea9340b 100644 --- a/vtkm/filter/particleadvection/Messenger.cxx +++ b/vtkm/filter/flow/internal/Messenger.cxx @@ -8,11 +8,12 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include +#include + #include #include #include -#include -#include #ifdef VTKM_ENABLE_MPI #include @@ -22,7 +23,9 @@ namespace vtkm { namespace filter { -namespace particleadvection +namespace flow +{ +namespace internal { VTKM_CONT @@ -80,7 +83,7 @@ void Messenger::CleanupRequests(int tag) for (const auto& i : this->RecvBuffers) { if (tag == TAG_ANY || tag == i.first.second) - delKeys.push_back(i.first); + delKeys.emplace_back(i.first); } if (!delKeys.empty()) @@ -150,9 +153,9 @@ void Messenger::CheckRequests(const std::map& buffers, { if (tagsToCheck.empty() || tagsToCheck.find(it.first.second) != tagsToCheck.end()) { - req.push_back(it.first.first); - copy.push_back(it.first.first); - tags.push_back(it.first.second); + req.emplace_back(it.first.first); + copy.emplace_back(it.first.first); + tags.emplace_back(it.first.second); } } @@ -176,7 +179,7 @@ void Messenger::CheckRequests(const std::map& buffers, //Add the req/tag to the return vector. reqTags.reserve(static_cast(num)); for (int i = 0; i < num; i++) - reqTags.push_back(RequestTagPair(copy[indices[i]], tags[indices[i]])); + reqTags.emplace_back(RequestTagPair(copy[indices[i]], tags[indices[i]])); } bool Messenger::PacketCompare(const char* a, const char* b) @@ -300,7 +303,7 @@ bool Messenger::RecvData(const std::set& tags, if (it == this->RecvBuffers.end()) throw vtkm::cont::ErrorFilterExecution("receive buffer not found"); - incomingBuffers.push_back(it->second); + incomingBuffers.emplace_back(it->second); this->RecvBuffers.erase(it); } @@ -329,7 +332,7 @@ void Messenger::ProcessReceivedBuffers(std::vector& incomingBuffers, entry.first = header.tag; entry.second.save_binary((char*)(buff + sizeof(header)), header.dataSz); entry.second.reset(); - buffers.push_back(std::move(entry)); + buffers.emplace_back(std::move(entry)); delete[] buff; } @@ -344,12 +347,12 @@ void Messenger::ProcessReceivedBuffers(std::vector& incomingBuffers, if (i2 == this->RecvPackets.end()) { std::list l; - l.push_back(buff); + l.emplace_back(buff); this->RecvPackets[k] = l; } else { - i2->second.push_back(buff); + i2->second.emplace_back(buff); // The last packet came in, merge into one MemStream. if (i2->second.size() == header.numPackets) @@ -370,7 +373,7 @@ void Messenger::ProcessReceivedBuffers(std::vector& incomingBuffers, } entry.second.reset(); - buffers.push_back(std::move(entry)); + buffers.emplace_back(std::move(entry)); this->RecvPackets.erase(i2); } } @@ -379,6 +382,8 @@ void Messenger::ProcessReceivedBuffers(std::vector& incomingBuffers, } #endif + } } -} // namespace vtkm::filter::particleadvection +} +} // vtkm::filter::flow::internal diff --git a/vtkm/filter/particleadvection/Messenger.h b/vtkm/filter/flow/internal/Messenger.h similarity index 90% rename from vtkm/filter/particleadvection/Messenger.h rename to vtkm/filter/flow/internal/Messenger.h index a9443961e..895f9bf46 100644 --- a/vtkm/filter/particleadvection/Messenger.h +++ b/vtkm/filter/flow/internal/Messenger.h @@ -8,13 +8,11 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_filter_Messenger_h -#define vtk_m_filter_Messenger_h - -#include +#ifndef vtk_m_filter_flow_internal_Messenger_h +#define vtk_m_filter_flow_internal_Messenger_h #include -#include +#include #include #include @@ -30,10 +28,12 @@ namespace vtkm { namespace filter { -namespace particleadvection +namespace flow +{ +namespace internal { -class VTKM_FILTER_EXTRA_EXPORT Messenger +class VTKM_FILTER_FLOW_EXPORT Messenger { public: VTKM_CONT Messenger(vtkmdiy::mpi::communicator& comm); @@ -106,9 +106,10 @@ protected: static constexpr int Rank = 0; #endif }; + } } -} // namespace vtkm::filter::particleadvection +} +} // vtkm::filter::flow::internal - -#endif +#endif // vtk_m_filter_flow_internal_Messenger_h diff --git a/vtkm/filter/flow/internal/ParticleAdvector.h b/vtkm/filter/flow/internal/ParticleAdvector.h new file mode 100644 index 000000000..919d460d1 --- /dev/null +++ b/vtkm/filter/flow/internal/ParticleAdvector.h @@ -0,0 +1,125 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_ParticleAdvector_h +#define vtk_m_filter_flow_internal_ParticleAdvector_h + +#include +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +template +class ParticleAdvector +{ +public: + ParticleAdvector(const vtkm::filter::flow::internal::BoundsMap& bm, + const std::vector& blocks, + const bool& useThreaded, + const vtkm::filter::flow::FlowResultType& parType) + : Blocks(blocks) + , BoundsMap(bm) + , ResultType(parType) + , UseThreadedAlgorithm(useThreaded) + { + } + + vtkm::cont::PartitionedDataSet Execute(vtkm::Id numSteps, + vtkm::FloatDefault stepSize, + const vtkm::cont::UnknownArrayHandle& seeds) + { + using ParticleTypeList = vtkm::List; + + vtkm::cont::PartitionedDataSet result; + seeds.CastAndCallForTypes( + [&](const auto& concreteSeeds) { + result = this->Execute(numSteps, stepSize, concreteSeeds); + }); + + return result; + } + +private: + template + vtkm::cont::PartitionedDataSet RunAlgo(vtkm::Id numSteps, + vtkm::FloatDefault stepSize, + const vtkm::cont::ArrayHandle& seeds) + { + AlgorithmType algo(this->BoundsMap, this->Blocks); + algo.Execute(numSteps, stepSize, seeds); + return algo.GetOutput(); + } + + template + vtkm::cont::PartitionedDataSet Execute(vtkm::Id numSteps, + vtkm::FloatDefault stepSize, + const vtkm::cont::ArrayHandle& seeds) + { + if (!this->UseThreadedAlgorithm) + { + if (this->ResultType == vtkm::filter::flow::FlowResultType::PARTICLE_ADVECT_TYPE) + { + using AlgorithmType = vtkm::filter::flow::internal:: + AdvectAlgorithm; + + return this->RunAlgo(numSteps, stepSize, seeds); + } + else + { + using AlgorithmType = vtkm::filter::flow::internal:: + AdvectAlgorithm; + + return this->RunAlgo(numSteps, stepSize, seeds); + } + } + else + { + if (this->ResultType == vtkm::filter::flow::FlowResultType::PARTICLE_ADVECT_TYPE) + { + using AlgorithmType = vtkm::filter::flow::internal::AdvectAlgorithmThreaded< + DSIType, + vtkm::worklet::flow::ParticleAdvectionResult, + ParticleType>; + + return this->RunAlgo(numSteps, stepSize, seeds); + } + else + { + using AlgorithmType = vtkm::filter::flow::internal:: + AdvectAlgorithmThreaded; + + return this->RunAlgo(numSteps, stepSize, seeds); + } + } + } + + + std::vector Blocks; + vtkm::filter::flow::internal::BoundsMap BoundsMap; + FlowResultType ResultType; + bool UseThreadedAlgorithm; +}; + +} +} +} +} //vtkm::filter::flow::internal + + +#endif //vtk_m_filter_flow_internal_ParticleAdvector_h diff --git a/vtkm/filter/flow/internal/ParticleMessenger.h b/vtkm/filter/flow/internal/ParticleMessenger.h new file mode 100644 index 000000000..3f010432e --- /dev/null +++ b/vtkm/filter/flow/internal/ParticleMessenger.h @@ -0,0 +1,368 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ + +#ifndef vtk_m_filter_flow_internal_ParticleMessenger_h +#define vtk_m_filter_flow_internal_ParticleMessenger_h + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace vtkm +{ +namespace filter +{ +namespace flow +{ +namespace internal +{ + +template +class VTKM_FILTER_FLOW_EXPORT ParticleMessenger : public vtkm::filter::flow::internal::Messenger +{ + //sendRank, message + using MsgCommType = std::pair>; + + //particle + blockIDs. + using ParticleCommType = std::pair>; + + //sendRank, vector of ParticleCommType. + using ParticleRecvCommType = std::pair>; + +public: + VTKM_CONT ParticleMessenger(vtkmdiy::mpi::communicator& comm, + const vtkm::filter::flow::internal::BoundsMap& bm, + int msgSz = 1, + int numParticles = 128, + int numBlockIds = 2); + VTKM_CONT ~ParticleMessenger() {} + + VTKM_CONT void Exchange(const std::vector& outData, + const std::unordered_map>& outBlockIDsMap, + vtkm::Id numLocalTerm, + std::vector& inData, + std::unordered_map>& inDataBlockIDsMap, + vtkm::Id& numTerminateMessages, + bool blockAndWait = false); + +protected: +#ifdef VTKM_ENABLE_MPI + static constexpr int MSG_TERMINATE = 1; + + enum { MESSAGE_TAG = 0x42000, PARTICLE_TAG = 0x42001 }; + + VTKM_CONT void RegisterMessages(int msgSz, int nParticles, int numBlockIds); + + // Send/Recv particles + VTKM_CONT + template + class Container, + typename Allocator = std::allocator

> + inline void SendParticles(int dst, const Container& c); + + VTKM_CONT + template + class Container, + typename Allocator = std::allocator

> + inline void SendParticles(const std::unordered_map>& m); + + // Send/Recv messages. + VTKM_CONT void SendMsg(int dst, const std::vector& msg); + VTKM_CONT void SendAllMsg(const std::vector& msg); + VTKM_CONT bool RecvMsg(std::vector& msgs) { return RecvAny(&msgs, NULL, false); } + + // Send/Recv datasets. + VTKM_CONT bool RecvAny(std::vector* msgs, + std::vector* recvParticles, + bool blockAndWait); + const vtkm::filter::flow::internal::BoundsMap& BoundsMap; + +#endif + + VTKM_CONT void SerialExchange( + const std::vector& outData, + const std::unordered_map>& outBlockIDsMap, + vtkm::Id numLocalTerm, + std::vector& inData, + std::unordered_map>& inDataBlockIDsMap, + bool blockAndWait) const; + + static std::size_t CalcParticleBufferSize(std::size_t nParticles, std::size_t numBlockIds = 2); +}; + +//methods + +VTKM_CONT +template +ParticleMessenger::ParticleMessenger( + vtkmdiy::mpi::communicator& comm, + const vtkm::filter::flow::internal::BoundsMap& boundsMap, + int msgSz, + int numParticles, + int numBlockIds) + : Messenger(comm) +#ifdef VTKM_ENABLE_MPI + , BoundsMap(boundsMap) +#endif +{ +#ifdef VTKM_ENABLE_MPI + this->RegisterMessages(msgSz, numParticles, numBlockIds); +#else + (void)(boundsMap); + (void)(msgSz); + (void)(numParticles); + (void)(numBlockIds); +#endif +} + +template +std::size_t ParticleMessenger::CalcParticleBufferSize(std::size_t nParticles, + std::size_t nBlockIds) +{ + ParticleType pTmp; + std::size_t pSize = ParticleType::Sizeof(); + +#ifndef NDEBUG + vtkmdiy::MemoryBuffer buff; + ParticleType p; + vtkmdiy::save(buff, p); + + //Make sure the buffer size is correct. + //If this fires, then the size of the class has changed. + VTKM_ASSERT(pSize == buff.size()); +#endif + + return + // rank + sizeof(int) + //std::vector p; + //p.size() + + sizeof(std::size_t) + //nParticles of ParticleType + + nParticles * pSize + // std::vector blockIDs for each particle. + // blockIDs.size() for each particle + + nParticles * sizeof(std::size_t) + // nBlockIDs of vtkm::Id for each particle. + + nParticles * nBlockIds * sizeof(vtkm::Id); +} + +VTKM_CONT +template +void ParticleMessenger::SerialExchange( + const std::vector& outData, + const std::unordered_map>& outBlockIDsMap, + vtkm::Id vtkmNotUsed(numLocalTerm), + std::vector& inData, + std::unordered_map>& inDataBlockIDsMap, + bool vtkmNotUsed(blockAndWait)) const +{ + for (auto& p : outData) + { + const auto& bids = outBlockIDsMap.find(p.ID)->second; + inData.emplace_back(p); + inDataBlockIDsMap[p.ID] = bids; + } +} + +VTKM_CONT +template +void ParticleMessenger::Exchange( + const std::vector& outData, + const std::unordered_map>& outBlockIDsMap, + vtkm::Id numLocalTerm, + std::vector& inData, + std::unordered_map>& inDataBlockIDsMap, + vtkm::Id& numTerminateMessages, + bool blockAndWait) +{ + numTerminateMessages = 0; + inDataBlockIDsMap.clear(); + + if (this->GetNumRanks() == 1) + return this->SerialExchange( + outData, outBlockIDsMap, numLocalTerm, inData, inDataBlockIDsMap, blockAndWait); + +#ifdef VTKM_ENABLE_MPI + + //dstRank, vector of (particles,blockIDs) + std::unordered_map> sendData; + + for (const auto& p : outData) + { + const auto& bids = outBlockIDsMap.find(p.ID)->second; + int dstRank = this->BoundsMap.FindRank(bids[0]); + sendData[dstRank].emplace_back(std::make_pair(p, bids)); + } + + //Do all the sends first. + if (numLocalTerm > 0) + this->SendAllMsg({ MSG_TERMINATE, static_cast(numLocalTerm) }); + this->SendParticles(sendData); + this->CheckPendingSendRequests(); + + //Check if we have anything coming in. + std::vector particleData; + std::vector msgData; + if (RecvAny(&msgData, &particleData, blockAndWait)) + { + for (const auto& it : particleData) + for (const auto& v : it.second) + { + const auto& p = v.first; + const auto& bids = v.second; + inData.emplace_back(p); + inDataBlockIDsMap[p.ID] = bids; + } + + for (const auto& m : msgData) + { + if (m.second[0] == MSG_TERMINATE) + numTerminateMessages += static_cast(m.second[1]); + } + } +#endif +} + + +#ifdef VTKM_ENABLE_MPI + +VTKM_CONT +template +void ParticleMessenger::RegisterMessages(int msgSz, int nParticles, int numBlockIds) +{ + //Determine buffer size for msg and particle tags. + std::size_t messageBuffSz = CalcMessageBufferSize(msgSz + 1); + std::size_t particleBuffSz = CalcParticleBufferSize(nParticles, numBlockIds); + + int numRecvs = std::min(64, this->GetNumRanks() - 1); + + this->RegisterTag(ParticleMessenger::MESSAGE_TAG, numRecvs, messageBuffSz); + this->RegisterTag(ParticleMessenger::PARTICLE_TAG, numRecvs, particleBuffSz); + + this->InitializeBuffers(); +} + +VTKM_CONT +template +void ParticleMessenger::SendMsg(int dst, const std::vector& msg) +{ + vtkmdiy::MemoryBuffer buff; + + //Write data. + vtkmdiy::save(buff, this->GetRank()); + vtkmdiy::save(buff, msg); + this->SendData(dst, ParticleMessenger::MESSAGE_TAG, buff); +} + +VTKM_CONT +template +void ParticleMessenger::SendAllMsg(const std::vector& msg) +{ + for (int i = 0; i < this->GetNumRanks(); i++) + if (i != this->GetRank()) + this->SendMsg(i, msg); +} + +VTKM_CONT +template +bool ParticleMessenger::RecvAny(std::vector* msgs, + std::vector* recvParticles, + bool blockAndWait) +{ + std::set tags; + if (msgs) + { + tags.insert(ParticleMessenger::MESSAGE_TAG); + msgs->resize(0); + } + if (recvParticles) + { + tags.insert(ParticleMessenger::PARTICLE_TAG); + recvParticles->resize(0); + } + + if (tags.empty()) + return false; + + std::vector> buffers; + if (!this->RecvData(tags, buffers, blockAndWait)) + return false; + + for (auto& buff : buffers) + { + if (buff.first == ParticleMessenger::MESSAGE_TAG) + { + int sendRank; + std::vector m; + vtkmdiy::load(buff.second, sendRank); + vtkmdiy::load(buff.second, m); + msgs->emplace_back(std::make_pair(sendRank, m)); + } + else if (buff.first == ParticleMessenger::PARTICLE_TAG) + { + int sendRank; + std::vector particles; + + vtkmdiy::load(buff.second, sendRank); + vtkmdiy::load(buff.second, particles); + recvParticles->emplace_back(std::make_pair(sendRank, particles)); + } + } + + return true; +} + +VTKM_CONT +template +template class Container, typename Allocator> +inline void ParticleMessenger::SendParticles(int dst, + const Container& c) +{ + if (dst == this->GetRank()) + { + VTKM_LOG_S(vtkm::cont::LogLevel::Error, "Error. Sending a particle to yourself."); + return; + } + if (c.empty()) + return; + + vtkmdiy::MemoryBuffer bb; + vtkmdiy::save(bb, this->GetRank()); + vtkmdiy::save(bb, c); + this->SendData(dst, ParticleMessenger::PARTICLE_TAG, bb); +} + +VTKM_CONT +template +template class Container, typename Allocator> +inline void ParticleMessenger::SendParticles( + const std::unordered_map>& m) +{ + for (const auto& mit : m) + if (!mit.second.empty()) + this->SendParticles(mit.first, mit.second); +} +#endif + +} +} +} +} // vtkm::filter::flow::internal + +#endif // vtk_m_filter_flow_internal_ParticleMessenger_h diff --git a/vtkm/filter/flow/testing/CMakeLists.txt b/vtkm/filter/flow/testing/CMakeLists.txt new file mode 100644 index 000000000..858aed60a --- /dev/null +++ b/vtkm/filter/flow/testing/CMakeLists.txt @@ -0,0 +1,55 @@ +##============================================================================ +## 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. +##============================================================================ + +set(filter_unit_tests + UnitTestStreamlineFilter.cxx + UnitTestStreamSurfaceFilter.cxx + ) +set(worklet_unit_tests + UnitTestWorkletParticleAdvection.cxx + UnitTestWorkletTemporalAdvection.cxx + UnitTestStreamSurfaceWorklet.cxx + ) + +set(libraries + vtkm_filter_mesh_info + vtkm_filter_flow + vtkm_io + ) + +if (VTKm_ENABLE_RENDERING) + list(APPEND libraries vtkm_filter_geometry_refinement vtkm_rendering vtkm_rendering_testing) + + list(APPEND filter_unit_tests + RenderTestStreamline.cxx + ) +endif() + +vtkm_unit_tests( + SOURCES ${filter_unit_tests} + DEVICE_SOURCES ${worklet_unit_tests} + LIBRARIES ${libraries} + USE_VTKM_JOB_POOL +) + +#add distributed tests i.e.test to run with MPI +#if MPI is enabled. +if (VTKm_ENABLE_MPI) + set(mpi_unit_tests + UnitTestParticleMessengerMPI.cxx + UnitTestStreamlineFilterMPI.cxx + ) + vtkm_unit_tests( + MPI DEVICE_SOURCES ${mpi_unit_tests} + LIBRARIES ${libraries} + ALL_BACKENDS + USE_VTKM_JOB_POOL + ) +endif() diff --git a/vtkm/filter/flow/testing/RenderTestStreamline.cxx b/vtkm/filter/flow/testing/RenderTestStreamline.cxx new file mode 100644 index 000000000..92ea31028 --- /dev/null +++ b/vtkm/filter/flow/testing/RenderTestStreamline.cxx @@ -0,0 +1,74 @@ +//============================================================================ +// 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace +{ +void TestStreamline() +{ + std::cout << "Generate Image for Streamline filter" << std::endl; + + auto pathname = vtkm::cont::testing::Testing::DataPath("uniform/StreamlineTestDataSet.vtk"); + vtkm::io::VTKDataSetReader reader(pathname); + vtkm::cont::DataSet dataSet = reader.ReadDataSet(); + vtkm::cont::ArrayHandle seedArray = + vtkm::cont::make_ArrayHandle({ vtkm::Particle(vtkm::Vec3f(.2f, 1.0f, .2f), 0), + vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1), + vtkm::Particle(vtkm::Vec3f(.2f, 3.0f, .2f), 2) }); + + vtkm::filter::flow::Streamline streamline; + streamline.SetStepSize(0.1f); + streamline.SetNumberOfSteps(20); + streamline.SetSeeds(seedArray); + streamline.SetActiveField("vector"); + auto result = streamline.Execute(dataSet); + + // Some sort of color map is needed when rendering the coordinates of a dataset + // so create a zeroed array for the coordinates. + std::vector colorMap(static_cast::size_type>( + result.GetCoordinateSystem().GetNumberOfPoints())); + for (std::vector::size_type i = 0; i < colorMap.size(); i++) + { + colorMap[i] = static_cast(i); + } + result.AddPointField("pointvar", colorMap); + + // The streamline by itself doesn't generate renderable geometry, so surround the + // streamlines in tubes. + vtkm::filter::geometry_refinement::Tube tube; + tube.SetCapping(true); + tube.SetNumberOfSides(3); + tube.SetRadius(static_cast(0.2)); + result = tube.Execute(result); + result.PrintSummary(std::cout); + + vtkm::rendering::testing::RenderTestOptions testOptions; + testOptions.ColorTable = vtkm::cont::ColorTable::Preset::Inferno; + testOptions.EnableAnnotations = false; + vtkm::rendering::testing::RenderTest(result, "pointvar", "filter/streamline.png", testOptions); +} +} // namespace + +int RenderTestStreamline(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(TestStreamline, argc, argv); +} diff --git a/vtkm/filter/testing/UnitTestParticleMessengerMPI.cxx b/vtkm/filter/flow/testing/UnitTestParticleMessengerMPI.cxx similarity index 96% rename from vtkm/filter/testing/UnitTestParticleMessengerMPI.cxx rename to vtkm/filter/flow/testing/UnitTestParticleMessengerMPI.cxx index dca664c08..480d9551b 100644 --- a/vtkm/filter/testing/UnitTestParticleMessengerMPI.cxx +++ b/vtkm/filter/flow/testing/UnitTestParticleMessengerMPI.cxx @@ -10,7 +10,7 @@ #include #include -#include +#include #include @@ -23,11 +23,11 @@ using MCommType = std::pair>; using PCommType = std::pair>; using PRecvCommType = std::pair>; -class TestMessenger : public vtkm::filter::particleadvection::ParticleMessenger +class TestMessenger : public vtkm::filter::flow::internal::ParticleMessenger { public: TestMessenger(vtkmdiy::mpi::communicator& comm, - const vtkm::filter::particleadvection::BoundsMap& bm, + const vtkm::filter::flow::internal::BoundsMap& bm, int msgSz = 1, int numParticles = 1, int numBlockIds = 1) @@ -120,7 +120,7 @@ void TestParticleMessenger() //Only works for 2 or more ranks. if (comm.size() == 1) return; - vtkm::filter::particleadvection::BoundsMap boundsMap; + vtkm::filter::flow::internal::BoundsMap boundsMap; int maxMsgSz = 100; int maxNumParticles = 128; @@ -244,7 +244,7 @@ void TestBufferSizes() { //Make sure the buffer sizes are correct. auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); - vtkm::filter::particleadvection::BoundsMap boundsMap; + vtkm::filter::flow::internal::BoundsMap boundsMap; std::vector mSzs = { 1, 2, 3, 4, 5 }; std::vector numPs = { 1, 2, 3, 4, 5 }; diff --git a/vtkm/filter/testing/UnitTestStreamSurfaceFilter.cxx b/vtkm/filter/flow/testing/UnitTestStreamSurfaceFilter.cxx similarity index 95% rename from vtkm/filter/testing/UnitTestStreamSurfaceFilter.cxx rename to vtkm/filter/flow/testing/UnitTestStreamSurfaceFilter.cxx index ed085eb82..505f84ff5 100644 --- a/vtkm/filter/testing/UnitTestStreamSurfaceFilter.cxx +++ b/vtkm/filter/flow/testing/UnitTestStreamSurfaceFilter.cxx @@ -8,9 +8,10 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include #include -#include +#include namespace { @@ -44,7 +45,7 @@ void TestStreamSurface() vtkm::Particle(vtkm::Vec3f(.1f, 3.0f, .3f), 2), vtkm::Particle(vtkm::Vec3f(.1f, 3.5f, .2f), 3) }); - vtkm::filter::StreamSurface streamSrf; + vtkm::filter::flow::StreamSurface streamSrf; streamSrf.SetStepSize(0.1f); streamSrf.SetNumberOfSteps(20); diff --git a/vtkm/worklet/testing/UnitTestStreamSurface.cxx b/vtkm/filter/flow/testing/UnitTestStreamSurfaceWorklet.cxx similarity index 91% rename from vtkm/worklet/testing/UnitTestStreamSurface.cxx rename to vtkm/filter/flow/testing/UnitTestStreamSurfaceWorklet.cxx index 23f611794..79b70992a 100644 --- a/vtkm/worklet/testing/UnitTestStreamSurface.cxx +++ b/vtkm/filter/flow/testing/UnitTestStreamSurfaceWorklet.cxx @@ -8,11 +8,11 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include #include #include +#include #include -#include -#include namespace { @@ -53,7 +53,7 @@ void TestSameNumPolylines() dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids); vtkm::cont::DataSet ds = dsb.Create(); - vtkm::worklet::StreamSurface streamSurfaceWorklet; + vtkm::worklet::flow::StreamSurface streamSurfaceWorklet; vtkm::cont::ArrayHandle newPoints; vtkm::cont::CellSetSingleType<> newCells; streamSurfaceWorklet.Run(ds.GetCoordinateSystem(0), ds.GetCellSet(), newPoints, newCells); @@ -111,7 +111,7 @@ void TestUnequalNumPolylines(int unequalType) dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids); vtkm::cont::DataSet ds = dsb.Create(); - vtkm::worklet::StreamSurface streamSurfaceWorklet; + vtkm::worklet::flow::StreamSurface streamSurfaceWorklet; vtkm::cont::ArrayHandle newPoints; vtkm::cont::CellSetSingleType<> newCells; streamSurfaceWorklet.Run(ds.GetCoordinateSystem(0), ds.GetCellSet(), newPoints, newCells); @@ -124,7 +124,7 @@ void TestUnequalNumPolylines(int unequalType) "Wrong number of cells in StreamSurface worklet"); } -void TestStreamSurface() +void TestStreamSurfaceWorklet() { std::cout << "Testing Stream Surface Worklet" << std::endl; TestSameNumPolylines(); @@ -134,7 +134,7 @@ void TestStreamSurface() } } -int UnitTestStreamSurface(int argc, char* argv[]) +int UnitTestStreamSurfaceWorklet(int argc, char* argv[]) { - return vtkm::cont::testing::Testing::Run(TestStreamSurface, argc, argv); + return vtkm::cont::testing::Testing::Run(TestStreamSurfaceWorklet, argc, argv); } diff --git a/vtkm/filter/testing/UnitTestStreamlineFilter.cxx b/vtkm/filter/flow/testing/UnitTestStreamlineFilter.cxx similarity index 95% rename from vtkm/filter/testing/UnitTestStreamlineFilter.cxx rename to vtkm/filter/flow/testing/UnitTestStreamlineFilter.cxx index 3b6def36f..c138ddd7c 100644 --- a/vtkm/filter/testing/UnitTestStreamlineFilter.cxx +++ b/vtkm/filter/flow/testing/UnitTestStreamlineFilter.cxx @@ -8,12 +8,15 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -63,7 +66,7 @@ void TestStreamline() vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1), vtkm::Particle(vtkm::Vec3f(.2f, 3.0f, .2f), 2) }); - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(0.1f); streamline.SetNumberOfSteps(20); @@ -122,7 +125,7 @@ void TestPathline() vtkm::Id numExpectedPoints; if (fType == 0) { - vtkm::filter::Pathline filt; + vtkm::filter::flow::Pathline filt; filt.SetActiveField(var); filt.SetStepSize(stepSize); filt.SetNumberOfSteps(numSteps); @@ -135,7 +138,7 @@ void TestPathline() } else { - vtkm::filter::PathParticle filt; + vtkm::filter::flow::PathParticle filt; filt.SetActiveField(var); filt.SetStepSize(stepSize); filt.SetNumberOfSteps(numSteps); @@ -192,7 +195,7 @@ void TestAMRStreamline(bool useSL) ghosts[idx] = vtkm::CellClassification::Normal; idx++; } - dsOuter.AddCellField("vtkmGhostCells", ghosts); + dsOuter.AddGhostCellField(vtkm::cont::make_ArrayHandle(ghosts, vtkm::CopyFlag::On)); //Create a partitioned dataset with 1 inner and 1 outer. vtkm::cont::PartitionedDataSet pds; @@ -221,7 +224,7 @@ void TestAMRStreamline(bool useSL) if (useSL) { - vtkm::filter::Streamline filter; + vtkm::filter::flow::Streamline filter; filter.SetStepSize(0.1f); filter.SetNumberOfSteps(100000); filter.SetSeeds(seedArray); @@ -293,7 +296,7 @@ void TestAMRStreamline(bool useSL) } else { - vtkm::filter::ParticleAdvection filter; + vtkm::filter::flow::ParticleAdvection filter; filter.SetStepSize(0.1f); filter.SetNumberOfSteps(100000); filter.SetSeeds(seedArray); @@ -375,7 +378,7 @@ void TestPartitionedDataSet(vtkm::Id num, bool useGhost, FilterType fType) vtkm::cont::PartitionedDataSet out; if (fType == FilterType::STREAMLINE) { - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(0.1f); streamline.SetNumberOfSteps(100000); streamline.SetSeeds(seedArray); @@ -388,7 +391,7 @@ void TestPartitionedDataSet(vtkm::Id num, bool useGhost, FilterType fType) auto pds2 = allPDs2[idx]; AddVectorFields(pds2, fieldName, vecX); - vtkm::filter::Pathline pathline; + vtkm::filter::flow::Pathline pathline; pathline.SetPreviousTime(0); pathline.SetNextTime(1000); pathline.SetNextDataSet(pds2); @@ -439,7 +442,7 @@ void TestPartitionedDataSet(vtkm::Id num, bool useGhost, FilterType fType) vtkm::cont::PartitionedDataSet out; if (fType == FilterType::PARTICLE_ADVECTION) { - vtkm::filter::ParticleAdvection particleAdvection; + vtkm::filter::flow::ParticleAdvection particleAdvection; particleAdvection.SetStepSize(0.1f); particleAdvection.SetNumberOfSteps(100000); @@ -453,7 +456,7 @@ void TestPartitionedDataSet(vtkm::Id num, bool useGhost, FilterType fType) auto pds2 = allPDs2[idx]; AddVectorFields(pds2, fieldName, vecX); - vtkm::filter::PathParticle pathParticle; + vtkm::filter::flow::PathParticle pathParticle; pathParticle.SetPreviousTime(0); pathParticle.SetNextTime(1000); pathParticle.SetNextDataSet(pds2); @@ -465,6 +468,7 @@ void TestPartitionedDataSet(vtkm::Id num, bool useGhost, FilterType fType) out = pathParticle.Execute(pds); } + VTKM_TEST_ASSERT(out.GetNumberOfPartitions() == 1, "Wrong number of partitions in output"); auto ds = out.GetPartition(0); //Validate the result is correct. @@ -542,7 +546,7 @@ void TestStreamlineFile(const std::string& fname, vtkm::cont::DataSet output; if (useSL) { - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(stepSize); streamline.SetNumberOfSteps(maxSteps); streamline.SetSeeds(seedArray); @@ -551,7 +555,7 @@ void TestStreamlineFile(const std::string& fname, } else { - vtkm::filter::ParticleAdvection particleAdvection; + vtkm::filter::flow::ParticleAdvection particleAdvection; particleAdvection.SetStepSize(stepSize); particleAdvection.SetNumberOfSteps(maxSteps); particleAdvection.SetSeeds(seedArray); @@ -584,13 +588,14 @@ void TestStreamlineFilters() FilterType::STREAMLINE, FilterType::PATHLINE, FilterType::PATH_PARTICLE }; + + //fTypes = {FilterType::PARTICLE_ADVECTION,FilterType::STREAMLINE}; + //fTypes = {FilterType::PATHLINE}; for (int n = 1; n < 3; n++) { for (auto useGhost : flags) for (auto ft : fTypes) - { TestPartitionedDataSet(n, useGhost, ft); - } } TestStreamline(); diff --git a/vtkm/filter/testing/UnitTestStreamlineFilterMPI.cxx b/vtkm/filter/flow/testing/UnitTestStreamlineFilterMPI.cxx similarity index 95% rename from vtkm/filter/testing/UnitTestStreamlineFilterMPI.cxx rename to vtkm/filter/flow/testing/UnitTestStreamlineFilterMPI.cxx index 4af041bff..db3d2a89e 100644 --- a/vtkm/filter/testing/UnitTestStreamlineFilterMPI.cxx +++ b/vtkm/filter/flow/testing/UnitTestStreamlineFilterMPI.cxx @@ -8,10 +8,12 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ +#include +#include #include -#include -#include -#include +#include +#include +#include #include #include @@ -111,7 +113,7 @@ void TestAMRStreamline(FilterType fType, bool useThreaded) ghosts[idx] = vtkm::CellClassification::Normal; idx++; } - dsOuter.AddCellField("vtkmGhostCells", ghosts); + dsOuter.AddGhostCellField(vtkm::cont::make_ArrayHandle(ghosts, vtkm::CopyFlag::On)); //Create a partitioned dataset with 1 inner and 1 outer. vtkm::cont::PartitionedDataSet pds; @@ -149,13 +151,13 @@ void TestAMRStreamline(FilterType fType, bool useThreaded) if (fType == STREAMLINE) { - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; SetFilter(streamline, stepSize, numSteps, fieldName, seedArray, useThreaded); out = streamline.Execute(pds); } else if (fType == PATHLINE) { - vtkm::filter::Pathline pathline; + vtkm::filter::flow::Pathline pathline; SetFilter(pathline, stepSize, numSteps, fieldName, seedArray, useThreaded); //Create timestep 2 auto pds2 = vtkm::cont::PartitionedDataSet(pds); @@ -239,7 +241,7 @@ void TestAMRStreamline(FilterType fType, bool useThreaded) } else if (fType == PARTICLE_ADVECTION) { - vtkm::filter::ParticleAdvection filter; + vtkm::filter::flow::ParticleAdvection filter; filter.SetUseThreadedAlgorithm(useThreaded); filter.SetStepSize(0.1f); filter.SetNumberOfSteps(100000); @@ -283,6 +285,8 @@ void ValidateOutput(const vtkm::cont::DataSet& out, "Wrong number of coordinate systems in the output dataset"); vtkm::cont::UnknownCellSet dcells = out.GetCellSet(); + out.PrintSummary(std::cout); + std::cout << " nSeeds= " << numSeeds << std::endl; VTKM_TEST_ASSERT(dcells.GetNumberOfCells() == numSeeds, "Wrong number of cells"); auto coords = out.GetCoordinateSystem().GetDataAsMultiplexer(); auto ptPortal = coords.ReadPortal(); @@ -392,7 +396,7 @@ void TestPartitionedDataSet(vtkm::Id nPerRank, bool useGhost, FilterType fType, if (fType == STREAMLINE) { - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; SetFilter(streamline, stepSize, numSteps, fieldName, seedArray, useThreaded); auto out = streamline.Execute(pds); @@ -401,7 +405,7 @@ void TestPartitionedDataSet(vtkm::Id nPerRank, bool useGhost, FilterType fType, } else if (fType == PARTICLE_ADVECTION) { - vtkm::filter::ParticleAdvection particleAdvection; + vtkm::filter::flow::ParticleAdvection particleAdvection; SetFilter(particleAdvection, stepSize, numSteps, fieldName, seedArray, useThreaded); auto out = particleAdvection.Execute(pds); @@ -419,7 +423,7 @@ void TestPartitionedDataSet(vtkm::Id nPerRank, bool useGhost, FilterType fType, auto pds2 = allPDS2[n]; AddVectorFields(pds2, fieldName, vecX); - vtkm::filter::Pathline pathline; + vtkm::filter::flow::Pathline pathline; SetFilter(pathline, stepSize, numSteps, fieldName, seedArray, useThreaded); pathline.SetPreviousTime(time0); diff --git a/vtkm/worklet/testing/UnitTestParticleAdvection.cxx b/vtkm/filter/flow/testing/UnitTestWorkletParticleAdvection.cxx similarity index 89% rename from vtkm/worklet/testing/UnitTestParticleAdvection.cxx rename to vtkm/filter/flow/testing/UnitTestWorkletParticleAdvection.cxx index 82cdea921..884449ed5 100644 --- a/vtkm/worklet/testing/UnitTestParticleAdvection.cxx +++ b/vtkm/filter/flow/testing/UnitTestWorkletParticleAdvection.cxx @@ -9,19 +9,20 @@ //============================================================================ #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -142,7 +143,7 @@ public: template VTKM_EXEC void operator()(vtkm::Particle& pointIn, const EvaluatorType& evaluator, - vtkm::worklet::particleadvection::GridEvaluatorStatus& status, + vtkm::worklet::flow::GridEvaluatorStatus& status, vtkm::Vec3f& pointOut) const { vtkm::VecVariable values; @@ -159,7 +160,7 @@ void ValidateEvaluator(const EvalType& eval, { using EvalTester = TestEvaluatorWorklet; using EvalTesterDispatcher = vtkm::worklet::DispatcherMapField; - using Status = vtkm::worklet::particleadvection::GridEvaluatorStatus; + using Status = vtkm::worklet::flow::GridEvaluatorStatus; EvalTester evalTester; EvalTesterDispatcher evalTesterDispatcher(evalTester); vtkm::cont::ArrayHandle pointsHandle = @@ -192,7 +193,7 @@ public: template VTKM_EXEC void operator()(Particle& pointIn, const IntegratorType integrator, - vtkm::worklet::particleadvection::IntegratorStatus& status, + vtkm::worklet::flow::IntegratorStatus& status, vtkm::Vec3f& pointOut) const { vtkm::FloatDefault time = 0; @@ -211,7 +212,7 @@ void ValidateIntegrator(const IntegratorType& integrator, { using IntegratorTester = TestIntegratorWorklet; using IntegratorTesterDispatcher = vtkm::worklet::DispatcherMapField; - using Status = vtkm::worklet::particleadvection::IntegratorStatus; + using Status = vtkm::worklet::flow::IntegratorStatus; IntegratorTesterDispatcher integratorTesterDispatcher; auto pointsHandle = vtkm::cont::make_ArrayHandle(pointIns, vtkm::CopyFlag::Off); vtkm::Id numPoints = pointsHandle.GetNumberOfValues(); @@ -243,7 +244,7 @@ void ValidateIntegratorForBoundary(const vtkm::Bounds& bounds, { using IntegratorTester = TestIntegratorWorklet; using IntegratorTesterDispatcher = vtkm::worklet::DispatcherMapField; - using Status = vtkm::worklet::particleadvection::IntegratorStatus; + using Status = vtkm::worklet::flow::IntegratorStatus; IntegratorTesterDispatcher integratorTesterDispatcher; auto pointsHandle = vtkm::cont::make_ArrayHandle(pointIns, vtkm::CopyFlag::Off); @@ -269,10 +270,10 @@ void ValidateIntegratorForBoundary(const vtkm::Bounds& bounds, void TestEvaluators() { using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; std::vector vecs; vtkm::FloatDefault vals[3] = { -1., 0., 1. }; @@ -364,10 +365,10 @@ void TestEvaluators() void TestGhostCellEvaluators() { using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; constexpr vtkm::Id nX = 6; constexpr vtkm::Id nY = 6; @@ -395,7 +396,7 @@ void TestGhostCellEvaluators() vtkm::FloatDefault stepSize = static_cast(0.1); Stepper rk4(gridEval, stepSize); - vtkm::worklet::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvection pa; std::vector seeds; //Points in a ghost cell. seeds.push_back(vtkm::Particle(vtkm::Vec3f(.5, .5, .5), 0)); @@ -426,7 +427,7 @@ void TestGhostCellEvaluators() } void ValidateParticleAdvectionResult( - const vtkm::worklet::ParticleAdvectionResult& res, + const vtkm::worklet::flow::ParticleAdvectionResult& res, vtkm::Id nSeeds, vtkm::Id maxSteps) { @@ -446,7 +447,7 @@ void ValidateParticleAdvectionResult( } } -void ValidateStreamlineResult(const vtkm::worklet::StreamlineResult& res, +void ValidateStreamlineResult(const vtkm::worklet::flow::StreamlineResult& res, vtkm::Id nSeeds, vtkm::Id maxSteps) { @@ -465,8 +466,8 @@ void ValidateStreamlineResult(const vtkm::worklet::StreamlineResult; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; const vtkm::Id3 dims(5, 5, 5); const vtkm::Bounds bounds(0., 1., 0., 1., .0, .1); @@ -491,20 +492,20 @@ void TestIntegrators() std::vector points; GenerateRandomParticles(points, 3, bounds); - vtkm::worklet::ParticleAdvection pa; - vtkm::worklet::ParticleAdvectionResult res; + vtkm::worklet::flow::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvectionResult res; { auto seeds = vtkm::cont::make_ArrayHandle(points, vtkm::CopyFlag::On); - using IntegratorType = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using IntegratorType = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; Stepper rk4(eval, stepSize); res = pa.Run(rk4, seeds, maxSteps); ValidateParticleAdvectionResult(res, nSeeds, maxSteps); } { auto seeds = vtkm::cont::make_ArrayHandle(points, vtkm::CopyFlag::On); - using IntegratorType = vtkm::worklet::particleadvection::EulerIntegrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using IntegratorType = vtkm::worklet::flow::EulerIntegrator; + using Stepper = vtkm::worklet::flow::Stepper; Stepper euler(eval, stepSize); res = pa.Run(euler, seeds, maxSteps); ValidateParticleAdvectionResult(res, nSeeds, maxSteps); @@ -515,10 +516,10 @@ void TestIntegrators() void TestParticleWorkletsWithDataSetTypes() { using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; vtkm::FloatDefault stepSize = 0.01f; const vtkm::Id3 dims(5, 5, 5); @@ -569,8 +570,8 @@ void TestParticleWorkletsWithDataSetTypes() { if (i < 2) { - vtkm::worklet::ParticleAdvection pa; - vtkm::worklet::ParticleAdvectionResult res; + vtkm::worklet::flow::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvectionResult res; if (i == 0) { auto seeds = vtkm::cont::make_ArrayHandle(pts, vtkm::CopyFlag::On); @@ -585,8 +586,8 @@ void TestParticleWorkletsWithDataSetTypes() } else { - vtkm::worklet::Streamline s; - vtkm::worklet::StreamlineResult res; + vtkm::worklet::flow::Streamline s; + vtkm::worklet::flow::StreamlineResult res; if (i == 2) { auto seeds = vtkm::cont::make_ArrayHandle(pts, vtkm::CopyFlag::On); @@ -618,10 +619,10 @@ void TestParticleStatus() auto dataSets = vtkm::worklet::testing::CreateAllDataSets(bounds, dims, false); for (auto& ds : dataSets) { - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; vtkm::Id maxSteps = 1000; vtkm::FloatDefault stepSize = 0.01f; @@ -631,7 +632,7 @@ void TestParticleStatus() GridEvalType eval(ds, velocities); Stepper rk4(eval, stepSize); - vtkm::worklet::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvection pa; std::vector pts; pts.push_back(vtkm::Particle(vtkm::Vec3f(.5, .5, .5), 0)); pts.push_back(vtkm::Particle(vtkm::Vec3f(-1, -1, -1), 1)); @@ -649,10 +650,10 @@ void TestParticleStatus() void TestWorkletsBasic() { using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; vtkm::FloatDefault stepSize = 0.01f; const vtkm::Id3 dims(5, 5, 5); @@ -711,8 +712,8 @@ void TestWorkletsBasic() if (w == "particleAdvection") { - vtkm::worklet::ParticleAdvection pa; - vtkm::worklet::ParticleAdvectionResult res; + vtkm::worklet::flow::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvectionResult res; res = pa.Run(rk4, seedsArray, maxSteps); @@ -735,8 +736,8 @@ void TestWorkletsBasic() } else if (w == "streamline") { - vtkm::worklet::Streamline s; - vtkm::worklet::StreamlineResult res; + vtkm::worklet::flow::Streamline s; + vtkm::worklet::flow::StreamlineResult res; res = s.Run(rk4, seedsArray, maxSteps); @@ -830,10 +831,10 @@ void TestParticleAdvectionFile(const std::string& fname, } using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator; - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; + using FieldType = vtkm::worklet::flow::VelocityField; + using GridEvalType = vtkm::worklet::flow::GridEvaluator; + using RK4Type = vtkm::worklet::flow::RK4Integrator; + using Stepper = vtkm::worklet::flow::Stepper; VTKM_TEST_ASSERT(ds.HasField("vec"), "Data set missing a field named 'vec'"); vtkm::cont::Field& field = ds.GetField("vec"); @@ -862,16 +863,16 @@ void TestParticleAdvectionFile(const std::string& fname, if (i == 0) { - vtkm::worklet::ParticleAdvection pa; - vtkm::worklet::ParticleAdvectionResult res; + vtkm::worklet::flow::ParticleAdvection pa; + vtkm::worklet::flow::ParticleAdvectionResult res; res = pa.Run(rk4, seedArray, maxSteps); ValidateResult(res, maxSteps, endPts); } else if (i == 1) { - vtkm::worklet::Streamline s; - vtkm::worklet::StreamlineResult res; + vtkm::worklet::flow::Streamline s; + vtkm::worklet::flow::StreamlineResult res; res = s.Run(rk4, seedArray, maxSteps); ValidateResult(res, maxSteps, endPts); @@ -917,7 +918,7 @@ void TestParticleAdvection() TestParticleAdvectionFile(fishFile, fishPts, fishStep, 100, fishEndPts); } -int UnitTestParticleAdvection(int argc, char* argv[]) +int UnitTestWorkletParticleAdvection(int argc, char* argv[]) { return vtkm::cont::testing::Testing::Run(TestParticleAdvection, argc, argv); } diff --git a/vtkm/worklet/testing/UnitTestTemporalAdvection.cxx b/vtkm/filter/flow/testing/UnitTestWorkletTemporalAdvection.cxx similarity index 90% rename from vtkm/worklet/testing/UnitTestTemporalAdvection.cxx rename to vtkm/filter/flow/testing/UnitTestWorkletTemporalAdvection.cxx index f1a470aa5..9cb4ddbe3 100644 --- a/vtkm/worklet/testing/UnitTestTemporalAdvection.cxx +++ b/vtkm/filter/flow/testing/UnitTestWorkletTemporalAdvection.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -17,11 +18,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include template vtkm::cont::DataSet CreateUniformDataSet(const vtkm::Bounds& bounds, const vtkm::Id3& dims) @@ -52,7 +53,7 @@ public: template VTKM_EXEC void operator()(vtkm::Particle& pointIn, const EvaluatorType& evaluator, - vtkm::worklet::particleadvection::GridEvaluatorStatus& status, + vtkm::worklet::flow::GridEvaluatorStatus& status, vtkm::Vec3f& pointOut) const { vtkm::VecVariable values; @@ -70,7 +71,7 @@ void ValidateEvaluator(const EvalType& eval, { using EvalTester = TestEvaluatorWorklet; using EvalTesterDispatcher = vtkm::worklet::DispatcherMapField; - using Status = vtkm::worklet::particleadvection::GridEvaluatorStatus; + using Status = vtkm::worklet::flow::GridEvaluatorStatus; EvalTester evalTester; EvalTesterDispatcher evalTesterDispatcher(evalTester); @@ -149,9 +150,9 @@ void TestTemporalEvaluators() using ScalarType = vtkm::FloatDefault; using PointType = vtkm::Vec; using FieldHandle = vtkm::cont::ArrayHandle; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using EvalType = vtkm::worklet::particleadvection::GridEvaluator; - using TemporalEvalType = vtkm::worklet::particleadvection::TemporalGridEvaluator; + using FieldType = vtkm::worklet::flow::VelocityField; + using EvalType = vtkm::worklet::flow::GridEvaluator; + using TemporalEvalType = vtkm::worklet::flow::TemporalGridEvaluator; // Create Datasets vtkm::Id3 dims(5, 5, 5); @@ -189,7 +190,7 @@ void TestTemporalAdvection() TestTemporalEvaluators(); } -int UnitTestTemporalAdvection(int argc, char* argv[]) +int UnitTestWorkletTemporalAdvection(int argc, char* argv[]) { return vtkm::cont::testing::Testing::Run(TestTemporalAdvection, argc, argv); } diff --git a/vtkm/worklet/particleadvection/CMakeLists.txt b/vtkm/filter/flow/worklet/CMakeLists.txt similarity index 95% rename from vtkm/worklet/particleadvection/CMakeLists.txt rename to vtkm/filter/flow/worklet/CMakeLists.txt index 9afc70707..1d5116a6c 100644 --- a/vtkm/worklet/particleadvection/CMakeLists.txt +++ b/vtkm/filter/flow/worklet/CMakeLists.txt @@ -9,6 +9,7 @@ ##============================================================================ set(headers + ParticleAdvection.h CellInterpolationHelper.h EulerIntegrator.h Field.h @@ -20,6 +21,7 @@ set(headers ParticleAdvectionWorklets.h RK4Integrator.h TemporalGridEvaluators.h + StreamSurface.h ) #----------------------------------------------------------------------------- diff --git a/vtkm/worklet/particleadvection/CellInterpolationHelper.h b/vtkm/filter/flow/worklet/CellInterpolationHelper.h similarity index 97% rename from vtkm/worklet/particleadvection/CellInterpolationHelper.h rename to vtkm/filter/flow/worklet/CellInterpolationHelper.h index 52534afbc..1cc507a99 100644 --- a/vtkm/worklet/particleadvection/CellInterpolationHelper.h +++ b/vtkm/filter/flow/worklet/CellInterpolationHelper.h @@ -8,8 +8,8 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particle_advection_cell_interpolation_helper -#define vtk_m_worklet_particle_advection_cell_interpolation_helper +#ifndef vtk_m_filter_flow_worklet_CellInterpolationHelper_h +#define vtk_m_filter_flow_worklet_CellInterpolationHelper_h #include #include @@ -282,4 +282,4 @@ private: } //namespace cont } //namespace vtkm -#endif //vtk_m_worklet_particle_advection_cell_interpolation_helper +#endif //vtk_m_filter_flow_worklet_CellInterpolationHelper_h diff --git a/vtkm/worklet/particleadvection/EulerIntegrator.h b/vtkm/filter/flow/worklet/EulerIntegrator.h similarity index 86% rename from vtkm/worklet/particleadvection/EulerIntegrator.h rename to vtkm/filter/flow/worklet/EulerIntegrator.h index 9653765da..8d2b074bd 100644 --- a/vtkm/worklet/particleadvection/EulerIntegrator.h +++ b/vtkm/filter/flow/worklet/EulerIntegrator.h @@ -10,14 +10,17 @@ // //============================================================================= -#ifndef vtk_m_worklet_particleadvection_EulerIntegrator_h -#define vtk_m_worklet_particleadvection_EulerIntegrator_h +#ifndef vtk_m_filter_flow_worklet_EulerIntegrator_h +#define vtk_m_filter_flow_worklet_EulerIntegrator_h + +#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template @@ -73,8 +76,8 @@ public: } }; //EulerIntegrator -} //namespace particleadvection -} //namespace worklet -} //namespace vtkm +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_EulerIntegrator_h +#endif // vtk_m_filter_flow_worklet_EulerIntegrator_h diff --git a/vtkm/worklet/particleadvection/Field.h b/vtkm/filter/flow/worklet/Field.h similarity index 96% rename from vtkm/worklet/particleadvection/Field.h rename to vtkm/filter/flow/worklet/Field.h index 3a2a5aae3..3d3124800 100644 --- a/vtkm/worklet/particleadvection/Field.h +++ b/vtkm/filter/flow/worklet/Field.h @@ -8,8 +8,8 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtkm_woklet_particleadvection_field_h -#define vtkm_woklet_particleadvection_field_h +#ifndef vtkm_filter_flow_worklet_Field_h +#define vtkm_filter_flow_worklet_Field_h #include @@ -22,7 +22,7 @@ namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template @@ -209,7 +209,8 @@ private: Association Assoc; }; -} // namespace particleadvection -} // namespace worklet -} // namespace -#endif //vtkm_woklet_particleadvection_field_h +} +} +} //vtkm::worklet::flow + +#endif //vtkm_filter_flow_worklet_Field_h diff --git a/vtkm/worklet/particleadvection/GridEvaluatorStatus.h b/vtkm/filter/flow/worklet/GridEvaluatorStatus.h similarity index 78% rename from vtkm/worklet/particleadvection/GridEvaluatorStatus.h rename to vtkm/filter/flow/worklet/GridEvaluatorStatus.h index 44182cec1..055ceb60b 100644 --- a/vtkm/worklet/particleadvection/GridEvaluatorStatus.h +++ b/vtkm/filter/flow/worklet/GridEvaluatorStatus.h @@ -8,25 +8,16 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particleadvection_GridEvaluatorStatus_h -#define vtk_m_worklet_particleadvection_GridEvaluatorStatus_h +#ifndef vtk_m_filter_flow_worklet_GridEvaluatorStatus_h +#define vtk_m_filter_flow_worklet_GridEvaluatorStatus_h #include -#include -#include -#include -#include -#include -#include -#include -#include -#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { class GridEvaluatorStatus : public vtkm::Bitset @@ -62,8 +53,9 @@ private: static constexpr vtkm::Id TEMPORAL_BOUNDS_BIT = 2; static constexpr vtkm::Id IN_GHOST_CELL_BIT = 3; }; + } } } -#endif // vtk_m_worklet_particleadvection_GridEvaluatorStatus_h +#endif // vtk_m_filter_flow_worklet_GridEvaluatorStatus_h diff --git a/vtkm/worklet/particleadvection/GridEvaluators.h b/vtkm/filter/flow/worklet/GridEvaluators.h similarity index 91% rename from vtkm/worklet/particleadvection/GridEvaluators.h rename to vtkm/filter/flow/worklet/GridEvaluators.h index 70fe9b398..ff92c694f 100644 --- a/vtkm/worklet/particleadvection/GridEvaluators.h +++ b/vtkm/filter/flow/worklet/GridEvaluators.h @@ -8,14 +8,10 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particleadvection_GridEvaluators_h -#define vtk_m_worklet_particleadvection_GridEvaluators_h +#ifndef vtk_m_filter_flow_worklet_GridEvaluators_h +#define vtk_m_filter_flow_worklet_GridEvaluators_h -#include #include -#include -#include -#include #include #include #include @@ -24,15 +20,15 @@ #include #include -#include -#include -#include +#include +#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template @@ -184,9 +180,9 @@ public: { this->InitializeLocator(dataSet.GetCoordinateSystem(), dataSet.GetCellSet()); - if (dataSet.HasCellField("vtkmGhostCells")) + if (dataSet.HasGhostCellField()) { - auto arr = dataSet.GetCellField("vtkmGhostCells").GetData(); + auto arr = dataSet.GetGhostCellField().GetData(); vtkm::cont::ArrayCopyShallowIfPossible(arr, this->GhostCellArray); } } @@ -232,8 +228,8 @@ private: vtkm::cont::CellLocatorGeneral Locator; }; -} //namespace particleadvection -} //namespace worklet -} //namespace vtkm +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_GridEvaluators_h +#endif // vtk_m_filter_flow_worklet_GridEvaluators_h diff --git a/vtkm/worklet/particleadvection/IntegratorStatus.h b/vtkm/filter/flow/worklet/IntegratorStatus.h similarity index 91% rename from vtkm/worklet/particleadvection/IntegratorStatus.h rename to vtkm/filter/flow/worklet/IntegratorStatus.h index a7985e847..ff0657afe 100644 --- a/vtkm/worklet/particleadvection/IntegratorStatus.h +++ b/vtkm/filter/flow/worklet/IntegratorStatus.h @@ -10,8 +10,8 @@ // //============================================================================= -#ifndef vtk_m_worklet_particleadvection_Integrator_Status_h -#define vtk_m_worklet_particleadvection_Integrator_Status_h +#ifndef vtk_m_filter_flow_worklet_IntegratorStatus_h +#define vtk_m_filter_flow_worklet_IntegratorStatus_h #include #include @@ -21,13 +21,13 @@ #include #include -#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { class IntegratorStatus : public vtkm::Bitset @@ -82,9 +82,9 @@ inline VTKM_CONT std::ostream& operator<<(std::ostream& s, const IntegratorStatu << " tm= " << status.CheckTemporalBounds() << " gc= " << status.CheckInGhostCell() << "]"; return s; } -} -} -} +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_IntegratorStatus_h +#endif // vtk_m_filter_flow_worklet_IntegratorStatus_h diff --git a/vtkm/worklet/ParticleAdvection.h b/vtkm/filter/flow/worklet/ParticleAdvection.h similarity index 79% rename from vtkm/worklet/ParticleAdvection.h rename to vtkm/filter/flow/worklet/ParticleAdvection.h index 66e3dee86..fa28c9ae6 100644 --- a/vtkm/worklet/ParticleAdvection.h +++ b/vtkm/filter/flow/worklet/ParticleAdvection.h @@ -8,19 +8,18 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_ParticleAdvection_h -#define vtk_m_worklet_ParticleAdvection_h +#ifndef vtk_m_filter_flow_worklet_ParticleAdvection_h +#define vtk_m_filter_flow_worklet_ParticleAdvection_h -#include -#include -#include #include -#include +#include namespace vtkm { namespace worklet { +namespace flow +{ namespace detail { @@ -70,14 +69,25 @@ class ParticleAdvection public: ParticleAdvection() {} + template + void Run2(const IntegratorType& it, + vtkm::cont::ArrayHandle& particles, + vtkm::Id MaxSteps, + ParticleAdvectionResult& result) + { + vtkm::worklet::flow::ParticleAdvectionWorklet worklet; + + worklet.Run(it, particles, MaxSteps); + result = ParticleAdvectionResult(particles); + } + template ParticleAdvectionResult Run( const IntegratorType& it, vtkm::cont::ArrayHandle& particles, vtkm::Id MaxSteps) { - vtkm::worklet::particleadvection::ParticleAdvectionWorklet - worklet; + vtkm::worklet::flow::ParticleAdvectionWorklet worklet; worklet.Run(it, particles, MaxSteps); return ParticleAdvectionResult(particles); @@ -89,8 +99,7 @@ public: const vtkm::cont::ArrayHandle& points, vtkm::Id MaxSteps) { - vtkm::worklet::particleadvection::ParticleAdvectionWorklet - worklet; + vtkm::worklet::flow::ParticleAdvectionWorklet worklet; vtkm::cont::ArrayHandle particles; vtkm::cont::ArrayHandle step, ids; @@ -148,7 +157,7 @@ public: vtkm::cont::ArrayHandle& particles, vtkm::Id MaxSteps) { - vtkm::worklet::particleadvection::StreamlineWorklet worklet; + vtkm::worklet::flow::StreamlineWorklet worklet; vtkm::cont::ArrayHandle positions; vtkm::cont::CellSetExplicit<> polyLines; @@ -158,7 +167,9 @@ public: return StreamlineResult(particles, positions, polyLines); } }; -} -} -#endif // vtk_m_worklet_ParticleAdvection_h +} +} +} // vtkm::worklet::flow + +#endif // vtk_m_filter_flow_worklet_ParticleAdvection_h diff --git a/vtkm/worklet/particleadvection/ParticleAdvectionWorklets.h b/vtkm/filter/flow/worklet/ParticleAdvectionWorklets.h similarity index 88% rename from vtkm/worklet/particleadvection/ParticleAdvectionWorklets.h rename to vtkm/filter/flow/worklet/ParticleAdvectionWorklets.h index 8fda04b7f..af3d5a730 100644 --- a/vtkm/worklet/particleadvection/ParticleAdvectionWorklets.h +++ b/vtkm/filter/flow/worklet/ParticleAdvectionWorklets.h @@ -8,23 +8,17 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particleadvection_ParticleAdvectionWorklets_h -#define vtk_m_worklet_particleadvection_ParticleAdvectionWorklets_h +#ifndef vtk_m_filter_flow_worklet_ParticleAdvectionWorklets_h +#define vtk_m_filter_flow_worklet_ParticleAdvectionWorklets_h -#include #include -#include -#include -#include -#include #include #include #include #include +#include #include -#include -#include #ifdef VTKM_CUDA #include @@ -34,7 +28,7 @@ namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { class ParticleAdvectWorklet : public vtkm::worklet::WorkletMapField @@ -106,10 +100,10 @@ public: vtkm::Id& MaxSteps) { - using ParticleAdvectWorkletType = vtkm::worklet::particleadvection::ParticleAdvectWorklet; + using ParticleAdvectWorkletType = vtkm::worklet::flow::ParticleAdvectWorklet; using ParticleWorkletDispatchType = typename vtkm::worklet::DispatcherMapField; - using ParticleArrayType = vtkm::worklet::particleadvection::Particles; + using ParticleArrayType = vtkm::worklet::flow::Particles; vtkm::Id numSeeds = static_cast(particles.GetNumberOfValues()); //Create and invoke the particle advection. @@ -186,10 +180,9 @@ public: vtkm::cont::CellSetExplicit<>& polyLines) { - using ParticleWorkletDispatchType = typename vtkm::worklet::DispatcherMapField< - vtkm::worklet::particleadvection::ParticleAdvectWorklet>; - using StreamlineArrayType = - vtkm::worklet::particleadvection::StateRecordingParticles; + using ParticleWorkletDispatchType = + typename vtkm::worklet::DispatcherMapField; + using StreamlineArrayType = vtkm::worklet::flow::StateRecordingParticles; vtkm::cont::ArrayHandle initialStepsTaken; @@ -238,8 +231,9 @@ public: polyLines.Fill(positions.GetNumberOfValues(), cellTypes, connectivity, offsets); } }; -} -} -} // namespace vtkm::worklet::particleadvection -#endif // vtk_m_worklet_particleadvection_ParticleAdvectionWorklets_h +} +} +} // namespace vtkm::worklet::flow + +#endif // vtk_m_filter_flow_worklet_ParticleAdvectionWorklets_h diff --git a/vtkm/worklet/particleadvection/Particles.h b/vtkm/filter/flow/worklet/Particles.h similarity index 88% rename from vtkm/worklet/particleadvection/Particles.h rename to vtkm/filter/flow/worklet/Particles.h index 0d7fde155..d0087d79f 100644 --- a/vtkm/worklet/particleadvection/Particles.h +++ b/vtkm/filter/flow/worklet/Particles.h @@ -8,23 +8,19 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particleadvection_Particles_h -#define vtk_m_worklet_particleadvection_Particles_h +#ifndef vtk_m_filter_flow_worklet_Particles_h +#define vtk_m_filter_flow_worklet_Particles_h -#include -#include -#include -#include -#include #include -#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { + template class ParticleExecutionObject { @@ -66,7 +62,7 @@ public: VTKM_EXEC void StatusUpdate(const vtkm::Id& idx, - const vtkm::worklet::particleadvection::IntegratorStatus& status, + const vtkm::worklet::flow::IntegratorStatus& status, vtkm::Id maxSteps) { ParticleType p(this->GetParticle(idx)); @@ -116,10 +112,11 @@ template class Particles : public vtkm::cont::ExecutionObjectBase { public: - VTKM_CONT vtkm::worklet::particleadvection::ParticleExecutionObject - PrepareForExecution(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const + VTKM_CONT vtkm::worklet::flow::ParticleExecutionObject PrepareForExecution( + vtkm::cont::DeviceAdapterId device, + vtkm::cont::Token& token) const { - return vtkm::worklet::particleadvection::ParticleExecutionObject( + return vtkm::worklet::flow::ParticleExecutionObject( this->ParticleArray, this->MaxSteps, device, token); } @@ -221,10 +218,10 @@ public: }; - VTKM_CONT vtkm::worklet::particleadvection::StateRecordingParticleExecutionObject + VTKM_CONT vtkm::worklet::flow::StateRecordingParticleExecutionObject PrepareForExecution(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const { - return vtkm::worklet::particleadvection::StateRecordingParticleExecutionObject( + return vtkm::worklet::flow::StateRecordingParticleExecutionObject( this->ParticleArray, this->HistoryArray, this->ValidPointArray, @@ -276,9 +273,9 @@ protected: }; -} //namespace particleadvection -} //namespace worklet -} //namespace vtkm +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_Particles_h +#endif // vtk_m_filter_flow_worklet_Particles_h //============================================================================ diff --git a/vtkm/worklet/particleadvection/RK4Integrator.h b/vtkm/filter/flow/worklet/RK4Integrator.h similarity index 91% rename from vtkm/worklet/particleadvection/RK4Integrator.h rename to vtkm/filter/flow/worklet/RK4Integrator.h index e6398c093..ffeab255b 100644 --- a/vtkm/worklet/particleadvection/RK4Integrator.h +++ b/vtkm/filter/flow/worklet/RK4Integrator.h @@ -10,14 +10,17 @@ // //============================================================================= -#ifndef vtk_m_worklet_particleadvection_RK4Integrator_h -#define vtk_m_worklet_particleadvection_RK4Integrator_h +#ifndef vtk_m_filter_flow_worklet_RK4Integrator_h +#define vtk_m_filter_flow_worklet_RK4Integrator_h + +#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template @@ -112,8 +115,8 @@ public: } }; -} //namespace particleadvection -} //namespace worklet -} //namespace vtkm +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_RK4Integrator_h +#endif // vtk_m_filter_flow_worklet_RK4Integrator_h diff --git a/vtkm/worklet/particleadvection/Stepper.h b/vtkm/filter/flow/worklet/Stepper.h similarity index 91% rename from vtkm/worklet/particleadvection/Stepper.h rename to vtkm/filter/flow/worklet/Stepper.h index 5cc6bf91f..4023bfa04 100644 --- a/vtkm/worklet/particleadvection/Stepper.h +++ b/vtkm/filter/flow/worklet/Stepper.h @@ -10,27 +10,20 @@ // //============================================================================= -#ifndef vtk_m_worklet_particleadvection_Stepper_h -#define vtk_m_worklet_particleadvection_Stepper_h +#ifndef vtk_m_filter_flow_worklet_Stepper_h +#define vtk_m_filter_flow_worklet_Stepper_h + +#include +#include +#include #include -#include -#include -#include -#include - -#include - -#include -#include -#include - namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template @@ -194,8 +187,8 @@ public: } }; -} //namespace particleadvection -} //namespace worklet -} //namespace vtkm +} +} +} //vtkm::worklet::flow -#endif // vtk_m_worklet_particleadvection_Stepper_h +#endif // vtk_m_filter_flow_worklet_Stepper_h diff --git a/vtkm/worklet/StreamSurface.h b/vtkm/filter/flow/worklet/StreamSurface.h similarity index 97% rename from vtkm/worklet/StreamSurface.h rename to vtkm/filter/flow/worklet/StreamSurface.h index a7fef872f..6108abd0e 100644 --- a/vtkm/worklet/StreamSurface.h +++ b/vtkm/filter/flow/worklet/StreamSurface.h @@ -7,15 +7,11 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_streamsurface_h -#define vtk_m_worklet_streamsurface_h +#ifndef vtk_m_filter_flow_worklet_streamsurface_h +#define vtk_m_filter_flow_worklet_streamsurface_h -#include -#include -#include #include #include -#include #include #include #include @@ -24,6 +20,8 @@ namespace vtkm { namespace worklet { +namespace flow +{ class StreamSurface { @@ -276,7 +274,9 @@ public: private: }; -} -} -#endif // vtk_m_worklet_streamsurface_h +} +} +} //vtkm::worklet::flow + +#endif // vtk_m_filter_flow_worklet_streamsurface_h diff --git a/vtkm/worklet/particleadvection/TemporalGridEvaluators.h b/vtkm/filter/flow/worklet/TemporalGridEvaluators.h similarity index 89% rename from vtkm/worklet/particleadvection/TemporalGridEvaluators.h rename to vtkm/filter/flow/worklet/TemporalGridEvaluators.h index 62c44ce11..521b3ebb9 100644 --- a/vtkm/worklet/particleadvection/TemporalGridEvaluators.h +++ b/vtkm/filter/flow/worklet/TemporalGridEvaluators.h @@ -8,26 +8,25 @@ // PURPOSE. See the above copyright notice for more information. //============================================================================ -#ifndef vtk_m_worklet_particleadvection_TemporalGridEvaluators_h -#define vtk_m_worklet_particleadvection_TemporalGridEvaluators_h +#ifndef vtk_m_filter_flow_worklet_TemporalGridEvaluators_h +#define vtk_m_filter_flow_worklet_TemporalGridEvaluators_h -#include -#include +#include +#include namespace vtkm { namespace worklet { -namespace particleadvection +namespace flow { template class ExecutionTemporalGridEvaluator { private: - using GridEvaluator = vtkm::worklet::particleadvection::GridEvaluator; - using ExecutionGridEvaluator = - vtkm::worklet::particleadvection::ExecutionGridEvaluator; + using GridEvaluator = vtkm::worklet::flow::GridEvaluator; + using ExecutionGridEvaluator = vtkm::worklet::flow::ExecutionGridEvaluator; public: VTKM_CONT @@ -117,7 +116,7 @@ template class TemporalGridEvaluator : public vtkm::cont::ExecutionObjectBase { private: - using GridEvaluator = vtkm::worklet::particleadvection::GridEvaluator; + using GridEvaluator = vtkm::worklet::flow::GridEvaluator; public: VTKM_CONT TemporalGridEvaluator() = default; @@ -178,8 +177,8 @@ private: vtkm::FloatDefault TimeTwo; }; -} // namespace particleadvection -} // namespace worklet -} // namespace vtkm +} +} +} //vtkm::worklet::flow -#endif +#endif // vtk_m_filter_flow_worklet_TemporalGridEvaluators_h diff --git a/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx b/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx index b864b9182..a6a7e8736 100644 --- a/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx +++ b/vtkm/filter/geometry_refinement/testing/UnitTestTubeFilter.cxx @@ -23,7 +23,6 @@ void appendPts(vtkm::cont::DataSetBuilderExplicitIterative& dsb, ids.push_back(pid); } - void TestTubeFilters() { using VecType = vtkm::Vec3f; @@ -43,6 +42,18 @@ void TestTubeFilters() appendPts(dsb, VecType(2, 1, 0), ids); dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids); + //add some degenerate polylines. + //polyline with 1 point. + ids.clear(); + appendPts(dsb, VecType(0, 0, 0), ids); + dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids); + + //polyline with coincident points. + ids.clear(); + appendPts(dsb, VecType(0, 0, 0), ids); + appendPts(dsb, VecType(0, 0, 0), ids); + dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids); + vtkm::cont::DataSet ds = dsb.Create(); std::vector ptVar, cellVar; @@ -53,7 +64,6 @@ void TestTubeFilters() cellVar.push_back(100); cellVar.push_back(101); - //Polyline 2. ptVar.push_back(10); ptVar.push_back(11); @@ -61,6 +71,16 @@ void TestTubeFilters() cellVar.push_back(110); cellVar.push_back(111); + //Add some degenerate polylines. + //Polyline 3: (only 1 point) + ptVar.push_back(-1); + cellVar.push_back(-1); + //Polyline 4: (2 coincident points) + ptVar.push_back(-1); + ptVar.push_back(-1); + cellVar.push_back(-1); + cellVar.push_back(-1); + ds.AddPointField("pointVar", ptVar); ds.AddCellField("cellVar", cellVar); @@ -93,7 +113,6 @@ void TestTubeFilters() VTKM_TEST_ASSERT(portal.Get(i) == ptVals[static_cast(i)], "Wrong value for point field"); - //Validate the cell field vtkm::cont::ArrayHandle cellArr; output.GetField("cellVar").GetData().AsArrayHandle(cellArr); diff --git a/vtkm/filter/geometry_refinement/worklet/Tube.h b/vtkm/filter/geometry_refinement/worklet/Tube.h index eaa41f3c4..22be15f6e 100644 --- a/vtkm/filter/geometry_refinement/worklet/Tube.h +++ b/vtkm/filter/geometry_refinement/worklet/Tube.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -47,7 +48,8 @@ public: FieldOut ptsPerPolyline, FieldOut ptsPerTube, FieldOut numTubeConnIds, - FieldOut linesPerPolyline); + FieldOut linesPerPolyline, + FieldOut validCell); using ExecutionSignature = void(CellShape shapeType, PointCount numPoints, PointIndices ptIndices, @@ -56,7 +58,8 @@ public: _4 ptsPerPolyline, _5 ptsPerTube, _6 numTubeConnIds, - _7 linesPerPolyline); + _7 linesPerPolyline, + _8 validCell); using InputDomain = _1; template @@ -68,11 +71,14 @@ public: vtkm::Id& ptsPerPolyline, vtkm::Id& ptsPerTube, vtkm::Id& numTubeConnIds, - vtkm::Id& linesPerPolyline) const + vtkm::Id& linesPerPolyline, + vtkm::Id& validCell) const { // We only support polylines that contain 2 or more points. vtkm::IdComponent numNonCoincidentPoints = 1; vtkm::Vec3f p = inPts.Get(ptIndices[0]); + + validCell = 0; for (int i = 1; i < numPoints; ++i) { vtkm::Vec3f pNext = inPts.Get(ptIndices[i]); @@ -80,6 +86,7 @@ public: { numNonCoincidentPoints++; p = pNext; + validCell = 1; } } @@ -101,6 +108,7 @@ public: } else { + validCell = 0; ptsPerPolyline = 0; nonIncidentPtsPerPolyline = 0; ptsPerTube = 0; @@ -138,7 +146,12 @@ public: _3 polylineOffset, _4 outNormals); using InputDomain = _1; - + using ScatterType = vtkm::worklet::ScatterCounting; + VTKM_CONT + static ScatterType MakeScatter(const vtkm::cont::ArrayHandle& validCell) + { + return ScatterType(validCell); + } template VTKM_EXEC vtkm::IdComponent FindValidSegment(const InPointsType& inPts, @@ -151,7 +164,7 @@ public: while (end < numPoints) { auto pe = inPts.Get(ptIndices[end]); - if (vtkm::Magnitude(pe - ps) > 0) + if (vtkm::Magnitude(pe - ps) > vtkm::Epsilon()) return end - 1; end++; } @@ -309,6 +322,12 @@ public: _7 outPts, _8 outPointSrcIdx); using InputDomain = _1; + using ScatterType = vtkm::worklet::ScatterCounting; + VTKM_CONT + static ScatterType MakeScatter(const vtkm::cont::ArrayHandle& validCell) + { + return ScatterType(validCell); + } template ptsPerPolyline, ptsPerTube, numTubeConnIds, segPerPolyline; + vtkm::cont::ArrayHandle ptsPerPolyline, ptsPerTube, numTubeConnIds, segPerPolyline, + validCell; vtkm::cont::ArrayHandle nonIncidentPtsPerPolyline; CountSegments countSegs(this->Capping, this->NumSides); vtkm::worklet::DispatcherMapTopology countInvoker(countSegs); @@ -613,7 +633,8 @@ public: ptsPerPolyline, ptsPerTube, numTubeConnIds, - segPerPolyline); + segPerPolyline, + validCell); vtkm::Id totalPolylinePts = vtkm::cont::Algorithm::Reduce(ptsPerPolyline, vtkm::Id(0)); if (totalPolylinePts == 0) @@ -636,14 +657,16 @@ public: //Generate normals at each point on all polylines NormalsType normals; normals.Allocate(totalPolylinePts); - vtkm::worklet::DispatcherMapTopology genNormalsDisp; + vtkm::worklet::DispatcherMapTopology genNormalsDisp( + GenerateNormals::MakeScatter(validCell)); genNormalsDisp.Invoke(cellset, coords, polylinePtOffset, normals); //Generate the tube points newPoints.Allocate(totalTubePts); this->OutputPointSourceIndex.Allocate(totalTubePts); GeneratePoints genPts(this->Capping, this->NumSides, this->Radius); - vtkm::worklet::DispatcherMapTopology genPtsDisp(genPts); + vtkm::worklet::DispatcherMapTopology genPtsDisp( + genPts, GeneratePoints::MakeScatter(validCell)); genPtsDisp.Invoke(cellset, coords, normals, diff --git a/vtkm/filter/mesh_info/GhostCellClassify.cxx b/vtkm/filter/mesh_info/GhostCellClassify.cxx index 4c930c8c6..366e1a063 100644 --- a/vtkm/filter/mesh_info/GhostCellClassify.cxx +++ b/vtkm/filter/mesh_info/GhostCellClassify.cxx @@ -88,6 +88,7 @@ private: namespace mesh_info { + VTKM_CONT vtkm::cont::DataSet GhostCellClassify::DoExecute(const vtkm::cont::DataSet& input) { const vtkm::cont::UnknownCellSet& cellset = input.GetCellSet(); @@ -142,7 +143,7 @@ VTKM_CONT vtkm::cont::DataSet GhostCellClassify::DoExecute(const vtkm::cont::Dat } auto output = this->CreateResult(input); - output.AddCellField("vtkmGhostCells", ghosts); + output.AddGhostCellField(this->GhostCellName, ghosts); return output; } } diff --git a/vtkm/filter/mesh_info/GhostCellClassify.h b/vtkm/filter/mesh_info/GhostCellClassify.h index c55dffb84..03e1d6952 100644 --- a/vtkm/filter/mesh_info/GhostCellClassify.h +++ b/vtkm/filter/mesh_info/GhostCellClassify.h @@ -22,6 +22,17 @@ namespace mesh_info class VTKM_FILTER_MESH_INFO_EXPORT GhostCellClassify : public vtkm::filter::NewFilter { VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) override; + std::string GhostCellName; + +public: + VTKM_CONT GhostCellClassify() + : NewFilter() + , GhostCellName(vtkm::cont::GetGlobalGhostCellFieldName()) + { + } + + VTKM_CONT void SetGhostCellName(const std::string& fieldName) { this->GhostCellName = fieldName; } + VTKM_CONT const std::string& GetGhostCellName() { return this->GhostCellName; } }; } // namespace mesh_info class VTKM_DEPRECATED(1.8, "Use vtkm::filter::mesh_info::GhostCellClassify.") GhostCellClassify diff --git a/vtkm/filter/mesh_info/testing/UnitTestGhostCellClassify.cxx b/vtkm/filter/mesh_info/testing/UnitTestGhostCellClassify.cxx index 7d76f327e..4390238fe 100644 --- a/vtkm/filter/mesh_info/testing/UnitTestGhostCellClassify.cxx +++ b/vtkm/filter/mesh_info/testing/UnitTestGhostCellClassify.cxx @@ -60,7 +60,7 @@ vtkm::cont::DataSet MakeRectilinear(vtkm::Id numI, vtkm::Id numJ, vtkm::Id numK) return ds; } -void TestStructured() +void TestStructured(std::string GhostFieldName = "") { std::cout << "Testing ghost cells for structured datasets." << std::endl; @@ -99,14 +99,18 @@ void TestStructured() ds = MakeRectilinear(nx, ny, nz); vtkm::filter::mesh_info::GhostCellClassify addGhost; - + if (GhostFieldName != "") + addGhost.SetGhostCellName(GhostFieldName); auto output = addGhost.Execute(ds); //Validate the output. - VTKM_TEST_ASSERT(output.HasCellField("vtkmGhostCells"), + std::string correctFieldName = vtkm::cont::GetGlobalGhostCellFieldName(); + if (GhostFieldName != "") + correctFieldName = GhostFieldName; + VTKM_TEST_ASSERT(output.HasCellField(correctFieldName), "Ghost cells array not found in output"); vtkm::Id numCells = output.GetNumberOfCells(); - auto fieldArray = output.GetCellField("vtkmGhostCells").GetData(); + auto fieldArray = output.GetCellField(addGhost.GetGhostCellName()).GetData(); VTKM_TEST_ASSERT(fieldArray.GetNumberOfValues() == numCells, "Wrong number of values in ghost cell array"); @@ -134,7 +138,7 @@ void TestStructured() void TestGhostCellClassify() { - TestStructured(); + TestStructured("MyGhostFieldName"); } } diff --git a/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.h b/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.h deleted file mode 100644 index 8695b62b9..000000000 --- a/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.h +++ /dev/null @@ -1,560 +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. -//============================================================================ - -#ifndef vtk_m_filter_particleadvection_AdvectorBaseAlgorithm_h -#define vtk_m_filter_particleadvection_AdvectorBaseAlgorithm_h - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -namespace internal -{ - -//Helper class to store the different result types. -template -class ResultHelper; - -//Specialization for ParticleAdvectionResult -using PAType = vtkm::worklet::ParticleAdvectionResult; - -template <> -class ResultHelper -{ -public: - static void Store(std::map>& results, - const PAType& res, - vtkm::Id blockId, - const std::vector& indices) - { - if (indices.empty()) - return; - - //Selected out the terminated particles and store them. - vtkm::cont::ArrayHandle termParticles; - auto indicesAH = vtkm::cont::make_ArrayHandle(indices, vtkm::CopyFlag::Off); - auto perm = vtkm::cont::make_ArrayHandlePermutation(indicesAH, res.Particles); - - vtkm::cont::Algorithm::Copy(perm, termParticles); - PAType termRes(termParticles); - results[blockId].push_back(termRes); - } - - static vtkm::cont::PartitionedDataSet GetOutput( - const std::map>& results) - { - vtkm::cont::PartitionedDataSet output; - for (const auto& it : results) - { - std::size_t nResults = it.second.size(); - if (nResults == 0) - continue; - - std::vector> allParticles; - allParticles.reserve(static_cast(nResults)); - - for (const auto& res : it.second) - allParticles.push_back(res.Particles); - - vtkm::cont::ArrayHandle pts; - vtkm::cont::ParticleArrayCopy(allParticles, pts); - - vtkm::cont::DataSet ds; - vtkm::cont::CoordinateSystem outCoords("coordinates", pts); - ds.AddCoordinateSystem(outCoords); - - //Create vertex cell set - vtkm::Id numPoints = pts.GetNumberOfValues(); - vtkm::cont::CellSetSingleType<> cells; - vtkm::cont::ArrayHandleIndex conn(numPoints); - vtkm::cont::ArrayHandle connectivity; - - vtkm::cont::ArrayCopy(conn, connectivity); - cells.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity); - ds.SetCellSet(cells); - - output.AppendPartition(ds); - } - - return output; - } -}; - -//Specialization for StreamlineResult -using SLType = vtkm::worklet::StreamlineResult; - -template <> -class ResultHelper -{ -public: - static void Store(std::map>& results, - const SLType& res, - vtkm::Id blockId, - const std::vector& vtkmNotUsed(indices)) - { - results[blockId].push_back(res); - } - - static vtkm::cont::PartitionedDataSet GetOutput( - const std::map>& results) - { - vtkm::cont::PartitionedDataSet output; - for (const auto& it : results) - { - std::size_t nResults = it.second.size(); - if (nResults == 0) - continue; - - vtkm::cont::DataSet ds; - //Easy case with one result. - if (nResults == 1) - { - ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", it.second[0].Positions)); - ds.SetCellSet(it.second[0].PolyLines); - } - else - { - //Append all the results into one data set. - vtkm::cont::ArrayHandle appendPts; - std::vector posOffsets(nResults); - - const auto& res0 = it.second[0]; - vtkm::Id totalNumCells = res0.PolyLines.GetNumberOfCells(); - vtkm::Id totalNumPts = res0.Positions.GetNumberOfValues(); - - posOffsets[0] = 0; - for (std::size_t i = 1; i < nResults; i++) - { - const auto& res = it.second[i]; - posOffsets[i] = totalNumPts; - totalNumPts += res.Positions.GetNumberOfValues(); - totalNumCells += res.PolyLines.GetNumberOfCells(); - } - - //Append all the points together. - appendPts.Allocate(totalNumPts); - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = it.second[i]; - // copy all values into appendPts starting at offset. - vtkm::cont::Algorithm::CopySubRange( - res.Positions, 0, res.Positions.GetNumberOfValues(), appendPts, posOffsets[i]); - } - vtkm::cont::CoordinateSystem outputCoords = - vtkm::cont::CoordinateSystem("coordinates", appendPts); - ds.AddCoordinateSystem(outputCoords); - - //Create polylines. - std::vector numPtsPerCell(static_cast(totalNumCells)); - std::size_t off = 0; - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = it.second[i]; - vtkm::Id nCells = res.PolyLines.GetNumberOfCells(); - for (vtkm::Id j = 0; j < nCells; j++) - numPtsPerCell[off++] = static_cast(res.PolyLines.GetNumberOfPointsInCell(j)); - } - - auto numPointsPerCellArray = - vtkm::cont::make_ArrayHandle(numPtsPerCell, vtkm::CopyFlag::Off); - - vtkm::cont::ArrayHandle cellIndex; - vtkm::Id connectivityLen = - vtkm::cont::Algorithm::ScanExclusive(numPointsPerCellArray, cellIndex); - vtkm::cont::ArrayHandleIndex connCount(connectivityLen); - vtkm::cont::ArrayHandle connectivity; - vtkm::cont::ArrayCopy(connCount, connectivity); - - vtkm::cont::ArrayHandle cellTypes; - auto polyLineShape = vtkm::cont::make_ArrayHandleConstant( - vtkm::CELL_SHAPE_POLY_LINE, totalNumCells); - vtkm::cont::ArrayCopy(polyLineShape, cellTypes); - auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPointsPerCellArray); - - vtkm::cont::CellSetExplicit<> polyLines; - polyLines.Fill(totalNumPts, cellTypes, connectivity, offsets); - ds.SetCellSet(polyLines); - } - output.AppendPartition(ds); - } - - return output; - } -}; -}; - -template -vtkm::cont::PartitionedDataSet RunAlgo(const vtkm::filter::particleadvection::BoundsMap& boundsMap, - const std::vector& dsi, - vtkm::Id numSteps, - vtkm::FloatDefault stepSize, - const vtkm::cont::ArrayHandle& seeds) -{ - AlgorithmType algo(boundsMap, dsi); - - algo.SetNumberOfSteps(numSteps); - algo.SetStepSize(stepSize); - algo.SetSeeds(seeds); - algo.Go(); - return algo.GetOutput(); -} - -// -// Base class for particle advector -// -template -class VTKM_ALWAYS_EXPORT AdvectorBaseAlgorithm -{ -public: - AdvectorBaseAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : Blocks(blocks) - , BoundsMap(bm) - , NumberOfSteps(0) - , NumRanks(this->Comm.size()) - , Rank(this->Comm.rank()) - , StepSize(0) - , TotalNumParticles(0) - , TotalNumTerminatedParticles(0) - { - } - - //Initialize ParticleAdvectorBase - void SetStepSize(vtkm::FloatDefault stepSize) { this->StepSize = stepSize; } - void SetNumberOfSteps(vtkm::Id numSteps) { this->NumberOfSteps = numSteps; } - void SetSeeds(const vtkm::cont::ArrayHandle& seeds) - { - this->ClearParticles(); - - vtkm::Id n = seeds.GetNumberOfValues(); - auto portal = seeds.ReadPortal(); - - std::vector> blockIDs; - std::vector particles; - for (vtkm::Id i = 0; i < n; i++) - { - const vtkm::Particle p = portal.Get(i); - std::vector ids = this->BoundsMap.FindBlocks(p.Pos); - if (!ids.empty() && this->BoundsMap.FindRank(ids[0]) == this->Rank) - { - particles.push_back(p); - blockIDs.push_back(ids); - } - } - - this->SetSeedArray(particles, blockIDs); - } - - //Advect all the particles. - virtual void Go() - { - vtkm::filter::particleadvection::ParticleMessenger messenger( - this->Comm, this->BoundsMap, 1, 128); - - vtkm::Id nLocal = static_cast(this->Active.size() + this->Inactive.size()); - this->ComputeTotalNumParticles(nLocal); - this->TotalNumTerminatedParticles = 0; - - while (this->TotalNumTerminatedParticles < this->TotalNumParticles) - { - std::vector v; - vtkm::Id numTerm = 0, blockId = -1; - if (GetActiveParticles(v, blockId)) - { - const auto& block = this->GetDataSet(blockId); - ResultType r; - block.Advect(v, this->StepSize, this->NumberOfSteps, r); - numTerm = this->UpdateResult(r, blockId); - } - - vtkm::Id numTermMessages = 0; - this->Communicate(messenger, numTerm, numTermMessages); - - this->TotalNumTerminatedParticles += (numTerm + numTermMessages); - if (this->TotalNumTerminatedParticles > this->TotalNumParticles) - throw vtkm::cont::ErrorFilterExecution("Particle count error"); - } - } - - vtkm::cont::PartitionedDataSet GetOutput() const - { - return internal::ResultHelper::GetOutput(this->Results); - } - -protected: - virtual void ClearParticles() - { - this->Active.clear(); - this->Inactive.clear(); - this->ParticleBlockIDsMap.clear(); - } - - void ComputeTotalNumParticles(const vtkm::Id& numLocal) - { - long long total = static_cast(numLocal); -#ifdef VTKM_ENABLE_MPI - MPI_Comm mpiComm = vtkmdiy::mpi::mpi_cast(this->Comm.handle()); - MPI_Allreduce(MPI_IN_PLACE, &total, 1, MPI_LONG_LONG, MPI_SUM, mpiComm); -#endif - this->TotalNumParticles = static_cast(total); - } - - const DataSetIntegratorType& GetDataSet(vtkm::Id id) const - { - for (const auto& it : this->Blocks) - if (it.GetID() == id) - return it; - throw vtkm::cont::ErrorFilterExecution("Bad block"); - } - - virtual void SetSeedArray(const std::vector& particles, - const std::vector>& blockIds) - { - VTKM_ASSERT(particles.size() == blockIds.size()); - - auto pit = particles.begin(); - auto bit = blockIds.begin(); - while (pit != particles.end() && bit != blockIds.end()) - { - this->ParticleBlockIDsMap[pit->ID] = *bit; - pit++; - bit++; - } - - this->Active.insert(this->Active.end(), particles.begin(), particles.end()); - } - - virtual bool GetActiveParticles(std::vector& particles, vtkm::Id& blockId) - { - particles.clear(); - blockId = -1; - if (this->Active.empty()) - return false; - - blockId = this->ParticleBlockIDsMap[this->Active.front().ID][0]; - auto it = this->Active.begin(); - while (it != this->Active.end()) - { - auto p = *it; - if (blockId == this->ParticleBlockIDsMap[p.ID][0]) - { - particles.push_back(p); - it = this->Active.erase(it); - } - else - it++; - } - - return !particles.empty(); - } - - virtual void Communicate(vtkm::filter::particleadvection::ParticleMessenger& messenger, - vtkm::Id numLocalTerminations, - vtkm::Id& numTermMessages) - { - std::vector incoming; - std::unordered_map> incomingIDs; - numTermMessages = 0; - messenger.Exchange(this->Inactive, - this->ParticleBlockIDsMap, - numLocalTerminations, - incoming, - incomingIDs, - numTermMessages, - this->GetBlockAndWait(numLocalTerminations)); - - this->Inactive.clear(); - this->UpdateActive(incoming, incomingIDs); - } - - virtual void UpdateActive(const std::vector& particles, - const std::unordered_map>& idsMap) - { - this->Update(this->Active, particles, idsMap); - } - - virtual void UpdateInactive(const std::vector& particles, - const std::unordered_map>& idsMap) - { - this->Update(this->Inactive, particles, idsMap); - } - - void Update(std::vector& arr, - const std::vector& particles, - const std::unordered_map>& idsMap) - { - VTKM_ASSERT(particles.size() == idsMap.size()); - - arr.insert(arr.end(), particles.begin(), particles.end()); - for (const auto& it : idsMap) - this->ParticleBlockIDsMap[it.first] = it.second; - } - - void UpdateTerminated(const vtkm::cont::ArrayHandle& particles, - const std::vector& idxTerm) - { - auto portal = particles.ReadPortal(); - for (const auto& idx : idxTerm) - this->ParticleBlockIDsMap.erase(portal.Get(idx).ID); - } - - void ClassifyParticles(const vtkm::cont::ArrayHandle& particles, - std::unordered_map>& idsMapA, - std::unordered_map>& idsMapI, - std::vector& A, - std::vector& I, - std::vector& termIdx) const - { - A.clear(); - I.clear(); - termIdx.clear(); - idsMapI.clear(); - idsMapA.clear(); - - auto portal = particles.WritePortal(); - vtkm::Id n = portal.GetNumberOfValues(); - - for (vtkm::Id i = 0; i < n; i++) - { - auto p = portal.Get(i); - - if (p.Status.CheckTerminate()) - termIdx.push_back(i); - else - { - const auto& it = this->ParticleBlockIDsMap.find(p.ID); - VTKM_ASSERT(it != this->ParticleBlockIDsMap.end()); - auto currBIDs = it->second; - VTKM_ASSERT(!currBIDs.empty()); - - std::vector newIDs; - if (p.Status.CheckSpatialBounds() && !p.Status.CheckTookAnySteps()) - newIDs.assign(std::next(currBIDs.begin(), 1), currBIDs.end()); - else - newIDs = this->BoundsMap.FindBlocks(p.Pos, currBIDs); - - //reset the particle status. - p.Status = vtkm::ParticleStatus(); - - if (newIDs.empty()) //No blocks, we're done. - { - p.Status.SetTerminate(); - termIdx.push_back(i); - } - else - { - //If we have more than blockId, we want to minimize communication - //and put any blocks owned by this rank first. - if (newIDs.size() > 1) - { - for (auto idit = newIDs.begin(); idit != newIDs.end(); idit++) - { - vtkm::Id bid = *idit; - if (this->BoundsMap.FindRank(bid) == this->Rank) - { - newIDs.erase(idit); - newIDs.insert(newIDs.begin(), bid); - break; - } - } - } - - int dstRank = this->BoundsMap.FindRank(newIDs[0]); - if (dstRank == this->Rank) - { - A.push_back(p); - idsMapA[p.ID] = newIDs; - } - else - { - I.push_back(p); - idsMapI[p.ID] = newIDs; - } - } - portal.Set(i, p); - } - } - - //Make sure we didn't miss anything. Every particle goes into a single bucket. - VTKM_ASSERT(static_cast(n) == (A.size() + I.size() + termIdx.size())); - } - - - vtkm::Id UpdateResult(ResultType& res, vtkm::Id blockId) - { - std::unordered_map> idsMapI, idsMapA; - std::vector A, I; - std::vector termIdx; - this->ClassifyParticles(res.Particles, idsMapA, idsMapI, A, I, termIdx); - - //Update active, inactive and terminated - this->UpdateActive(A, idsMapA); - this->UpdateInactive(I, idsMapI); - - vtkm::Id numTerm = static_cast(termIdx.size()); - if (numTerm > 0) - this->UpdateTerminated(res.Particles, termIdx); - - internal::ResultHelper::Store(this->Results, res, blockId, termIdx); - - return numTerm; - } - - virtual bool GetBlockAndWait(const vtkm::Id& numLocalTerm) - { - //There are only two cases where blocking would deadlock. - //1. There are active particles. - //2. numLocalTerm + this->TotalNumberOfTerminatedParticles == this->TotalNumberOfParticles - //So, if neither are true, we can safely block and wait for communication to come in. - - if (this->Active.empty() && this->Inactive.empty() && - (numLocalTerm + this->TotalNumTerminatedParticles < this->TotalNumParticles)) - { - return true; - } - - return false; - } - - //Member data - std::vector Active; - std::vector Blocks; - vtkm::filter::particleadvection::BoundsMap BoundsMap; - vtkmdiy::mpi::communicator Comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); - std::vector Inactive; - vtkm::Id NumberOfSteps; - vtkm::Id NumRanks; - std::unordered_map> ParticleBlockIDsMap; - vtkm::Id Rank; - std::map> Results; - vtkm::FloatDefault StepSize; - vtkm::Id TotalNumParticles; - vtkm::Id TotalNumTerminatedParticles; -}; - -} -} -} // namespace vtkm::filter::particleadvection - -#endif diff --git a/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.hxx b/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.hxx deleted file mode 100644 index 6baf02f6e..000000000 --- a/vtkm/filter/particleadvection/AdvectorBaseAlgorithm.hxx +++ /dev/null @@ -1,161 +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. -//============================================================================ - -#ifndef vtk_m_filter_particleadvection_AdvectorBaseAlgorithm_hxx -#define vtk_m_filter_particleadvection_AdvectorBaseAlgorithm_hxx - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -using PAResultType = vtkm::worklet::ParticleAdvectionResult; -using SLResultType = vtkm::worklet::StreamlineResult; - -//Result specific implementation. -template <> -inline void AdvectorBaseAlgorithm::StoreResult(const PAResultType& vtkmNotUsed(res), - vtkm::Id vtkmNotUsed(blockId)) -{ -} - -template <> -inline void AdvectorBaseAlgorithm::StoreResult(const SLResultType& res, - vtkm::Id blockId) -{ - this->Results[blockId].push_back(res); -} - -template <> -inline vtkm::cont::PartitionedDataSet AdvectorBaseAlgorithm::GetOutput() -{ - vtkm::cont::PartitionedDataSet output; - - for (const auto& it : this->Terminated) - { - if (it.second.empty()) - continue; - - auto particles = vtkm::cont::make_ArrayHandle(it.second, vtkm::CopyFlag::Off); - vtkm::cont::ArrayHandle pos; - vtkm::cont::ParticleArrayCopy(particles, pos); - - vtkm::cont::DataSet ds; - vtkm::cont::CoordinateSystem outCoords("coordinates", pos); - ds.AddCoordinateSystem(outCoords); - - //Create vertex cell set - vtkm::Id numPoints = pos.GetNumberOfValues(); - vtkm::cont::CellSetSingleType<> cells; - vtkm::cont::ArrayHandleIndex conn(numPoints); - vtkm::cont::ArrayHandle connectivity; - - vtkm::cont::ArrayCopy(conn, connectivity); - cells.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity); - ds.SetCellSet(cells); - - output.AppendPartition(ds); - } - - return output; -} - -template <> -inline vtkm::cont::PartitionedDataSet AdvectorBaseAlgorithm::GetOutput() -{ - vtkm::cont::PartitionedDataSet output; - - for (const auto& it : this->Results) - { - std::size_t nResults = it.second.size(); - if (nResults == 0) - continue; - - vtkm::cont::DataSet ds; - //Easy case with one result. - if (nResults == 1) - { - ds.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", it.second[0].Positions)); - ds.SetCellSet(it.second[0].PolyLines); - } - else - { - //Append all the results into one data set. - vtkm::cont::ArrayHandle appendPts; - std::vector posOffsets(nResults); - - const auto& res0 = it.second[0]; - vtkm::Id totalNumCells = res0.PolyLines.GetNumberOfCells(); - vtkm::Id totalNumPts = res0.Positions.GetNumberOfValues(); - - posOffsets[0] = 0; - for (std::size_t i = 1; i < nResults; i++) - { - const auto& res = it.second[i]; - posOffsets[i] = totalNumPts; - totalNumPts += res.Positions.GetNumberOfValues(); - totalNumCells += res.PolyLines.GetNumberOfCells(); - } - - //Append all the points together. - appendPts.Allocate(totalNumPts); - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = it.second[i]; - // copy all values into appendPts starting at offset. - vtkm::cont::Algorithm::CopySubRange( - res.Positions, 0, res.Positions.GetNumberOfValues(), appendPts, posOffsets[i]); - } - vtkm::cont::CoordinateSystem outputCoords = - vtkm::cont::CoordinateSystem("coordinates", appendPts); - ds.AddCoordinateSystem(outputCoords); - - //Create polylines. - std::vector numPtsPerCell(static_cast(totalNumCells)); - std::size_t off = 0; - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = it.second[i]; - vtkm::Id nCells = res.PolyLines.GetNumberOfCells(); - for (vtkm::Id j = 0; j < nCells; j++) - numPtsPerCell[off++] = static_cast(res.PolyLines.GetNumberOfPointsInCell(j)); - } - - auto numPointsPerCellArray = vtkm::cont::make_ArrayHandle(numPtsPerCell, vtkm::CopyFlag::Off); - - vtkm::cont::ArrayHandle cellIndex; - vtkm::Id connectivityLen = - vtkm::cont::Algorithm::ScanExclusive(numPointsPerCellArray, cellIndex); - vtkm::cont::ArrayHandleIndex connCount(connectivityLen); - vtkm::cont::ArrayHandle connectivity; - vtkm::cont::ArrayCopy(connCount, connectivity); - - vtkm::cont::ArrayHandle cellTypes; - auto polyLineShape = vtkm::cont::make_ArrayHandleConstant( - vtkm::CELL_SHAPE_POLY_LINE, totalNumCells); - vtkm::cont::ArrayCopy(polyLineShape, cellTypes); - auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numPointsPerCellArray); - - vtkm::cont::CellSetExplicit<> polyLines; - polyLines.Fill(totalNumPts, cellTypes, connectivity, offsets); - ds.SetCellSet(polyLines); - } - output.AppendPartition(ds); - } - return output; -} - -} -} -} // namespace vtkm::filter::particleadvection - -#endif //vtk_m_filter_particleadvection_AdvectorBaseAlgorithm_hxx diff --git a/vtkm/filter/particleadvection/DataSetIntegrator.h b/vtkm/filter/particleadvection/DataSetIntegrator.h deleted file mode 100644 index 793c7ed9c..000000000 --- a/vtkm/filter/particleadvection/DataSetIntegrator.h +++ /dev/null @@ -1,141 +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. -//============================================================================ - -#ifndef vtk_m_filter_DataSetIntegrator_h -#define vtk_m_filter_DataSetIntegrator_h - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -template -class VTKM_ALWAYS_EXPORT DataSetIntegratorBase -{ -public: - DataSetIntegratorBase(bool copySeeds = false, vtkm::Id id = -1) - : CopySeedArray(copySeeds) - , Eval(nullptr) - , ID(id) - { - } - - ~DataSetIntegratorBase() = default; - - vtkm::Id GetID() const { return this->ID; } - void SetCopySeedFlag(bool val) { this->CopySeedArray = val; } - - template - void Advect(std::vector& v, - vtkm::FloatDefault stepSize, - vtkm::Id maxSteps, - ResultType& result) const - { - auto copyFlag = (this->CopySeedArray ? vtkm::CopyFlag::On : vtkm::CopyFlag::Off); - auto seedArray = vtkm::cont::make_ArrayHandle(v, copyFlag); - Stepper rk4(*this->Eval, stepSize); - this->DoAdvect(seedArray, rk4, maxSteps, result); - } - -protected: - using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; - using Stepper = vtkm::worklet::particleadvection::Stepper; - using FieldHandleType = vtkm::cont::ArrayHandle; - - template - inline void DoAdvect(vtkm::cont::ArrayHandle& seeds, - const Stepper& rk4, - vtkm::Id maxSteps, - ResultType& result) const; - - FieldHandleType GetFieldHandle(const vtkm::cont::DataSet& ds, const std::string& fieldNm) - { - if (!ds.HasField(fieldNm)) - throw vtkm::cont::ErrorFilterExecution("Field " + fieldNm + " not found on dataset."); - - FieldHandleType fieldArray; - auto fieldData = ds.GetField(fieldNm).GetData(); - vtkm::cont::ArrayCopyShallowIfPossible(fieldData, fieldArray); - - return fieldArray; - } - - bool CopySeedArray; - std::shared_ptr Eval; - vtkm::Id ID; -}; - -class VTKM_ALWAYS_EXPORT DataSetIntegrator - : public DataSetIntegratorBase>>> -{ -public: - DataSetIntegrator(const vtkm::cont::DataSet& ds, vtkm::Id id, const std::string& fieldNm) - : DataSetIntegratorBase>>(false, id) - { - using Association = vtkm::cont::Field::Association; - using FieldType = vtkm::worklet::particleadvection::VelocityField; - using EvalType = vtkm::worklet::particleadvection::GridEvaluator; - Association association = ds.GetField(fieldNm).GetAssociation(); - auto fieldArray = this->GetFieldHandle(ds, fieldNm); - FieldType field(fieldArray, association); - this->Eval = std::shared_ptr(new EvalType(ds, field)); - } -}; - -class VTKM_ALWAYS_EXPORT TemporalDataSetIntegrator - : public DataSetIntegratorBase>>> -{ - using FieldHandleType = vtkm::cont::ArrayHandle; - -public: - TemporalDataSetIntegrator(const vtkm::cont::DataSet& ds1, - vtkm::FloatDefault t1, - const vtkm::cont::DataSet& ds2, - vtkm::FloatDefault t2, - vtkm::Id id, - const std::string& fieldNm) - : DataSetIntegratorBase>>(false, id) - { - auto fieldArray1 = this->GetFieldHandle(ds1, fieldNm); - auto fieldArray2 = this->GetFieldHandle(ds2, fieldNm); - - using EvalType = vtkm::worklet::particleadvection::TemporalGridEvaluator< - vtkm::worklet::particleadvection::VelocityField>; - - this->Eval = - std::shared_ptr(new EvalType(ds1, t1, fieldArray1, ds2, t2, fieldArray2)); - } -}; - -} -} -} // namespace vtkm::filter::particleadvection - -#ifndef vtk_m_filter_particleadvection_DataSetIntegrator_hxx -#include -#endif - -#endif //vtk_m_filter_DataSetIntegrator_h diff --git a/vtkm/filter/particleadvection/DataSetIntegrator.hxx b/vtkm/filter/particleadvection/DataSetIntegrator.hxx deleted file mode 100644 index da3893277..000000000 --- a/vtkm/filter/particleadvection/DataSetIntegrator.hxx +++ /dev/null @@ -1,91 +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. -//============================================================================ - -#ifndef vtk_m_filter_DataSetIntegrator_hxx -#define vtk_m_filter_DataSetIntegrator_hxx - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -using GridEvalType = vtkm::worklet::particleadvection::GridEvaluator< - vtkm::worklet::particleadvection::VelocityField>>; -using TemporalGridEvalType = vtkm::worklet::particleadvection::TemporalGridEvaluator< - vtkm::worklet::particleadvection::VelocityField>>; -using RK4Type = vtkm::worklet::particleadvection::RK4Integrator; -using Stepper = vtkm::worklet::particleadvection::Stepper; -using TemporalRK4Type = vtkm::worklet::particleadvection::RK4Integrator; -using TemporalStepper = - vtkm::worklet::particleadvection::Stepper; - -//----- -// Specialization for ParticleAdvection worklet -template <> -template <> -inline void DataSetIntegratorBase::DoAdvect( - vtkm::cont::ArrayHandle& seeds, - const Stepper& stepper, - vtkm::Id maxSteps, - vtkm::worklet::ParticleAdvectionResult& result) const -{ - vtkm::worklet::ParticleAdvection Worklet; - result = Worklet.Run(stepper, seeds, maxSteps); -} - -//----- -// Specialization for Streamline worklet -template <> -template <> -inline void DataSetIntegratorBase::DoAdvect( - vtkm::cont::ArrayHandle& seeds, - const Stepper& stepper, - vtkm::Id maxSteps, - vtkm::worklet::StreamlineResult& result) const -{ - vtkm::worklet::Streamline Worklet; - result = Worklet.Run(stepper, seeds, maxSteps); -} - -//----- -// Specialization for PathParticle worklet -template <> -template <> -inline void DataSetIntegratorBase::DoAdvect( - vtkm::cont::ArrayHandle& seeds, - const TemporalStepper& stepper, - vtkm::Id maxSteps, - vtkm::worklet::ParticleAdvectionResult& result) const -{ - vtkm::worklet::ParticleAdvection Worklet; - result = Worklet.Run(stepper, seeds, maxSteps); -} - -//----- -// Specialization for Pathline worklet -template <> -template <> -inline void DataSetIntegratorBase::DoAdvect( - vtkm::cont::ArrayHandle& seeds, - const TemporalStepper& stepper, - vtkm::Id maxSteps, - vtkm::worklet::StreamlineResult& result) const -{ - vtkm::worklet::Streamline Worklet; - result = Worklet.Run(stepper, seeds, maxSteps); -} - -} -} -} // namespace vtkm::filter::particleadvection - -#endif diff --git a/vtkm/filter/particleadvection/ParticleAdvectionAlgorithm.h b/vtkm/filter/particleadvection/ParticleAdvectionAlgorithm.h deleted file mode 100644 index d75cb9237..000000000 --- a/vtkm/filter/particleadvection/ParticleAdvectionAlgorithm.h +++ /dev/null @@ -1,151 +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. -//============================================================================ - -#ifndef vtk_m_filter_particleadvection_ParticleAdvectionAlgorithm_h -#define vtk_m_filter_particleadvection_ParticleAdvectionAlgorithm_h - -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -using DSIType = vtkm::filter::particleadvection::DataSetIntegrator; -using TDSIType = vtkm::filter::particleadvection::TemporalDataSetIntegrator; - -//------------------------------------------------------------------------------------------- -//Steady state advection algorithms - -//Particle advection -class VTKM_ALWAYS_EXPORT ParticleAdvectionAlgorithm - : public AdvectorBaseAlgorithm> -{ -public: - ParticleAdvectionAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseAlgorithm>(bm, - blocks) - { - } -}; - -//Threaded particle advection -class VTKM_ALWAYS_EXPORT ParticleAdvectionThreadedAlgorithm - : public AdvectorBaseThreadedAlgorithm> -{ -public: - ParticleAdvectionThreadedAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseThreadedAlgorithm>(bm, - blocks) - { - } -}; - -//Streamline -class VTKM_ALWAYS_EXPORT StreamlineAlgorithm - : public AdvectorBaseAlgorithm> -{ -public: - StreamlineAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseAlgorithm>(bm, blocks) - { - } -}; - -//Threaded streamline - -class VTKM_ALWAYS_EXPORT StreamlineThreadedAlgorithm - : public AdvectorBaseThreadedAlgorithm> -{ -public: - StreamlineThreadedAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseThreadedAlgorithm>( - bm, - blocks) - { - } -}; - -//------------------------------------------------------------------------------------------- -//Unsteady state advection algorithms - -//PathParticle -class VTKM_ALWAYS_EXPORT PathParticleAlgorithm - : public AdvectorBaseAlgorithm> -{ -public: - PathParticleAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseAlgorithm>( - bm, - blocks) - { - } -}; - - -//Threaded PathParticle -class VTKM_ALWAYS_EXPORT PathParticleThreadedAlgorithm - : public AdvectorBaseThreadedAlgorithm> -{ -public: - PathParticleThreadedAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseThreadedAlgorithm>(bm, - blocks) - { - } -}; - -//Pathline -class VTKM_ALWAYS_EXPORT PathlineAlgorithm - : public AdvectorBaseAlgorithm> -{ -public: - PathlineAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseAlgorithm>(bm, blocks) - { - } -}; - -//Threaded pathline -class VTKM_ALWAYS_EXPORT PathlineThreadedAlgorithm - : public AdvectorBaseThreadedAlgorithm> -{ -public: - PathlineThreadedAlgorithm(const vtkm::filter::particleadvection::BoundsMap& bm, - const std::vector& blocks) - : AdvectorBaseThreadedAlgorithm>( - bm, - blocks) - { - } -}; - - - -} -} -} // namespace vtkm::filter::particleadvection - -#endif //vtk_m_filter_particleadvection_ParticleAdvectionAlgorithm_h diff --git a/vtkm/filter/particleadvection/ParticleMessenger.cxx b/vtkm/filter/particleadvection/ParticleMessenger.cxx deleted file mode 100644 index b65f6460b..000000000 --- a/vtkm/filter/particleadvection/ParticleMessenger.cxx +++ /dev/null @@ -1,241 +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 - -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -VTKM_CONT -ParticleMessenger::ParticleMessenger(vtkmdiy::mpi::communicator& comm, - const vtkm::filter::particleadvection::BoundsMap& boundsMap, - int msgSz, - int numParticles, - int numBlockIds) - : Messenger(comm) -#ifdef VTKM_ENABLE_MPI - , BoundsMap(boundsMap) -#endif -{ -#ifdef VTKM_ENABLE_MPI - this->RegisterMessages(msgSz, numParticles, numBlockIds); -#else - (void)(boundsMap); - (void)(msgSz); - (void)(numParticles); - (void)(numBlockIds); -#endif -} - -std::size_t ParticleMessenger::CalcParticleBufferSize(std::size_t nParticles, std::size_t nBlockIds) -{ - constexpr std::size_t pSize = sizeof(vtkm::Vec3f) // Pos - + sizeof(vtkm::Id) // ID - + sizeof(vtkm::Id) // NumSteps - + sizeof(vtkm::UInt8) // Status - + sizeof(vtkm::FloatDefault); // Time - -#ifndef NDEBUG - vtkmdiy::MemoryBuffer buff; - vtkm::Particle p; - vtkmdiy::save(buff, p); - - //If this assert fires, vtkm::Particle changed - //and pSize should be updated. - VTKM_ASSERT(pSize == buff.size()); -#endif - - return - // rank - sizeof(int) - //std::vector p; - //p.size() - + sizeof(std::size_t) - //nParticles of vtkm::Particle - + nParticles * pSize - // std::vector blockIDs for each particle. - // blockIDs.size() for each particle - + nParticles * sizeof(std::size_t) - // nBlockIDs of vtkm::Id for each particle. - + nParticles * nBlockIds * sizeof(vtkm::Id); -} - -VTKM_CONT -void ParticleMessenger::SerialExchange( - const std::vector& outData, - const std::unordered_map>& outBlockIDsMap, - vtkm::Id vtkmNotUsed(numLocalTerm), - std::vector& inData, - std::unordered_map>& inDataBlockIDsMap, - bool vtkmNotUsed(blockAndWait)) const -{ - for (auto& p : outData) - { - const auto& bids = outBlockIDsMap.find(p.ID)->second; - inData.push_back(p); - inDataBlockIDsMap[p.ID] = bids; - } -} - -VTKM_CONT -void ParticleMessenger::Exchange( - const std::vector& outData, - const std::unordered_map>& outBlockIDsMap, - vtkm::Id numLocalTerm, - std::vector& inData, - std::unordered_map>& inDataBlockIDsMap, - vtkm::Id& numTerminateMessages, - bool blockAndWait) -{ - numTerminateMessages = 0; - inDataBlockIDsMap.clear(); - - if (this->GetNumRanks() == 1) - return this->SerialExchange( - outData, outBlockIDsMap, numLocalTerm, inData, inDataBlockIDsMap, blockAndWait); - -#ifdef VTKM_ENABLE_MPI - - //dstRank, vector of (particles,blockIDs) - std::unordered_map> sendData; - - for (const auto& p : outData) - { - const auto& bids = outBlockIDsMap.find(p.ID)->second; - int dstRank = this->BoundsMap.FindRank(bids[0]); - sendData[dstRank].push_back(std::make_pair(p, bids)); - } - - //Do all the sends first. - if (numLocalTerm > 0) - this->SendAllMsg({ MSG_TERMINATE, static_cast(numLocalTerm) }); - this->SendParticles(sendData); - this->CheckPendingSendRequests(); - - //Check if we have anything coming in. - std::vector particleData; - std::vector msgData; - if (RecvAny(&msgData, &particleData, blockAndWait)) - { - for (const auto& it : particleData) - for (const auto& v : it.second) - { - const auto& p = v.first; - const auto& bids = v.second; - inData.push_back(p); - inDataBlockIDsMap[p.ID] = bids; - } - - for (const auto& m : msgData) - { - if (m.second[0] == MSG_TERMINATE) - numTerminateMessages += static_cast(m.second[1]); - } - } -#endif -} - -#ifdef VTKM_ENABLE_MPI - -VTKM_CONT -void ParticleMessenger::RegisterMessages(int msgSz, int nParticles, int numBlockIds) -{ - //Determine buffer size for msg and particle tags. - std::size_t messageBuffSz = CalcMessageBufferSize(msgSz + 1); - std::size_t particleBuffSz = CalcParticleBufferSize(nParticles, numBlockIds); - - int numRecvs = std::min(64, this->GetNumRanks() - 1); - - this->RegisterTag(ParticleMessenger::MESSAGE_TAG, numRecvs, messageBuffSz); - this->RegisterTag(ParticleMessenger::PARTICLE_TAG, numRecvs, particleBuffSz); - - this->InitializeBuffers(); -} - -VTKM_CONT -void ParticleMessenger::SendMsg(int dst, const std::vector& msg) -{ - vtkmdiy::MemoryBuffer buff; - - //Write data. - vtkmdiy::save(buff, this->GetRank()); - vtkmdiy::save(buff, msg); - this->SendData(dst, ParticleMessenger::MESSAGE_TAG, buff); -} - -VTKM_CONT -void ParticleMessenger::SendAllMsg(const std::vector& msg) -{ - for (int i = 0; i < this->GetNumRanks(); i++) - if (i != this->GetRank()) - this->SendMsg(i, msg); -} - -VTKM_CONT -bool ParticleMessenger::RecvAny(std::vector* msgs, - std::vector* recvParticles, - bool blockAndWait) -{ - std::set tags; - if (msgs) - { - tags.insert(ParticleMessenger::MESSAGE_TAG); - msgs->resize(0); - } - if (recvParticles) - { - tags.insert(ParticleMessenger::PARTICLE_TAG); - recvParticles->resize(0); - } - - if (tags.empty()) - return false; - - std::vector> buffers; - if (!this->RecvData(tags, buffers, blockAndWait)) - return false; - - for (auto& buff : buffers) - { - if (buff.first == ParticleMessenger::MESSAGE_TAG) - { - int sendRank; - std::vector m; - vtkmdiy::load(buff.second, sendRank); - vtkmdiy::load(buff.second, m); - msgs->push_back(std::make_pair(sendRank, m)); - } - else if (buff.first == ParticleMessenger::PARTICLE_TAG) - { - int sendRank; - std::vector particles; - - vtkmdiy::load(buff.second, sendRank); - vtkmdiy::load(buff.second, particles); - recvParticles->push_back(std::make_pair(sendRank, particles)); - } - } - - return true; -} - -#endif -} -} -} // vtkm::filter::particleadvection diff --git a/vtkm/filter/particleadvection/ParticleMessenger.h b/vtkm/filter/particleadvection/ParticleMessenger.h deleted file mode 100644 index 87435804a..000000000 --- a/vtkm/filter/particleadvection/ParticleMessenger.h +++ /dev/null @@ -1,146 +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. -//============================================================================ - -#ifndef vtk_m_filter_ParticleMessenger_h -#define vtk_m_filter_ParticleMessenger_h - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace vtkm -{ -namespace filter -{ -namespace particleadvection -{ - -class VTKM_FILTER_EXTRA_EXPORT ParticleMessenger : public vtkm::filter::particleadvection::Messenger -{ - //sendRank, message - using MsgCommType = std::pair>; - - //particle + blockIDs. - using ParticleCommType = std::pair>; - - //sendRank, vector of ParticleCommType. - using ParticleRecvCommType = std::pair>; - -public: - VTKM_CONT ParticleMessenger(vtkmdiy::mpi::communicator& comm, - const vtkm::filter::particleadvection::BoundsMap& bm, - int msgSz = 1, - int numParticles = 128, - int numBlockIds = 2); - VTKM_CONT ~ParticleMessenger() {} - - VTKM_CONT void Exchange(const std::vector& outData, - const std::unordered_map>& outBlockIDsMap, - vtkm::Id numLocalTerm, - std::vector& inData, - std::unordered_map>& inDataBlockIDsMap, - vtkm::Id& numTerminateMessages, - bool blockAndWait = false); - -protected: -#ifdef VTKM_ENABLE_MPI - static constexpr int MSG_TERMINATE = 1; - - enum - { - MESSAGE_TAG = 0x42000, - PARTICLE_TAG = 0x42001 - }; - - VTKM_CONT void RegisterMessages(int msgSz, int nParticles, int numBlockIds); - - // Send/Recv particles - VTKM_CONT - template - class Container, - typename Allocator = std::allocator

> - inline void SendParticles(int dst, const Container& c); - - VTKM_CONT - template - class Container, - typename Allocator = std::allocator

> - inline void SendParticles(const std::unordered_map>& m); - - // Send/Recv messages. - VTKM_CONT void SendMsg(int dst, const std::vector& msg); - VTKM_CONT void SendAllMsg(const std::vector& msg); - VTKM_CONT bool RecvMsg(std::vector& msgs) { return RecvAny(&msgs, NULL, false); } - - // Send/Recv datasets. - VTKM_CONT bool RecvAny(std::vector* msgs, - std::vector* recvParticles, - bool blockAndWait); - const vtkm::filter::particleadvection::BoundsMap& BoundsMap; - -#endif - - VTKM_CONT void SerialExchange( - const std::vector& outData, - const std::unordered_map>& outBlockIDsMap, - vtkm::Id numLocalTerm, - std::vector& inData, - std::unordered_map>& inDataBlockIDsMap, - bool blockAndWait) const; - - static std::size_t CalcParticleBufferSize(std::size_t nParticles, std::size_t numBlockIds = 2); -}; - - -#ifdef VTKM_ENABLE_MPI -VTKM_CONT -template class Container, typename Allocator> -inline void ParticleMessenger::SendParticles(int dst, const Container& c) -{ - if (dst == this->GetRank()) - { - VTKM_LOG_S(vtkm::cont::LogLevel::Error, "Error. Sending a particle to yourself."); - return; - } - if (c.empty()) - return; - - vtkmdiy::MemoryBuffer bb; - vtkmdiy::save(bb, this->GetRank()); - vtkmdiy::save(bb, c); - this->SendData(dst, ParticleMessenger::PARTICLE_TAG, bb); -} - -VTKM_CONT -template class Container, typename Allocator> -inline void ParticleMessenger::SendParticles( - const std::unordered_map>& m) -{ - for (const auto& mit : m) - if (!mit.second.empty()) - this->SendParticles(mit.first, mit.second); -} -#endif -} -} -} // namespace vtkm::filter::particleadvection - - -#endif diff --git a/vtkm/filter/resampling/Probe.cxx b/vtkm/filter/resampling/Probe.cxx index c492d5088..7ede251c4 100644 --- a/vtkm/filter/resampling/Probe.cxx +++ b/vtkm/filter/resampling/Probe.cxx @@ -19,34 +19,21 @@ namespace filter { namespace resampling { -vtkm::cont::DataSet Probe::DoExecute(const vtkm::cont::DataSet& input) + +namespace { - vtkm::worklet::Probe worklet; - worklet.Run(input.GetCellSet(), - input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()), - this->Geometry.GetCoordinateSystem().GetData()); - auto mapper = [&](auto& outDataSet, const auto& f) { this->DoMapField(outDataSet, f, worklet); }; - auto output = this->CreateResult( - input, this->Geometry.GetCellSet(), this->Geometry.GetCoordinateSystems(), mapper); - output.AddField(vtkm::cont::make_FieldPoint("HIDDEN", worklet.GetHiddenPointsField())); - output.AddField( - vtkm::cont::make_FieldCell("HIDDEN", worklet.GetHiddenCellsField(output.GetCellSet()))); - - return output; -} - - -bool Probe::DoMapField(vtkm::cont::DataSet& result, - const vtkm::cont::Field& field, - const vtkm::worklet::Probe& worklet) +bool DoMapField(vtkm::cont::DataSet& result, + const vtkm::cont::Field& field, + const vtkm::worklet::Probe& worklet, + vtkm::Float64 invalidValue) { if (field.IsFieldPoint()) { auto resolve = [&](const auto& concrete) { using T = typename std::decay_t::ValueType; vtkm::cont::ArrayHandle outputArray = worklet.ProcessPointField( - concrete, vtkm::cont::internal::CastInvalidValue(this->InvalidValue)); + concrete, vtkm::cont::internal::CastInvalidValue(invalidValue)); result.AddPointField(field.GetName(), outputArray); }; field.GetData() @@ -57,8 +44,7 @@ bool Probe::DoMapField(vtkm::cont::DataSet& result, else if (field.IsFieldCell()) { vtkm::cont::Field outField; - if (vtkm::filter::MapFieldPermutation( - field, worklet.GetCellIds(), outField, this->InvalidValue)) + if (vtkm::filter::MapFieldPermutation(field, worklet.GetCellIds(), outField, invalidValue)) { // output field should be associated with points outField = vtkm::cont::Field( @@ -78,6 +64,27 @@ bool Probe::DoMapField(vtkm::cont::DataSet& result, return false; } } +} // anonymous namespace + +vtkm::cont::DataSet Probe::DoExecute(const vtkm::cont::DataSet& input) +{ + vtkm::worklet::Probe worklet; + worklet.Run(input.GetCellSet(), + input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()), + this->Geometry.GetCoordinateSystem().GetData()); + + auto mapper = [&](auto& outDataSet, const auto& f) { + DoMapField(outDataSet, f, worklet, this->InvalidValue); + }; + auto output = this->CreateResult( + input, this->Geometry.GetCellSet(), this->Geometry.GetCoordinateSystems(), mapper); + output.AddField(vtkm::cont::make_FieldPoint("HIDDEN", worklet.GetHiddenPointsField())); + output.AddField( + vtkm::cont::make_FieldCell("HIDDEN", worklet.GetHiddenCellsField(output.GetCellSet()))); + + return output; +} + } // namespace resampling } // namespace filter } // namespace vtkm diff --git a/vtkm/filter/resampling/Probe.h b/vtkm/filter/resampling/Probe.h index eb283c25c..2b896a260 100644 --- a/vtkm/filter/resampling/Probe.h +++ b/vtkm/filter/resampling/Probe.h @@ -15,11 +15,6 @@ namespace vtkm { -namespace worklet -{ -class Probe; -} - namespace filter { namespace resampling @@ -43,10 +38,6 @@ public: private: VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override; - bool DoMapField(vtkm::cont::DataSet& result, - const vtkm::cont::Field& field, - const vtkm::worklet::Probe& worklet); - vtkm::cont::DataSet Geometry; vtkm::Float64 InvalidValue = vtkm::Nan64(); diff --git a/vtkm/filter/scalar_topology/CMakeLists.txt b/vtkm/filter/scalar_topology/CMakeLists.txt index 44cee269d..01a938d26 100644 --- a/vtkm/filter/scalar_topology/CMakeLists.txt +++ b/vtkm/filter/scalar_topology/CMakeLists.txt @@ -16,6 +16,7 @@ set(scalar_topology_headers set(scalar_topology_sources internal/BranchDecompositionBlock.cxx + internal/ComputeBlockIndices.cxx internal/ComputeDistributedBranchDecompositionFunctor.cxx ContourTreeUniform.cxx ContourTreeUniformAugmented.cxx diff --git a/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.cxx b/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.cxx index 720bfa9d2..6bf2b7268 100644 --- a/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.cxx +++ b/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.cxx @@ -51,6 +51,7 @@ //============================================================================== #include +#include #include #include @@ -83,12 +84,9 @@ ContourTreeAugmented::ContourTreeAugmented(bool useMarchingCubes, this->SetOutputFieldName("resultData"); } -void ContourTreeAugmented::SetSpatialDecomposition( +void ContourTreeAugmented::SetBlockIndices( vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes) + const vtkm::cont::ArrayHandle& localBlockIndices) { if (this->MultiBlockTreeHelper) { @@ -96,7 +94,7 @@ void ContourTreeAugmented::SetSpatialDecomposition( } this->MultiBlockTreeHelper = std::make_unique( - blocksPerDim, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes); + blocksPerDim, localBlockIndices); } const vtkm::worklet::contourtree_augmented::ContourTree& ContourTreeAugmented::GetContourTree() @@ -234,7 +232,7 @@ VTKM_CONT void ContourTreeAugmented::PreExecute(const vtkm::cont::PartitionedDat { if (this->MultiBlockTreeHelper) { - if (this->MultiBlockTreeHelper->GetGlobalNumberOfBlocks(input) != + if (input.GetGlobalNumberOfPartitions() != this->MultiBlockTreeHelper->GetGlobalNumberOfBlocks()) { throw vtkm::cont::ErrorFilterExecution( @@ -246,6 +244,12 @@ VTKM_CONT void ContourTreeAugmented::PreExecute(const vtkm::cont::PartitionedDat "Global number of block in MultiBlock dataset does not match the SpatialDecomposition"); } } + else + { + // No block indices set -> compute information automatically later + this->MultiBlockTreeHelper = + std::make_unique(input); + } } //----------------------------------------------------------------------------- @@ -268,10 +272,6 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned unsigned int compRegularStruct = (this->ComputeRegularStructure > 0) ? this->ComputeRegularStructure : 2; - auto localBlocksOriginPortal = - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal(); - auto localBlocksSizesPortal = - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal(); for (std::size_t bi = 0; bi < static_cast(input.GetNumberOfPartitions()); bi++) { // create the local contour tree mesh @@ -279,20 +279,25 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned auto currBlock = input.GetPartition(static_cast(bi)); auto currField = currBlock.GetField(this->GetActiveFieldName(), this->GetActiveFieldAssociation()); + + vtkm::Id3 pointDimensions, globalPointDimensions, globalPointIndexStart; + currBlock.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + pointDimensions, + globalPointDimensions, + globalPointIndexStart); + //const vtkm::cont::ArrayHandle &fieldData = currField.GetData().Cast >(); vtkm::cont::ArrayHandle fieldData; vtkm::cont::ArrayCopy(currField.GetData(), fieldData); auto currContourTreeMesh = vtkm::worklet::contourtree_distributed::MultiBlockContourTreeHelper:: - ComputeLocalContourTreeMesh( - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal() - .Get(static_cast(bi)), - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get( - static_cast(bi)), - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.GlobalSize, - fieldData, - MultiBlockTreeHelper->LocalContourTrees[bi], - MultiBlockTreeHelper->LocalSortOrders[bi], - compRegularStruct); + ComputeLocalContourTreeMesh(globalPointIndexStart, + pointDimensions, + globalPointDimensions, + fieldData, + MultiBlockTreeHelper->LocalContourTrees[bi], + MultiBlockTreeHelper->LocalSortOrders[bi], + compRegularStruct); localContourTreeMeshes[bi] = currContourTreeMesh; // create the local data block structure localDataBlocks[bi] = new vtkm::worklet::contourtree_distributed::ContourTreeBlockData(); @@ -303,10 +308,9 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned localDataBlocks[bi]->NeighborConnectivity = currContourTreeMesh->NeighborConnectivity; localDataBlocks[bi]->NeighborOffsets = currContourTreeMesh->NeighborOffsets; localDataBlocks[bi]->MaxNeighbors = currContourTreeMesh->MaxNeighbors; - localDataBlocks[bi]->BlockOrigin = localBlocksOriginPortal.Get(static_cast(bi)); - localDataBlocks[bi]->BlockSize = localBlocksSizesPortal.Get(static_cast(bi)); - localDataBlocks[bi]->GlobalSize = - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.GlobalSize; + localDataBlocks[bi]->BlockOrigin = globalPointIndexStart; + localDataBlocks[bi]->BlockSize = pointDimensions; + localDataBlocks[bi]->GlobalSize = globalPointDimensions; // We need to augment at least with the boundary vertices when running in parallel localDataBlocks[bi]->ComputeRegularStructure = compRegularStruct; } @@ -320,33 +324,32 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned // Compute the gids for our local blocks using RegularDecomposer = vtkmdiy::RegularDecomposer; - const vtkm::filter::scalar_topology::internal::SpatialDecomposition& spatialDecomp = - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition; - const auto numDims = spatialDecomp.NumberOfDimensions(); - // ... division vector - RegularDecomposer::DivisionsVector diyDivisions(numDims); - for (vtkm::IdComponent d = 0; - d < static_cast(spatialDecomp.NumberOfDimensions()); - ++d) + RegularDecomposer::DivisionsVector diyDivisions; + std::vector vtkmdiyLocalBlockGids; + vtkmdiy::DiscreteBounds diyBounds(0); + if (this->MultiBlockTreeHelper->BlocksPerDimension[0] == -1) { - diyDivisions[d] = static_cast(spatialDecomp.BlocksPerDimension[d]); + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "BlocksPerDimension not set. Computing block indices " + "from information in CellSetStructured."); + diyBounds = vtkm::filter::scalar_topology::internal::ComputeBlockIndices( + input, diyDivisions, vtkmdiyLocalBlockGids); } - - // ... coordinates of local blocks - auto localBlockIndicesPortal = spatialDecomp.LocalBlockIndices.ReadPortal(); - std::vector vtkmdiyLocalBlockGids(static_cast(input.GetNumberOfPartitions())); - for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) + else { - RegularDecomposer::DivisionsVector diyCoords(static_cast(numDims)); - auto currentCoords = localBlockIndicesPortal.Get(bi); - for (vtkm::IdComponent d = 0; d < numDims; ++d) - { - diyCoords[d] = static_cast(currentCoords[d]); - } - vtkmdiyLocalBlockGids[static_cast(bi)] = - RegularDecomposer::coords_to_gid(diyCoords, diyDivisions); + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "BlocksPerDimension set. Using information provided by caller."); + diyBounds = vtkm::filter::scalar_topology::internal::ComputeBlockIndices( + input, + this->MultiBlockTreeHelper->BlocksPerDimension, + this->MultiBlockTreeHelper->LocalBlockIndices, + diyDivisions, + vtkmdiyLocalBlockGids); } + int numDims = diyBounds.min.dimension(); + int globalNumberOfBlocks = + std::accumulate(diyDivisions.cbegin(), diyDivisions.cend(), 1, std::multiplies{}); // Add my local blocks to the vtkmdiy master. for (std::size_t bi = 0; bi < static_cast(input.GetNumberOfPartitions()); bi++) @@ -361,16 +364,15 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned RegularDecomposer::BoolVector wrap(3, false); RegularDecomposer::CoordinateVector ghosts(3, 1); RegularDecomposer decomposer(static_cast(numDims), - spatialDecomp.GetVTKmDIYBounds(), - static_cast(spatialDecomp.GetGlobalNumberOfBlocks()), + diyBounds, + globalNumberOfBlocks, shareFace, wrap, ghosts, diyDivisions); // Define which blocks live on which rank so that vtkmdiy can manage them - vtkmdiy::DynamicAssigner assigner( - comm, static_cast(size), static_cast(spatialDecomp.GetGlobalNumberOfBlocks())); + vtkmdiy::DynamicAssigner assigner(comm, static_cast(size), globalNumberOfBlocks); for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) { assigner.set_rank(static_cast(rank), @@ -394,6 +396,13 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned if (rank == 0) { + vtkm::Id3 dummy1, globalPointDimensions, dummy2; + vtkm::cont::DataSet firstDS = input.GetPartition(0); + firstDS.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + dummy1, + globalPointDimensions, + dummy2); // Now run the contour tree algorithm on the last block to compute the final tree vtkm::Id currNumIterations; vtkm::worklet::contourtree_augmented::ContourTree currContourTree; @@ -412,12 +421,12 @@ VTKM_CONT void ContourTreeAugmented::DoPostExecute(const vtkm::cont::Partitioned contourTreeMeshOut.MaxNeighbors = localDataBlocks[0]->MaxNeighbors; // Construct the mesh boundary exectuion object needed for boundary augmentation vtkm::Id3 minIdx(0, 0, 0); - vtkm::Id3 maxIdx = this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.GlobalSize; + vtkm::Id3 maxIdx = globalPointDimensions; maxIdx[0] = maxIdx[0] - 1; maxIdx[1] = maxIdx[1] - 1; maxIdx[2] = maxIdx[2] > 0 ? (maxIdx[2] - 1) : 0; - auto meshBoundaryExecObj = contourTreeMeshOut.GetMeshBoundaryExecutionObject( - this->MultiBlockTreeHelper->MultiBlockSpatialDecomposition.GlobalSize, minIdx, maxIdx); + auto meshBoundaryExecObj = + contourTreeMeshOut.GetMeshBoundaryExecutionObject(globalPointDimensions, minIdx, maxIdx); // Run the worklet to compute the final contour tree worklet.Run( contourTreeMeshOut.SortedValues, // Unused param. Provide something to keep API happy diff --git a/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.h b/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.h index 0b5dc342c..466b75c90 100644 --- a/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.h +++ b/vtkm/filter/scalar_topology/ContourTreeUniformAugmented.h @@ -114,19 +114,24 @@ public: /// /// Note: Only used when running on a multi-block dataset. /// @param[in] blocksPerDim Number of data blocks used in each data dimension - /// @param[in] globalSize Global extends of the input mesh (i.e., number of mesh points in each dimension) /// @param[in] localBlockIndices Array with the (x,y,z) index of each local data block with /// with respect to blocksPerDim - /// @param[in] localBlockOrigins Array with the (x,y,z) origin (with regard to mesh index) of each - /// local data block - /// @param[in] localBlockSizes Array with the sizes (i.e., extends in number of mesh points) of each - /// local data block VTKM_CONT + void SetBlockIndices(vtkm::Id3 blocksPerDim, + const vtkm::cont::ArrayHandle& localBlockIndices); + + VTKM_CONT + VTKM_DEPRECATED(1.9, + "Set PointSize, GlobalPointOrigin, and GlobalPointSize in CellSetStructured and " + "optionally use SetBlockIndices.") void SetSpatialDecomposition(vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, + vtkm::Id3, const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes); + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&) + { + SetBlockIndices(blocksPerDim, localBlockIndices); + } //@{ /// Get the contour tree computed by the filter diff --git a/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.cxx b/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.cxx index 3ccbdbc2d..d237dd8b0 100644 --- a/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.cxx +++ b/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.cxx @@ -51,6 +51,7 @@ //============================================================================== // vtkm includes +#include #include #include @@ -61,7 +62,7 @@ #include // distributed contour tree includes -#include +#include #include #include #include @@ -165,10 +166,10 @@ void SaveHierarchicalTreeDot( //----------------------------------------------------------------------------- ContourTreeUniformDistributed::ContourTreeUniformDistributed( vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, + vtkm::Id3, // globalSize, -> Now in CellSetStructured const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes, + const vtkm::cont::ArrayHandle&, // localBlockOrigins, -> Use from CellSetStructured + const vtkm::cont::ArrayHandle&, // localBlockSizes, -> Use from CellSetStructured vtkm::cont::LogLevel timingsLogLevel, vtkm::cont::LogLevel treeLogLevel) : UseBoundaryExtremaOnly(true) @@ -177,19 +178,33 @@ ContourTreeUniformDistributed::ContourTreeUniformDistributed( , SaveDotFiles(false) , TimingsLogLevel(timingsLogLevel) , TreeLogLevel(treeLogLevel) - , MultiBlockSpatialDecomposition(blocksPerDim, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes) - , LocalMeshes(static_cast(localBlockSizes.GetNumberOfValues())) - , LocalContourTrees(static_cast(localBlockSizes.GetNumberOfValues())) - , LocalBoundaryTrees(static_cast(localBlockSizes.GetNumberOfValues())) - , LocalInteriorForests(static_cast(localBlockSizes.GetNumberOfValues())) + , BlocksPerDimension(blocksPerDim) + , LocalBlockIndices(localBlockIndices) + , LocalMeshes() + , LocalContourTrees() + , LocalBoundaryTrees() + , LocalInteriorForests() { this->SetOutputFieldName("resultData"); } +ContourTreeUniformDistributed::ContourTreeUniformDistributed(vtkm::cont::LogLevel timingsLogLevel, + vtkm::cont::LogLevel treeLogLevel) + : UseBoundaryExtremaOnly(true) + , UseMarchingCubes(false) + , AugmentHierarchicalTree(false) + , SaveDotFiles(false) + , TimingsLogLevel(timingsLogLevel) + , TreeLogLevel(treeLogLevel) + , BlocksPerDimension(vtkm::Id3{ -1, -1, -1 }) + , LocalBlockIndices() + , LocalMeshes() + , LocalContourTrees() + , LocalBoundaryTrees() + , LocalInteriorForests() +{ + this->SetOutputFieldName("resultData"); +} //----------------------------------------------------------------------------- // Functions used in PrepareForExecution() to compute the local contour @@ -237,7 +252,7 @@ void ContourTreeUniformDistributed::ComputeLocalTree( template void ContourTreeUniformDistributed::ComputeLocalTreeImpl( const vtkm::Id blockIndex, - const vtkm::cont::DataSet&, // input, + const vtkm::cont::DataSet& ds, // input, const vtkm::cont::ArrayHandle& field, MeshType& mesh, MeshBoundaryExecType& meshBoundaryExecObject) @@ -278,10 +293,14 @@ void ContourTreeUniformDistributed::ComputeLocalTreeImpl( // Create an IdRelabeler since we are using a DataSetMesh type here, we don't need // the IdRelabeler for the BRACT construction when we are using a ContourTreeMesh. + vtkm::Id3 pointDimensions, globalPointDimensions, globalPointIndexStart; + ds.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + pointDimensions, + globalPointDimensions, + globalPointIndexStart); auto localToGlobalIdRelabeler = vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler( - this->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal().Get(blockIndex), - this->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get(blockIndex), - this->MultiBlockSpatialDecomposition.GlobalSize); + globalPointIndexStart, pointDimensions, globalPointDimensions); // Initialize the BoundaryTreeMaker auto boundaryTreeMaker = vtkm::worklet::contourtree_distributed::BoundaryTreeMaker( @@ -322,9 +341,9 @@ void ContourTreeUniformDistributed::ComputeLocalTreeImpl( "Before Fan In", mesh, field, - this->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal().Get(blockIndex), - this->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get(blockIndex), - this->MultiBlockSpatialDecomposition.GlobalSize); + globalPointIndexStart, + pointDimensions, + globalPointDimensions); bractFile << bractString << std::endl; } @@ -461,18 +480,40 @@ vtkm::cont::DataSet ContourTreeUniformDistributed::DoExecute(const vtkm::cont::D VTKM_CONT void ContourTreeUniformDistributed::PreExecute( const vtkm::cont::PartitionedDataSet& input) { - if (vtkm::filter::scalar_topology::internal::SpatialDecomposition::GetGlobalNumberOfBlocks( - input) != this->MultiBlockSpatialDecomposition.GetGlobalNumberOfBlocks()) + // TODO/FIXME: The following may be too expensive for a "sanity" check as it + // requires global communication + auto globalNumberOfPartitions = input.GetGlobalNumberOfPartitions(); + + if (globalNumberOfPartitions < 2) { - throw vtkm::cont::ErrorFilterExecution( - "Global number of blocks in MultiBlock dataset does not match the SpatialDecomposition"); + throw vtkm::cont::ErrorFilterExecution("ContourTreeUniformDistributed filter expects a " + "PartitionedDataSet with at least two partitions."); } - if (this->MultiBlockSpatialDecomposition.GetLocalNumberOfBlocks() != - input.GetNumberOfPartitions()) + + if (this->BlocksPerDimension[0] != -1) { - throw vtkm::cont::ErrorFilterExecution( - "Local number of blocks in MultiBlock dataset does not match the SpatialDecomposition"); + if (this->BlocksPerDimension[1] < 1 || this->BlocksPerDimension[2] < 1) + { + throw vtkm::cont::ErrorFilterExecution("Invalid input BlocksPerDimension."); + } + if (globalNumberOfPartitions != + this->BlocksPerDimension[0] * this->BlocksPerDimension[1] * this->BlocksPerDimension[2]) + { + throw vtkm::cont::ErrorFilterExecution("Global number of blocks in data set does not match " + "expected value based on BlocksPerDimension"); + } + if (this->LocalBlockIndices.GetNumberOfValues() != input.GetNumberOfPartitions()) + { + throw vtkm::cont::ErrorFilterExecution("Local number of partitions in data set does not " + "match number of specified blocks indices."); + } } + + // Allocate vectors + this->LocalMeshes.resize(static_cast(input.GetGlobalNumberOfPartitions())); + this->LocalContourTrees.resize(static_cast(input.GetGlobalNumberOfPartitions())); + this->LocalBoundaryTrees.resize(static_cast(input.GetGlobalNumberOfPartitions())); + this->LocalInteriorForests.resize(static_cast(input.GetGlobalNumberOfPartitions())); } vtkm::cont::PartitionedDataSet ContourTreeUniformDistributed::DoExecutePartitions( @@ -546,15 +587,6 @@ VTKM_CONT void ContourTreeUniformDistributed::PostExecute( vtkm::cont::Timer timer; timer.Start(); - // We are running in parallel and need to merge the contour tree in PostExecute - // TODO/FIXME: This filter should only be used in a parallel setting with more - // than one block. Is there a better way to enforce this? thrown an exception - // instead of an empty return? What is the appropriate exception? - if (this->MultiBlockSpatialDecomposition.GetGlobalNumberOfBlocks() == 1) - { - return; - } - auto field = // TODO/FIXME: Correct for more than one block per rank? input.GetPartition(0).GetField(this->GetActiveFieldName(), this->GetActiveFieldAssociation()); @@ -602,12 +634,15 @@ inline VTKM_CONT void ContourTreeUniformDistributed::ComputeVolumeMetric( inputContourTreeMaster.foreach ( [&](DistributedContourTreeBlockData* currInBlock, const vtkmdiy::Master::ProxyWithLink&) { vtkm::Id blockNo = currInBlock->LocalBlockNo; + const vtkm::cont::DataSet& currDS = hierarchicalTreeOutputDataSet[blockNo]; // The block size and origin may be modified during the FanIn so we need to use the // size and origin from the original decomposition instead of looking it up in the currInBlock - auto currBlockSize = - this->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get(blockNo); - auto currBlockOrigin = - this->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal().Get(blockNo); + vtkm::Id3 pointDimensions, globalPointDimensions, globalPointIndexStart; + currDS.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + pointDimensions, + globalPointDimensions, + globalPointIndexStart); // NOTE: Use dummy link to make DIY happy. The dummy link is never used, since all // communication is via RegularDecomposer, which sets up its own links. No need @@ -618,9 +653,9 @@ inline VTKM_CONT void ContourTreeUniformDistributed::ComputeVolumeMetric( currInBlock->GlobalBlockId, new HyperSweepBlock(blockNo, currInBlock->GlobalBlockId, - currBlockOrigin, - currBlockSize, - this->MultiBlockSpatialDecomposition.GlobalSize, + globalPointIndexStart, + pointDimensions, + globalPointDimensions, *currInBlock->HierarchicalAugmenter.AugmentedTree), new vtkmdiy::Link()); }); @@ -774,6 +809,7 @@ inline VTKM_CONT void ContourTreeUniformDistributed::ComputeVolumeMetric( }); } + //----------------------------------------------------------------------------- template VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( @@ -809,30 +845,32 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( // 1.1.2 Compute the gids for our local blocks using RegularDecomposer = vtkmdiy::RegularDecomposer; - const auto& spatialDecomp = this->MultiBlockSpatialDecomposition; - const auto numDims = spatialDecomp.NumberOfDimensions(); - // ... compute division vector for global domain - RegularDecomposer::DivisionsVector diyDivisions(numDims); - for (vtkm::IdComponent d = 0; d < static_cast(numDims); ++d) + RegularDecomposer::DivisionsVector diyDivisions; + std::vector vtkmdiyLocalBlockGids; + vtkmdiy::DiscreteBounds diyBounds(0); + if (this->BlocksPerDimension[0] == -1) { - diyDivisions[d] = static_cast(spatialDecomp.BlocksPerDimension[d]); + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "BlocksPerDimension not set. Computing block indices " + "from information in CellSetStructured."); + diyBounds = vtkm::filter::scalar_topology::internal::ComputeBlockIndices( + input, diyDivisions, vtkmdiyLocalBlockGids); } - - // ... compute coordinates of local blocks - auto localBlockIndicesPortal = spatialDecomp.LocalBlockIndices.ReadPortal(); - std::vector vtkmdiyLocalBlockGids(static_cast(input.GetNumberOfPartitions())); - for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) + else { - RegularDecomposer::DivisionsVector diyCoords(static_cast(numDims)); - auto currentCoords = localBlockIndicesPortal.Get(bi); - for (vtkm::IdComponent d = 0; d < numDims; ++d) - { - diyCoords[d] = static_cast(currentCoords[d]); - } - vtkmdiyLocalBlockGids[static_cast(bi)] = - RegularDecomposer::coords_to_gid(diyCoords, diyDivisions); + VTKM_LOG_S(vtkm::cont::LogLevel::Info, + "BlocksPerDimension set. Using information provided by caller."); + diyBounds = + vtkm::filter::scalar_topology::internal::ComputeBlockIndices(input, + this->BlocksPerDimension, + this->LocalBlockIndices, + diyDivisions, + vtkmdiyLocalBlockGids); } + int numDims = diyBounds.min.dimension(); + int globalNumberOfBlocks = + std::accumulate(diyDivisions.cbegin(), diyDivisions.cend(), 1, std::multiplies{}); // Record time to compute the local block ids timingsStream << " " << std::setw(38) << std::left << "Compute Block Ids and Local Links" @@ -840,16 +878,28 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( timer.Start(); // 1.1.3 Setup the block data for DIY and add it to master + // Note: globalPointDimensions is defined outside the loop since it is needed later. + // It may be set multiple times in the loop, but always to the same value. + vtkm::Id3 globalPointDimensions; for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) { + // Get the input block and associated cell set information + auto currBlock = input.GetPartition(static_cast(bi)); + vtkm::Id3 pointDimensions, globalPointIndexStart; + currBlock.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + pointDimensions, + globalPointDimensions, + globalPointIndexStart); + // Create the local data block structure and set extents auto newBlock = new DistributedContourTreeBlockData(); // Copy global block id into the local data block for use in the hierarchical augmentation newBlock->GlobalBlockId = vtkmdiyLocalBlockGids[bi]; newBlock->LocalBlockNo = bi; - newBlock->BlockOrigin = spatialDecomp.LocalBlockOrigins.ReadPortal().Get(bi); - newBlock->BlockSize = spatialDecomp.LocalBlockSizes.ReadPortal().Get(bi); + newBlock->BlockOrigin = globalPointIndexStart; + newBlock->BlockSize = pointDimensions; // Save local tree information for fan out; TODO/FIXME: Try to avoid copy newBlock->ContourTrees.push_back(this->LocalContourTrees[bi]); @@ -868,15 +918,10 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( auto transformedIndex = vtkm::cont::make_ArrayHandleTransform( permutedSortOrder, vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler( - this->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal().Get( - static_cast(bi)), - this->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get( - static_cast(bi)), - this->MultiBlockSpatialDecomposition.GlobalSize)); + globalPointIndexStart, pointDimensions, globalPointDimensions)); vtkm::cont::Algorithm::Copy(transformedIndex, localGlobalMeshIndex); // ... get data values - auto currBlock = input.GetPartition(static_cast(bi)); auto currField = currBlock.GetField(this->GetActiveFieldName(), this->GetActiveFieldAssociation()); vtkm::cont::ArrayHandle fieldData; @@ -942,16 +987,15 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( RegularDecomposer::BoolVector wrap(3, false); RegularDecomposer::CoordinateVector ghosts(3, 1); RegularDecomposer decomposer(static_cast(numDims), - spatialDecomp.GetVTKmDIYBounds(), - static_cast(spatialDecomp.GetGlobalNumberOfBlocks()), + diyBounds, + globalNumberOfBlocks, shareFace, wrap, ghosts, diyDivisions); // Define which blocks live on which rank so that vtkmdiy can manage them - vtkmdiy::DynamicAssigner assigner( - comm, static_cast(size), static_cast(spatialDecomp.GetGlobalNumberOfBlocks())); + vtkmdiy::DynamicAssigner assigner(comm, static_cast(size), globalNumberOfBlocks); for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) { assigner.set_rank(static_cast(rank), vtkmdiyLocalBlockGids[static_cast(bi)]); @@ -984,7 +1028,7 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( timer.Start(); // 1.3 Perform fan-in reduction const vtkm::worklet::contourtree_distributed::ComputeDistributedContourTreeFunctor - computeDistributedContourTreeFunctor(this->MultiBlockSpatialDecomposition.GlobalSize, + computeDistributedContourTreeFunctor(globalPointDimensions, this->UseBoundaryExtremaOnly, this->TimingsLogLevel, this->TreeLogLevel); @@ -1061,17 +1105,22 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( grafter(&(this->LocalMeshes[static_cast(blockData->LocalBlockNo)]), blockData->ContourTrees[0], &(blockData->InteriorForests[0])); - auto currBlock = input.GetPartition(blockData->LocalBlockNo); + vtkm::cont::DataSet currBlock = input.GetPartition(blockData->LocalBlockNo); auto currField = currBlock.GetField(this->GetActiveFieldName(), this->GetActiveFieldAssociation()); vtkm::cont::ArrayHandle fieldData; vtkm::cont::ArrayCopy(currField.GetData(), fieldData); + + vtkm::Id3 pointDimensions, globalPointIndexStart; + // globalPointDimensions already defined in parent scope + currBlock.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + pointDimensions, + globalPointDimensions, + globalPointIndexStart); + auto localToGlobalIdRelabeler = vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler( - this->MultiBlockSpatialDecomposition.LocalBlockOrigins.ReadPortal().Get( - blockData->LocalBlockNo), - this->MultiBlockSpatialDecomposition.LocalBlockSizes.ReadPortal().Get( - blockData->LocalBlockNo), - this->MultiBlockSpatialDecomposition.GlobalSize); + globalPointIndexStart, pointDimensions, globalPointDimensions); grafter.GraftInteriorForests( 0, blockData->HierarchicalTree, fieldData, &localToGlobalIdRelabeler); @@ -1155,9 +1204,30 @@ VTKM_CONT void ContourTreeUniformDistributed::DoPostExecute( // Add the information to the output data set blockHierarchcialTree.AddToVTKMDataSet(hierarchicalTreeOutputDataSet[blockData->LocalBlockNo]); + // Save information required to set up DIY + vtkm::cont::ArrayHandle vtkmGlobalBlockIdAH; + vtkmGlobalBlockIdAH.Allocate(1); + auto vtkmGlobalBlockIdWP = vtkmGlobalBlockIdAH.WritePortal(); + vtkmGlobalBlockIdWP.Set(0, blockData->GlobalBlockId); + vtkm::cont::Field vtkmGlobalBlockIdField( + "vtkmGlobalBlockId", vtkm::cont::Field::Association::WholeMesh, vtkmGlobalBlockIdAH); + hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(vtkmGlobalBlockIdField); + vtkm::cont::ArrayHandle vtkmBlocksPerDimensionAH; + vtkmBlocksPerDimensionAH.Allocate(3); + auto vtkmBlocksPerDimensionWP = vtkmBlocksPerDimensionAH.WritePortal(); + vtkmBlocksPerDimensionWP.Set(0, this->BlocksPerDimension[0]); + vtkmBlocksPerDimensionWP.Set(1, this->BlocksPerDimension[1]); + vtkmBlocksPerDimensionWP.Set(2, this->BlocksPerDimension[2]); + vtkm::cont::Field vtkmBlocksPerDimensionField("vtkmBlocksPerDimension", + vtkm::cont::Field::Association::WholeMesh, + vtkmBlocksPerDimensionAH); + hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].AddField(vtkmBlocksPerDimensionField); + // Copy cell set from input data set. This is mainly to ensure that the output data set // has a defined cell set. Without one, serialization for DIY does not work properly. // Having the extents of the input data set may also help in other use cases. + // For example, the ComputeVolume method gets information from this cell set as will + // the branch decomposition filter. hierarchicalTreeOutputDataSet[blockData->LocalBlockNo].SetCellSet( input.GetPartition(blockData->LocalBlockNo).GetCellSet()); diff --git a/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h b/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h index d173bb60c..5f915d250 100644 --- a/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h +++ b/vtkm/filter/scalar_topology/ContourTreeUniformDistributed.h @@ -56,7 +56,6 @@ #include #include -#include #include #include #include @@ -113,14 +112,20 @@ public: /// @param[in] treeLogLevel Set the vtkm::cont:LogLevel to be used to record metadata information /// about the various trees computed as part of the hierarchical contour tree compute VTKM_CONT - ContourTreeUniformDistributed( - vtkm::Id3 blocksPerDim, // TODO/FIXME: Possibly pass SpatialDecomposition object instead - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes, - vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf, - vtkm::cont::LogLevel treeLogLevel = vtkm::cont::LogLevel::Info); + VTKM_DEPRECATED( + 1.9, + "Use default constructor and set PointSize, GlobalPointIndexStart, and GlobalPointSize in " + "CellSetStructured. Optionally use `SetBlockIndices` accessor (if information is available).") + ContourTreeUniformDistributed(vtkm::Id3 blocksPerDim, + vtkm::Id3 globalSize, + const vtkm::cont::ArrayHandle& localBlockIndices, + const vtkm::cont::ArrayHandle& localBlockOrigins, + const vtkm::cont::ArrayHandle& localBlockSizes, + vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf, + vtkm::cont::LogLevel treeLogLevel = vtkm::cont::LogLevel::Info); + + ContourTreeUniformDistributed(vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf, + vtkm::cont::LogLevel treeLogLevel = vtkm::cont::LogLevel::Info); VTKM_CONT void SetUseBoundaryExtremaOnly(bool useBoundaryExtremaOnly) { @@ -141,6 +146,13 @@ public: this->AugmentHierarchicalTree = augmentHierarchicalTree; } + VTKM_CONT void SetBlockIndices(vtkm::Id3 blocksPerDim, + const vtkm::cont::ArrayHandle& localBlockIndices) + { + this->BlocksPerDimension = blocksPerDim; + vtkm::cont::ArrayCopy(localBlockIndices, this->LocalBlockIndices); + } + VTKM_CONT bool GetAugmentHierarchicalTree() { return this->AugmentHierarchicalTree; } VTKM_CONT void SetSaveDotFiles(bool saveDotFiles) { this->SaveDotFiles = saveDotFiles; } @@ -213,8 +225,11 @@ private: /// Log level to be used for outputting metadata about the trees. Default is vtkm::cont::LogLevel::Info vtkm::cont::LogLevel TreeLogLevel = vtkm::cont::LogLevel::Info; - /// Information about the spatial decomposition - vtkm::filter::scalar_topology::internal::SpatialDecomposition MultiBlockSpatialDecomposition; + /// Information about block decomposition TODO/FIXME: Remove need for this information + // ... Number of blocks along each dimension + vtkm::Id3 BlocksPerDimension; + // ... Index of the local blocks in x,y,z, i.e., in i,j,k mesh coordinates + vtkm::cont::ArrayHandle LocalBlockIndices; /// Intermediate results (one per local data block)... /// ... local mesh information needed at end of fan out @@ -240,28 +255,23 @@ class VTKM_DEPRECATED(1.8, "Use vtkm::filter::scalar_topology::ContourTreeUnifor using scalar_topology::ContourTreeUniformDistributed::ContourTreeUniformDistributed; ContourTreeUniformDistributed(vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, + vtkm::Id3, const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes, + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&, bool useBoundaryExtremaOnly = true, bool useMarchingCubes = false, bool augmentHierarchicalTree = false, bool saveDotFiles = false, vtkm::cont::LogLevel timingsLogLevel = vtkm::cont::LogLevel::Perf, vtkm::cont::LogLevel treeLogLevel = vtkm::cont::LogLevel::Info) - : vtkm::filter::scalar_topology::ContourTreeUniformDistributed(blocksPerDim, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes, - timingsLogLevel, - treeLogLevel) + : vtkm::filter::scalar_topology::ContourTreeUniformDistributed(timingsLogLevel, treeLogLevel) { this->SetUseBoundaryExtremaOnly(useBoundaryExtremaOnly); this->SetUseMarchingCubes(useMarchingCubes); this->SetAugmentHierarchicalTree(augmentHierarchicalTree); this->SetSaveDotFiles(saveDotFiles); + this->SetBlockIndices(blocksPerDim, localBlockIndices); this->SetOutputFieldName("resultData"); } }; diff --git a/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.cxx b/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.cxx index 22fc3b6a9..f2adc22cc 100644 --- a/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.cxx +++ b/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.cxx @@ -36,16 +36,11 @@ namespace scalar_topology // not need to pass it sperately (or check if it can already be derived from // information stored in PartitionedDataSet) VTKM_CONT DistributedBranchDecompositionFilter::DistributedBranchDecompositionFilter( - vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes) - : MultiBlockSpatialDecomposition(blocksPerDim, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes) + vtkm::Id3, + vtkm::Id3, + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&) { } @@ -80,52 +75,59 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D BranchDecompositionBlock::Destroy); timingsStream << " " << std::setw(60) << std::left - << "Create DIY Master (Branch Decomposition)" + << "Create DIY Master and Assigner (Branch Decomposition)" << ": " << timer.GetElapsedTime() << " seconds" << std::endl; timer.Start(); // Compute global ids (gids) for our local blocks - using RegularDecomposer = vtkmdiy::RegularDecomposer; - int globalNumberOfBlocks = - static_cast(this->MultiBlockSpatialDecomposition.GetGlobalNumberOfBlocks()); - int numDims = static_cast(this->MultiBlockSpatialDecomposition.NumberOfDimensions()); + // TODO/FIXME: Is there a better way to set this up? + auto firstDS = input.GetPartition(0); + vtkm::Id3 firstPointDimensions, firstGlobalPointDimensions, firstGlobalPointIndexStart; + firstDS.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + firstPointDimensions, + firstGlobalPointDimensions, + firstGlobalPointIndexStart); + int numDims = firstGlobalPointDimensions[2] > 1 ? 3 : 2; + auto vtkmBlocksPerDimensionRP = input.GetPartition(0) + .GetField("vtkmBlocksPerDimension") + .GetData() + .AsArrayHandle>() + .ReadPortal(); // ... compute division vector for global domain + using RegularDecomposer = vtkmdiy::RegularDecomposer; RegularDecomposer::DivisionsVector diyDivisions(numDims); + vtkmdiy::DiscreteBounds diyBounds(numDims); + int globalNumberOfBlocks = 1; + for (vtkm::IdComponent d = 0; d < static_cast(numDims); ++d) { - diyDivisions[d] = static_cast(this->MultiBlockSpatialDecomposition.BlocksPerDimension[d]); - } - - // ... compute coordinates of local blocks - std::vector vtkmdiyLocalBlockGids(static_cast(input.GetNumberOfPartitions())); - - auto localBlockIndicesPortal = - this->MultiBlockSpatialDecomposition.LocalBlockIndices.ReadPortal(); - for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) - { - RegularDecomposer::DivisionsVector diyCoords(static_cast(numDims)); - auto currentCoords = localBlockIndicesPortal.Get(bi); - for (vtkm::IdComponent d = 0; d < numDims; ++d) - { - diyCoords[d] = static_cast(currentCoords[d]); - } - vtkmdiyLocalBlockGids[static_cast(bi)] = - RegularDecomposer::coords_to_gid(diyCoords, diyDivisions); + diyDivisions[d] = static_cast(vtkmBlocksPerDimensionRP.Get(d)); + globalNumberOfBlocks *= diyDivisions[d]; + diyBounds.min[d] = 0; + diyBounds.max[d] = static_cast(firstGlobalPointDimensions[d]); } // Record time to compute the local block ids timingsStream << " " << std::setw(60) << std::left - << "Compute Block Ids and Local Links (Branch Decomposition)" + << "Get DIY Information (Branch Decomposition)" << ": " << timer.GetElapsedTime() << " seconds" << std::endl; timer.Start(); + // Initialize branch decomposition computation from data in PartitionedDataSet blocks + vtkmdiy::DynamicAssigner assigner(comm, size, globalNumberOfBlocks); for (vtkm::Id localBlockIndex = 0; localBlockIndex < input.GetNumberOfPartitions(); ++localBlockIndex) { - int globalBlockId = vtkmdiyLocalBlockGids[localBlockIndex]; const vtkm::cont::DataSet& ds = input.GetPartition(localBlockIndex); + int globalBlockId = static_cast( + vtkm::cont::ArrayGetValue(0, + ds.GetField("vtkmGlobalBlockId") + .GetData() + .AsArrayHandle>())); + BranchDecompositionBlock* newBlock = new BranchDecompositionBlock(localBlockIndex, globalBlockId, ds); // NOTE: Use dummy link to make DIY happy. The dummy link is never used, since all @@ -134,6 +136,9 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D // NOTE: Since we passed a "Destroy" function to DIY master, it will own the local data // blocks and delete them when done. branch_decomposition_master.add(globalBlockId, newBlock, new vtkmdiy::Link()); + + // Tell assigner that this block lives on this rank so that DIY can manage blocks + assigner.set_rank(rank, globalBlockId); } // Log time to copy the data to the HyperSweepBlock data objects @@ -146,19 +151,15 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D RegularDecomposer::BoolVector wrap(3, false); RegularDecomposer::CoordinateVector ghosts(3, 1); RegularDecomposer decomposer(numDims, - this->MultiBlockSpatialDecomposition.GetVTKmDIYBounds(), + diyBounds, static_cast(globalNumberOfBlocks), shareFace, wrap, ghosts, diyDivisions); - // Define which blocks live on which rank so that vtkmdiy can manage them - vtkmdiy::DynamicAssigner assigner(comm, size, globalNumberOfBlocks); - for (vtkm::Id bi = 0; bi < input.GetNumberOfPartitions(); bi++) { - assigner.set_rank(rank, vtkmdiyLocalBlockGids[static_cast(bi)]); } timingsStream << " " << std::setw(60) << std::left @@ -196,7 +197,7 @@ VTKM_CONT vtkm::cont::PartitionedDataSet DistributedBranchDecompositionFilter::D ds.GetField("DependentVolume").GetData().AsArrayHandle>(); // Get global size and compute total volume from it - const auto& globalSize = this->MultiBlockSpatialDecomposition.GlobalSize; + const auto& globalSize = firstGlobalPointDimensions; vtkm::Id totalVolume = globalSize[0] * globalSize[1] * globalSize[2]; // Compute local best up and down paths by volume diff --git a/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h b/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h index fc6458694..244bbfa71 100644 --- a/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h +++ b/vtkm/filter/scalar_topology/DistributedBranchDecompositionFilter.h @@ -45,8 +45,6 @@ #include #include -#include - namespace vtkm { namespace filter @@ -59,20 +57,17 @@ class VTKM_FILTER_SCALAR_TOPOLOGY_EXPORT DistributedBranchDecompositionFilter : public vtkm::filter::NewFilter { public: - VTKM_CONT DistributedBranchDecompositionFilter( - vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes); + VTKM_CONT DistributedBranchDecompositionFilter() = default; + VTKM_CONT DistributedBranchDecompositionFilter(vtkm::Id3, + vtkm::Id3, + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&, + const vtkm::cont::ArrayHandle&); private: VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet&) override; VTKM_CONT vtkm::cont::PartitionedDataSet DoExecutePartitions( const vtkm::cont::PartitionedDataSet& inData) override; - - /// Information about the spatial decomposition - vtkm::filter::scalar_topology::internal::SpatialDecomposition MultiBlockSpatialDecomposition; }; } // namespace scalar_topology diff --git a/vtkm/filter/scalar_topology/internal/CMakeLists.txt b/vtkm/filter/scalar_topology/internal/CMakeLists.txt index 6585e20c7..896c847f5 100644 --- a/vtkm/filter/scalar_topology/internal/CMakeLists.txt +++ b/vtkm/filter/scalar_topology/internal/CMakeLists.txt @@ -10,8 +10,8 @@ set(headers BranchDecompositionBlock.h + ComputeBlockIndices.h ComputeDistributedBranchDecompositionFunctor.h - SpatialDecomposition.h ) #----------------------------------------------------------------------------- diff --git a/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.cxx b/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.cxx new file mode 100644 index 000000000..ff881c797 --- /dev/null +++ b/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.cxx @@ -0,0 +1,255 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +// Copyright (c) 2018, The Regents of the University of California, through +// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals +// from the U.S. Dept. of Energy). All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National +// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================================= +// +// This code is an extension of the algorithm presented in the paper: +// Parallel Peak Pruning for Scalable SMP Contour Tree Computation. +// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens. +// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization +// (LDAV), October 2016, Baltimore, Maryland. +// +// The PPP2 algorithm and software were jointly developed by +// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and +// Oliver Ruebel (LBNL) +//============================================================================== + +#include +#include +#include +#include +#include +#include + +namespace // anonymous namespace for local helper classes +{ + +struct OriginsBlock +{ + std::vector Origins; + OriginsBlock(const std::vector& origins) + : Origins(origins) + { + } + static void Destroy(void* b) { delete static_cast(b); } +}; + +struct MergeOriginsFunctor +{ + void operator()(OriginsBlock* b, + const vtkmdiy::ReduceProxy& rp, // communication proxy + const vtkmdiy::RegularSwapPartners& // partners of the current block (unused) + ) const + { + const auto selfid = rp.gid(); + + std::vector incoming; + rp.incoming(incoming); + for (const int ingid : incoming) + { + if (ingid != selfid) + { + std::vector incoming_origins; + rp.dequeue(ingid, incoming_origins); + + std::vector merged_origins; + std::merge(incoming_origins.begin(), + incoming_origins.end(), + b->Origins.begin(), + b->Origins.end(), + std::inserter(merged_origins, merged_origins.begin())); + auto last = std::unique(merged_origins.begin(), merged_origins.end()); + merged_origins.erase(last, merged_origins.end()); + std::swap(merged_origins, b->Origins); + } + } + for (int cc = 0; cc < rp.out_link().size(); ++cc) + { + auto target = rp.out_link().target(cc); + if (target.gid != selfid) + { + rp.enqueue(target, b->Origins); + } + } + } +}; + +} +namespace vtkm +{ +namespace filter +{ +namespace scalar_topology +{ +namespace internal +{ + +VTKM_CONT vtkmdiy::DiscreteBounds ComputeBlockIndices(const vtkm::cont::PartitionedDataSet& input, + DiscreteBoundsDivisionVector& diyDivisions, + std::vector& diyLocalBlockGids) +{ + auto firstDS = input.GetPartition(0); + vtkm::Id3 dummy1, firstGlobalPointDimensions, dummy2; + firstDS.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + dummy1, + firstGlobalPointDimensions, + dummy2); + int numDims = firstGlobalPointDimensions[2] > 1 ? 3 : 2; + + diyDivisions.clear(); + vtkmdiy::DiscreteBounds diyBounds(numDims); + std::vector diyBlockCoords(input.GetNumberOfPartitions()); + + for (vtkm::IdComponent d = 0; d < numDims; ++d) + { + // Set bounds for this dimension + diyBounds.min[d] = 0; + diyBounds.max[d] = static_cast(firstGlobalPointDimensions[d]); + + // Get the list of origins along current coordinate axis + std::vector local_origins; + + for (vtkm::Id ds_no = 0; ds_no < input.GetNumberOfPartitions(); ++ds_no) + { + vtkm::Id3 globalPointIndexStart; + input.GetPartition(ds_no) + .GetCellSet() + .CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + dummy1, + dummy2, + globalPointIndexStart); + + local_origins.push_back(static_cast(globalPointIndexStart[d])); + } + + // Sort and remove duplicates + OriginsBlock* origins_block = new OriginsBlock(local_origins); + std::sort(origins_block->Origins.begin(), origins_block->Origins.end()); + auto last = std::unique(origins_block->Origins.begin(), origins_block->Origins.end()); + origins_block->Origins.erase(last, origins_block->Origins.end()); + + // Create global list of origins across all ranks + auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); + auto rank = comm.rank(); + auto size = comm.size(); + vtkmdiy::Master master(comm, 1, -1, 0, OriginsBlock::Destroy); + master.add(rank, origins_block, new vtkmdiy::Link); + vtkmdiy::ContiguousAssigner assigner(size, size); + vtkmdiy::DiscreteBounds bounds(1); + bounds.min[0] = 0; + bounds.max[0] = size - 1; + vtkmdiy::RegularDecomposer decomposer(1, bounds, size); + vtkmdiy::RegularSwapPartners partners(decomposer, 2, true); + vtkmdiy::reduce(master, assigner, partners, MergeOriginsFunctor{}); + + // Number of blocks/divisions along axis is number of unique origins along this axis + diyDivisions.push_back(static_cast(origins_block->Origins.size())); + + // Block index aling this axis is the index of the origin in that list + for (vtkm::Id ds_no = 0; ds_no < input.GetNumberOfPartitions(); ++ds_no) + { + diyBlockCoords[ds_no].push_back(static_cast(std::find(origins_block->Origins.begin(), + origins_block->Origins.end(), + local_origins[ds_no]) - + origins_block->Origins.begin())); + } + } + + // Compute global block IDs + diyLocalBlockGids.clear(); + for (vtkm::Id ds_no = 0; ds_no < input.GetNumberOfPartitions(); ++ds_no) + { + diyLocalBlockGids.push_back(vtkmdiy::RegularDecomposer::coords_to_gid( + diyBlockCoords[ds_no], diyDivisions)); + } + + return diyBounds; +} + +VTKM_CONT vtkmdiy::DiscreteBounds ComputeBlockIndices( + const vtkm::cont::PartitionedDataSet& input, + vtkm::Id3 blocksPerDim, + const vtkm::cont::ArrayHandle& blockIndices, + DiscreteBoundsDivisionVector& diyDivisions, + std::vector& diyLocalBlockGids) +{ + auto firstDS = input.GetPartition(0); + vtkm::Id3 dummy1, firstGlobalPointDimensions, dummy2; + firstDS.GetCellSet().CastAndCallForTypes( + vtkm::worklet::contourtree_augmented::GetLocalAndGlobalPointDimensions(), + dummy1, + firstGlobalPointDimensions, + dummy2); + int numDims = firstGlobalPointDimensions[2] > 1 ? 3 : 2; + + diyDivisions.clear(); + vtkmdiy::DiscreteBounds diyBounds(numDims); + for (vtkm::IdComponent d = 0; d < numDims; ++d) + { + // Set bounds for this dimension + diyBounds.min[d] = 0; + diyBounds.max[d] = static_cast(firstGlobalPointDimensions[d]); + diyDivisions.push_back(static_cast(blocksPerDim[d])); + } + + // Compute global block IDs + diyLocalBlockGids.clear(); + auto blockIndicesPortal = blockIndices.ReadPortal(); + for (vtkm::Id ds_no = 0; ds_no < input.GetNumberOfPartitions(); ++ds_no) + { + auto currBlockIndices = blockIndicesPortal.Get(ds_no); + DiscreteBoundsDivisionVector diyBlockCoords(numDims); + for (vtkm::IdComponent d = 0; d < numDims; ++d) + { + diyBlockCoords[d] = static_cast(currBlockIndices[d]); + } + + diyLocalBlockGids.push_back(vtkmdiy::RegularDecomposer::coords_to_gid( + diyBlockCoords, diyDivisions)); + } + + return diyBounds; +} + +} // namespace internal +} // namespace scalar_topology +} // namespace filter +} // namespace vtkm diff --git a/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.h b/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.h new file mode 100644 index 000000000..1b492e9b5 --- /dev/null +++ b/vtkm/filter/scalar_topology/internal/ComputeBlockIndices.h @@ -0,0 +1,98 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +// Copyright (c) 2018, The Regents of the University of California, through +// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals +// from the U.S. Dept. of Energy). All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National +// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +// OF THE POSSIBILITY OF SUCH DAMAGE. +// +//============================================================================= +// +// This code is an extension of the algorithm presented in the paper: +// Parallel Peak Pruning for Scalable SMP Contour Tree Computation. +// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens. +// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization +// (LDAV), October 2016, Baltimore, Maryland. +// +// The PPP2 algorithm and software were jointly developed by +// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and +// Oliver Ruebel (LBNL) +//============================================================================== + +#ifndef vtk_m_filter_scalar_topology_internal_ComputeBlockIndices_h_ +#define vtk_m_filter_scalar_topology_internal_ComputeBlockIndices_h_ + +#include + +#include +#include +#include + +// DIY includes +// clang-format off +VTKM_THIRDPARTY_PRE_INCLUDE +#include +#include +VTKM_THIRDPARTY_POST_INCLUDE +// clang-format on + +namespace vtkm +{ +namespace filter +{ +namespace scalar_topology +{ +namespace internal +{ + +using DiscreteBoundsDivisionVector = + vtkmdiy::RegularDecomposer::DivisionsVector; + +VTKM_CONT vtkmdiy::DiscreteBounds ComputeBlockIndices(const vtkm::cont::PartitionedDataSet& input, + DiscreteBoundsDivisionVector& diyDivisions, + std::vector& diyLocalBlockGids); + +VTKM_CONT vtkmdiy::DiscreteBounds ComputeBlockIndices( + const vtkm::cont::PartitionedDataSet& input, + vtkm::Id3 blocksPerDim, + const vtkm::cont::ArrayHandle& blockIndices, + DiscreteBoundsDivisionVector& diyDivisions, + std::vector& diyLocalBlockGids); + +} // namespace internal +} // namespace scalar_topology +} // namespace filter +} // namespace vtkm + +#endif diff --git a/vtkm/filter/scalar_topology/internal/SpatialDecomposition.h b/vtkm/filter/scalar_topology/internal/SpatialDecomposition.h deleted file mode 100644 index 5ab7ab689..000000000 --- a/vtkm/filter/scalar_topology/internal/SpatialDecomposition.h +++ /dev/null @@ -1,172 +0,0 @@ -//============================================================================ -// Copyright (c) Kitware, Inc. -// All rights reserved. -// See LICENSE.txt for details. -// -// This software is distributed WITHOUT ANY WARRANTY; without even -// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the above copyright notice for more information. -//============================================================================ -// Copyright (c) 2018, The Regents of the University of California, through -// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals -// from the U.S. Dept. of Energy). All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// (1) Redistributions of source code must retain the above copyright notice, this -// list of conditions and the following disclaimer. -// -// (2) Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// (3) Neither the name of the University of California, Lawrence Berkeley National -// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be -// used to endorse or promote products derived from this software without -// specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -// OF THE POSSIBILITY OF SUCH DAMAGE. -// -//============================================================================= -// -// This code is an extension of the algorithm presented in the paper: -// Parallel Peak Pruning for Scalable SMP Contour Tree Computation. -// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens. -// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization -// (LDAV), October 2016, Baltimore, Maryland. -// -// The PPP2 algorithm and software were jointly developed by -// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and -// Oliver Ruebel (LBNL) -//============================================================================== - -#ifndef vtk_m_filter_scalar_topology_internal_SpatialDecomposition_h -#define vtk_m_filter_scalar_topology_internal_SpatialDecomposition_h - -#include -#include -#include -#include -#include - -#include - -// clang-format off -VTKM_THIRDPARTY_PRE_INCLUDE -#include -VTKM_THIRDPARTY_POST_INCLUDE -// clang-format on - -namespace vtkm -{ -namespace filter -{ -namespace scalar_topology -{ -namespace internal -{ - -// --- Helper class to store the spatial decomposition defined by the PartitionedDataSet input data -class SpatialDecomposition -{ -public: - VTKM_CONT - SpatialDecomposition(vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes) - : BlocksPerDimension(blocksPerDim) - , GlobalSize(globalSize) - , LocalBlockIndices(localBlockIndices) - , LocalBlockOrigins(localBlockOrigins) - , LocalBlockSizes(localBlockSizes) - { - } - - inline vtkmdiy::DiscreteBounds GetVTKmDIYBounds() const - { - if (this->NumberOfDimensions() == 2) - { - vtkmdiy::DiscreteBounds domain(2); - domain.min[0] = domain.min[1] = 0; - domain.max[0] = static_cast(this->GlobalSize[0]); - domain.max[1] = static_cast(this->GlobalSize[1]); - return domain; - } - else - { - vtkmdiy::DiscreteBounds domain(3); - domain.min[0] = domain.min[1] = domain.min[2] = 0; - domain.max[0] = static_cast(this->GlobalSize[0]); - domain.max[1] = static_cast(this->GlobalSize[1]); - domain.max[2] = static_cast(this->GlobalSize[2]); - return domain; - } - } - - inline vtkm::Id NumberOfDimensions() const { return GlobalSize[2] > 1 ? 3 : 2; } - - inline vtkm::Id GetGlobalNumberOfBlocks() const - { - return BlocksPerDimension[0] * BlocksPerDimension[1] * BlocksPerDimension[2]; - } - - inline vtkm::Id GetLocalNumberOfBlocks() const { return LocalBlockSizes.GetNumberOfValues(); } - - inline static vtkm::Bounds GetGlobalBounds(const vtkm::cont::PartitionedDataSet& input) - { - // Get the spatial bounds of a multi -block data set - vtkm::Bounds bounds = vtkm::cont::BoundsGlobalCompute(input); - return bounds; - } - - inline static vtkm::Bounds GetLocalBounds(const vtkm::cont::PartitionedDataSet& input) - { - // Get the spatial bounds of a multi -block data set - vtkm::Bounds bounds = vtkm::cont::BoundsCompute(input); - return bounds; - } - - inline static vtkm::Id GetGlobalNumberOfBlocks(const vtkm::cont::PartitionedDataSet& input) - { - auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); - vtkm::Id localSize = input.GetNumberOfPartitions(); - vtkm::Id globalSize = 0; -#ifdef VTKM_ENABLE_MPI - vtkmdiy::mpi::all_reduce(comm, localSize, globalSize, std::plus{}); -#else - globalSize = localSize; -#endif - return globalSize; - } - - // Number of blocks along each dimension - vtkm::Id3 BlocksPerDimension; - // Size of the global mesh - vtkm::Id3 GlobalSize; - // Index of the local blocks in x,y,z, i.e., in i,j,k mesh coordinates - vtkm::cont::ArrayHandle LocalBlockIndices; - // Origin of the local blocks in mesh index space - vtkm::cont::ArrayHandle LocalBlockOrigins; - // Size of each local block in x, y,z - vtkm::cont::ArrayHandle LocalBlockSizes; -}; - - -} // internal -} // namespace scalar_topology -} // namespace filter -} // namespace vtkm - -#endif diff --git a/vtkm/filter/scalar_topology/testing/TestingContourTreeUniformDistributedFilter.h b/vtkm/filter/scalar_topology/testing/TestingContourTreeUniformDistributedFilter.h index 2747866c2..431ef376a 100644 --- a/vtkm/filter/scalar_topology/testing/TestingContourTreeUniformDistributedFilter.h +++ b/vtkm/filter/scalar_topology/testing/TestingContourTreeUniformDistributedFilter.h @@ -203,12 +203,22 @@ inline vtkm::cont::DataSet CreateSubDataSet(const vtkm::cont::DataSet& ds, { vtkm::Id2 dimensions{ blockSize[0], blockSize[1] }; vtkm::cont::DataSet dataSet = dsb.Create(dimensions); + vtkm::cont::CellSetStructured<2> cellSet; + cellSet.SetPointDimensions(dimensions); + cellSet.SetGlobalPointDimensions(vtkm::Id2{ globalSize[0], globalSize[1] }); + cellSet.SetGlobalPointIndexStart(vtkm::Id2{ blockOrigin[0], blockOrigin[1] }); + dataSet.SetCellSet(cellSet); dataSet.AddField(permutedField); return dataSet; } else { vtkm::cont::DataSet dataSet = dsb.Create(blockSize); + vtkm::cont::CellSetStructured<3> cellSet; + cellSet.SetPointDimensions(blockSize); + cellSet.SetGlobalPointDimensions(globalSize); + cellSet.SetGlobalPointIndexStart(blockOrigin); + dataSet.SetCellSet(cellSet); dataSet.AddField(permutedField); return dataSet; } @@ -241,7 +251,8 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( int numberOfRanks, bool augmentHierarchicalTree, bool computeHierarchicalVolumetricBranchDecomposition, - vtkm::Id3& globalSize) + vtkm::Id3& globalSize, + bool passBlockIndices = true) { // Get dimensions of data set vtkm::cont::CastAndCall( @@ -267,15 +278,9 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( // Created partitioned (split) data set vtkm::cont::PartitionedDataSet pds; vtkm::cont::ArrayHandle localBlockIndices; - vtkm::cont::ArrayHandle localBlockOrigins; - vtkm::cont::ArrayHandle localBlockSizes; localBlockIndices.Allocate(blocksOnThisRank); - localBlockOrigins.Allocate(blocksOnThisRank); - localBlockSizes.Allocate(blocksOnThisRank); auto localBlockIndicesPortal = localBlockIndices.WritePortal(); - auto localBlockOriginsPortal = localBlockOrigins.WritePortal(); - auto localBlockSizesPortal = localBlockSizes.WritePortal(); for (vtkm::Id blockNo = 0; blockNo < blocksOnThisRank; ++blockNo) { @@ -283,20 +288,17 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( std::tie(blockIndex, blockOrigin, blockSize) = ComputeBlockExtents(globalSize, blocksPerAxis, startBlockNo + blockNo); pds.AppendPartition(CreateSubDataSet(ds, blockOrigin, blockSize, fieldName)); - localBlockOriginsPortal.Set(blockNo, blockOrigin); - localBlockSizesPortal.Set(blockNo, blockSize); localBlockIndicesPortal.Set(blockNo, blockIndex); } // Run the contour tree analysis vtkm::filter::scalar_topology::ContourTreeUniformDistributed filter( - blocksPerAxis, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes, - vtkm::cont::LogLevel::UserVerboseLast, - vtkm::cont::LogLevel::UserVerboseLast); + vtkm::cont::LogLevel::UserVerboseLast, vtkm::cont::LogLevel::UserVerboseLast); + + if (passBlockIndices) + { + filter.SetBlockIndices(blocksPerAxis, localBlockIndices); + } filter.SetUseMarchingCubes(useMarchingCubes); // Freudenthal: Only use boundary extrema; MC: use all points on boundary @@ -310,8 +312,7 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( { using vtkm::filter::scalar_topology::DistributedBranchDecompositionFilter; - DistributedBranchDecompositionFilter bd_filter( - blocksPerAxis, globalSize, localBlockIndices, localBlockOrigins, localBlockSizes); + DistributedBranchDecompositionFilter bd_filter; result = bd_filter.Execute(result); } @@ -387,7 +388,8 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( int rank = 0, int numberOfRanks = 1, bool augmentHierarchicalTree = false, - bool computeHierarchicalVolumetricBranchDecomposition = false) + bool computeHierarchicalVolumetricBranchDecomposition = false, + bool passBlockIndices = true) { vtkm::Id3 globalSize; @@ -399,7 +401,8 @@ inline vtkm::cont::PartitionedDataSet RunContourTreeDUniformDistributed( numberOfRanks, augmentHierarchicalTree, computeHierarchicalVolumetricBranchDecomposition, - globalSize); + globalSize, + passBlockIndices); } inline void TestContourTreeUniformDistributed8x9(int nBlocks, int rank = 0, int size = 1) @@ -575,7 +578,8 @@ inline void TestContourTreeFile(std::string ds_filename, int rank = 0, int size = 1, bool augmentHierarchicalTree = false, - bool computeHierarchicalVolumetricBranchDecomposition = false) + bool computeHierarchicalVolumetricBranchDecomposition = false, + bool passBlockIndices = true) { if (rank == 0) { @@ -611,7 +615,8 @@ inline void TestContourTreeFile(std::string ds_filename, size, augmentHierarchicalTree, computeHierarchicalVolumetricBranchDecomposition, - globalSize); + globalSize, + passBlockIndices); if (rank == 0) { diff --git a/vtkm/filter/scalar_topology/testing/UnitTestContourTreeUniformDistributedFilter.cxx b/vtkm/filter/scalar_topology/testing/UnitTestContourTreeUniformDistributedFilter.cxx index 35e878c32..e37194004 100644 --- a/vtkm/filter/scalar_topology/testing/UnitTestContourTreeUniformDistributedFilter.cxx +++ b/vtkm/filter/scalar_topology/testing/UnitTestContourTreeUniformDistributedFilter.cxx @@ -112,6 +112,16 @@ public: 1, true, false); + TestContourTreeFile(Testing::DataPath("rectilinear/vanc.vtk"), + "var", + Testing::RegressionImagePath("vanc.augment_hierarchical_tree.ct_txt"), + 4, + false, + 0, + 1, + true, + false, + false); } }; } diff --git a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h index f9752a05f..1927b3831 100644 --- a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h +++ b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/Types.h @@ -328,6 +328,47 @@ struct GetPointDimensions } }; + +struct GetLocalAndGlobalPointDimensions +{ + void operator()(const vtkm::cont::CellSetStructured<2>& cells, + vtkm::Id3& pointDimensions, + vtkm::Id3& globalPointDimensions, + vtkm::Id3& globalPointIndexStart) const + { + vtkm::Id2 pointDimensions2D = cells.GetPointDimensions(); + pointDimensions[0] = pointDimensions2D[0]; + pointDimensions[1] = pointDimensions2D[1]; + pointDimensions[2] = 1; + vtkm::Id2 globalPointDimensions2D = cells.GetGlobalPointDimensions(); + globalPointDimensions[0] = globalPointDimensions2D[0]; + globalPointDimensions[1] = globalPointDimensions2D[1]; + globalPointDimensions[2] = 1; + vtkm::Id2 pointIndexStart2D = cells.GetGlobalPointIndexStart(); + globalPointIndexStart[0] = pointIndexStart2D[0]; + globalPointIndexStart[1] = pointIndexStart2D[1]; + globalPointIndexStart[2] = 0; + } + void operator()(const vtkm::cont::CellSetStructured<3>& cells, + vtkm::Id3& pointDimensions, + vtkm::Id3& globalPointDimensions, + vtkm::Id3& globalPointIndexStart) const + { + pointDimensions = cells.GetPointDimensions(); + globalPointDimensions = cells.GetGlobalPointDimensions(); + globalPointIndexStart = cells.GetGlobalPointIndexStart(); + } + //@} + + + /// Raise ErrorBadValue if the input cell set is not a vtkm::cont::CellSetStructured<2> or <3> + template + void operator()(const T&, vtkm::Id3&, vtkm::Id3&, vtkm::Id3&) const + { + throw vtkm::cont::ErrorBadValue("Expected 2D or 3D structured cell cet! "); + } +}; + } // namespace contourtree_augmented } // worklet } // vtkm diff --git a/vtkm/filter/scalar_topology/worklet/contourtree_distributed/MultiBlockContourTreeHelper.h b/vtkm/filter/scalar_topology/worklet/contourtree_distributed/MultiBlockContourTreeHelper.h index ba9095521..5aad7f3ae 100644 --- a/vtkm/filter/scalar_topology/worklet/contourtree_distributed/MultiBlockContourTreeHelper.h +++ b/vtkm/filter/scalar_topology/worklet/contourtree_distributed/MultiBlockContourTreeHelper.h @@ -53,15 +53,12 @@ #ifndef vtk_m_worklet_contourtree_distributed_multiblockcontourtreehelper_h #define vtk_m_worklet_contourtree_distributed_multiblockcontourtreehelper_h -#include - #include #include #include #include #include -//#include #include #include #include @@ -79,19 +76,21 @@ class MultiBlockContourTreeHelper public: VTKM_CONT MultiBlockContourTreeHelper(vtkm::Id3 blocksPerDim, - vtkm::Id3 globalSize, - const vtkm::cont::ArrayHandle& localBlockIndices, - const vtkm::cont::ArrayHandle& localBlockOrigins, - const vtkm::cont::ArrayHandle& localBlockSizes) - : MultiBlockSpatialDecomposition(blocksPerDim, - globalSize, - localBlockIndices, - localBlockOrigins, - localBlockSizes) + const vtkm::cont::ArrayHandle& localBlockIndices) + : BlocksPerDimension(blocksPerDim) + , LocalBlockIndices(localBlockIndices) + , LocalContourTrees(static_cast(localBlockIndices.GetNumberOfValues())) + , LocalSortOrders(static_cast(localBlockIndices.GetNumberOfValues())) + { + } + + VTKM_CONT + MultiBlockContourTreeHelper(const vtkm::cont::PartitionedDataSet& input) + : BlocksPerDimension(-1, -1, -1) + , LocalBlockIndices() + , LocalContourTrees(static_cast(input.GetNumberOfPartitions())) + , LocalSortOrders(static_cast(input.GetNumberOfPartitions())) { - vtkm::Id localNumBlocks = this->GetLocalNumberOfBlocks(); - LocalContourTrees.resize(static_cast(localNumBlocks)); - LocalSortOrders.resize(static_cast(localNumBlocks)); } VTKM_CONT @@ -118,25 +117,12 @@ public: inline vtkm::Id GetLocalNumberOfBlocks() const { - return this->MultiBlockSpatialDecomposition.GetLocalNumberOfBlocks(); + return static_cast(this->LocalContourTrees.size()); } inline vtkm::Id GetGlobalNumberOfBlocks() const { - return this->MultiBlockSpatialDecomposition.GetGlobalNumberOfBlocks(); - } - - inline static vtkm::Id GetGlobalNumberOfBlocks(const vtkm::cont::PartitionedDataSet& input) - { - auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator(); - vtkm::Id localSize = input.GetNumberOfPartitions(); - vtkm::Id globalSize = 0; -#ifdef VTKM_ENABLE_MPI - vtkmdiy::mpi::all_reduce(comm, localSize, globalSize, std::plus{}); -#else - globalSize = localSize; -#endif - return globalSize; + return this->BlocksPerDimension[0] * this->BlocksPerDimension[1] * this->BlocksPerDimension[2]; } // Used to compute the local contour tree mesh in after DoExecute. I.e., the function is @@ -198,7 +184,8 @@ public: } } - vtkm::filter::scalar_topology::internal::SpatialDecomposition MultiBlockSpatialDecomposition; + vtkm::Id3 BlocksPerDimension; + vtkm::cont::ArrayHandle LocalBlockIndices; std::vector LocalContourTrees; std::vector LocalSortOrders; }; // end MultiBlockContourTreeHelper diff --git a/vtkm/filter/testing/CMakeLists.txt b/vtkm/filter/testing/CMakeLists.txt index c3ae6ad89..b9995d3c0 100644 --- a/vtkm/filter/testing/CMakeLists.txt +++ b/vtkm/filter/testing/CMakeLists.txt @@ -17,8 +17,6 @@ set(unit_tests UnitTestMapFieldPermutation.cxx UnitTestMultiBlockFilter.cxx UnitTestPartitionedDataSetFilters.cxx - UnitTestStreamlineFilter.cxx - UnitTestStreamSurfaceFilter.cxx ) set(libraries @@ -27,50 +25,8 @@ set(libraries vtkm_source ) -if (VTKm_ENABLE_RENDERING) - list(APPEND libraries vtkm_rendering vtkm_rendering_testing) - - list(APPEND unit_tests - RenderTestStreamline.cxx - ) -endif() - -if ((TARGET vtkm::cuda) OR (TARGET vtkm::kokkos_cuda)) -#CUDA architecture has a limited amount of memory available for constants.The CUDA -#compiler uses this space to hold constants for some optimizations.However, for large -#kernels, the number of constants needed might be larger than the constant space -#available.For these conditions, you have to disable this form of optimization with -#the - Xptxas-- disable - optimizer - constants flags. -#TODO : Find a more elegant way to do this.Either figure out a way around this problem -# or add more general flags to vtkm_library / vtkm_unit_tests for sources with "large" kernels. - set(large_kernel_sources - RegressionTestStreamline.cxx - UnitTestLagrangianFilter.cxx - UnitTestStreamlineFilter.cxx - UnitTestStreamSurfaceFilter.cxx - ) - set_source_files_properties(${large_kernel_sources} PROPERTIES - COMPILE_OPTIONS "-Xptxas;--disable-optimizer-constants" - ) -endif() - vtkm_unit_tests( DEVICE_SOURCES ${unit_tests} LIBRARIES ${libraries} USE_VTKM_JOB_POOL ) - -#add distributed tests i.e.test to run with MPI -#if MPI is enabled. -if (VTKm_ENABLE_MPI) - set(mpi_unit_tests - UnitTestParticleMessengerMPI.cxx - UnitTestStreamlineFilterMPI.cxx - ) - vtkm_unit_tests( - MPI - DEVICE_SOURCES ${mpi_unit_tests} - LIBRARIES vtkm_filter vtkm_source vtkm_io - USE_VTKM_JOB_POOL - ) -endif() diff --git a/vtkm/filter/testing/RenderTestStreamline.cxx b/vtkm/filter/testing/RenderTestStreamline.cxx index 03f128ca4..a6fde1804 100644 --- a/vtkm/filter/testing/RenderTestStreamline.cxx +++ b/vtkm/filter/testing/RenderTestStreamline.cxx @@ -9,12 +9,14 @@ //============================================================================ #include +#include +#include #include #include #include #include -#include +#include #include #include @@ -34,7 +36,7 @@ void TestStreamline() vtkm::Particle(vtkm::Vec3f(.2f, 2.0f, .2f), 1), vtkm::Particle(vtkm::Vec3f(.2f, 3.0f, .2f), 2) }); - vtkm::filter::Streamline streamline; + vtkm::filter::flow::Streamline streamline; streamline.SetStepSize(0.1f); streamline.SetNumberOfSteps(20); streamline.SetSeeds(seedArray); diff --git a/vtkm/filter/testing/UnitTestLagrangianStructuresFilter.cxx b/vtkm/filter/testing/UnitTestLagrangianStructuresFilter.cxx index e2ecb2686..cee1b803f 100644 --- a/vtkm/filter/testing/UnitTestLagrangianStructuresFilter.cxx +++ b/vtkm/filter/testing/UnitTestLagrangianStructuresFilter.cxx @@ -9,6 +9,7 @@ //============================================================================ #include +#include #include #include #include diff --git a/vtkm/internal/ConnectivityStructuredInternals.h b/vtkm/internal/ConnectivityStructuredInternals.h index 5240850ae..7e2e0717a 100644 --- a/vtkm/internal/ConnectivityStructuredInternals.h +++ b/vtkm/internal/ConnectivityStructuredInternals.h @@ -37,15 +37,24 @@ public: VTKM_EXEC_CONT void SetPointDimensions(vtkm::Id dimensions) { this->PointDimensions = dimensions; } + VTKM_EXEC_CONT + void SetGlobalPointDimensions(vtkm::Id dimensions) { this->GlobalPointDimensions = dimensions; } + VTKM_EXEC_CONT void SetGlobalPointIndexStart(vtkm::Id start) { this->GlobalPointIndexStart = start; } VTKM_EXEC_CONT vtkm::Id GetPointDimensions() const { return this->PointDimensions; } + VTKM_EXEC_CONT + vtkm::Id GetGlobalPointDimensions() const { return this->GlobalPointDimensions; } + VTKM_EXEC_CONT vtkm::Id GetCellDimensions() const { return this->PointDimensions - 1; } + VTKM_EXEC_CONT + vtkm::Id GetGlobalCellDimensions() const { return this->GlobalPointDimensions - 1; } + VTKM_EXEC_CONT SchedulingRangeType GetSchedulingRange(vtkm::TopologyElementTagCell) const { @@ -138,12 +147,15 @@ public: void PrintSummary(std::ostream& out) const { out << " UniformConnectivity<1> "; - out << "this->PointDimensions[" << this->PointDimensions << "] "; + out << "PointDimensions[" << this->PointDimensions << "] "; + out << "GlobalPointDimensions[" << this->GlobalPointDimensions << "] "; + out << "GlobalPointIndexStart[" << this->GlobalPointIndexStart << "] "; out << "\n"; } private: vtkm::Id PointDimensions = 0; + vtkm::Id GlobalPointDimensions = 0; vtkm::Id GlobalPointIndexStart = 0; }; @@ -157,15 +169,24 @@ public: VTKM_EXEC_CONT void SetPointDimensions(vtkm::Id2 dims) { this->PointDimensions = dims; } + VTKM_EXEC_CONT + void SetGlobalPointDimensions(vtkm::Id2 dims) { this->GlobalPointDimensions = dims; } + VTKM_EXEC_CONT void SetGlobalPointIndexStart(vtkm::Id2 start) { this->GlobalPointIndexStart = start; } VTKM_EXEC_CONT const vtkm::Id2& GetPointDimensions() const { return this->PointDimensions; } + VTKM_EXEC_CONT + const vtkm::Id2& GetGlobalPointDimensions() const { return this->GlobalPointDimensions; } + VTKM_EXEC_CONT vtkm::Id2 GetCellDimensions() const { return this->PointDimensions - vtkm::Id2(1); } + VTKM_EXEC_CONT + vtkm::Id2 GetGlobalCellDimensions() const { return this->GlobalPointDimensions - vtkm::Id2(1); } + VTKM_EXEC_CONT vtkm::Id GetNumberOfPoints() const { return vtkm::ReduceProduct(this->GetPointDimensions()); } @@ -303,12 +324,18 @@ public: void PrintSummary(std::ostream& out) const { out << " UniformConnectivity<2> "; - out << "pointDim[" << this->PointDimensions[0] << " " << this->PointDimensions[1] << "] "; + out << "PointDimensions[" << this->PointDimensions[0] << " " << this->PointDimensions[1] + << "] "; + out << "GlobalPointDimensions[" << this->GlobalPointDimensions[0] << " " + << this->GlobalPointDimensions[1] << "] "; + out << "GlobalPointIndexStart[" << this->GlobalPointIndexStart[0] << " " + << this->GlobalPointIndexStart[1] << "] "; out << std::endl; } private: vtkm::Id2 PointDimensions = { 0, 0 }; + vtkm::Id2 GlobalPointDimensions = { 0, 0 }; vtkm::Id2 GlobalPointIndexStart = { 0, 0 }; }; @@ -327,15 +354,28 @@ public: this->CellDim01 = (dims[0] - 1) * (dims[1] - 1); } + VTKM_EXEC_CONT + void SetGlobalPointDimensions(vtkm::Id3 dims) + { + this->GlobalPointDimensions = dims; + this->GlobalCellDimensions = dims - vtkm::Id3(1); + } + VTKM_EXEC_CONT void SetGlobalPointIndexStart(vtkm::Id3 start) { this->GlobalPointIndexStart = start; } VTKM_EXEC_CONT const vtkm::Id3& GetPointDimensions() const { return this->PointDimensions; } + VTKM_EXEC_CONT + const vtkm::Id3& GetGlobalPointDimensions() const { return this->GlobalPointDimensions; } + VTKM_EXEC_CONT const vtkm::Id3& GetCellDimensions() const { return this->CellDimensions; } + VTKM_EXEC_CONT + const vtkm::Id3& GetGlobalCellDimensions() const { return this->GlobalCellDimensions; } + VTKM_EXEC_CONT vtkm::Id GetNumberOfPoints() const { return vtkm::ReduceProduct(this->PointDimensions); } @@ -466,8 +506,12 @@ public: void PrintSummary(std::ostream& out) const { out << " UniformConnectivity<3> "; - out << "pointDim[" << this->PointDimensions[0] << " " << this->PointDimensions[1] << " " + out << "PointDimensions[" << this->PointDimensions[0] << " " << this->PointDimensions[1] << " " << this->PointDimensions[2] << "] "; + out << "GlobalPointDimensions[" << this->GlobalPointDimensions[0] << " " + << this->GlobalPointDimensions[1] << " " << this->GlobalPointDimensions[2] << "] "; + out << "GlobalPointIndexStart[" << this->GlobalPointIndexStart[0] << " " + << this->GlobalPointIndexStart[1] << " " << this->GlobalPointIndexStart[2] << "] "; out << std::endl; } @@ -509,6 +553,8 @@ public: private: vtkm::Id3 PointDimensions = { 0, 0, 0 }; + vtkm::Id3 GlobalPointDimensions = { 0, 0, 0 }; + vtkm::Id3 GlobalCellDimensions = { 0, 0, 0 }; vtkm::Id3 GlobalPointIndexStart = { 0, 0, 0 }; vtkm::Id3 CellDimensions = { 0, 0, 0 }; vtkm::Id CellDim01 = 0; diff --git a/vtkm/internal/VariantImpl.h b/vtkm/internal/VariantImpl.h index 9ec1d422b..64436e58a 100644 --- a/vtkm/internal/VariantImpl.h +++ b/vtkm/internal/VariantImpl.h @@ -518,7 +518,6 @@ public: template VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) const noexcept(noexcept(f(std::declval&>(), args...))) - -> decltype(f(std::declval&>(), args...)) { VTKM_ASSERT(this->IsValid()); return detail::VariantCastAndCallImpl( @@ -526,9 +525,9 @@ public: } template - VTK_M_DEVICE auto CastAndCall(Functor&& f, Args&&... args) noexcept( - noexcept(f(std::declval&>(), args...))) - -> decltype(f(std::declval&>(), args...)) + VTK_M_DEVICE auto CastAndCall(Functor&& f, + Args&&... args) noexcept(noexcept(f(std::declval&>(), + args...))) { VTKM_ASSERT(this->IsValid()); return detail::VariantCastAndCallImpl( diff --git a/vtkm/worklet/CMakeLists.txt b/vtkm/worklet/CMakeLists.txt index 0183319c1..21f2ff401 100644 --- a/vtkm/worklet/CMakeLists.txt +++ b/vtkm/worklet/CMakeLists.txt @@ -29,7 +29,6 @@ set(headers MaskSelect.h NDimsHistMarginalization.h Normalize.h - ParticleAdvection.h ScalarsToColors.h ScatterCounting.h ScatterIdentity.h @@ -38,7 +37,6 @@ set(headers StableSortIndices.h DescriptiveStatistics.h StreamLineUniformGrid.h - StreamSurface.h TriangleWinding.h WaveletCompressor.h WorkletMapField.h @@ -79,7 +77,6 @@ add_subdirectory(lcs) add_subdirectory(splatkernels) add_subdirectory(spatialstructure) add_subdirectory(wavelets) -add_subdirectory(particleadvection) vtkm_library( NAME vtkm_worklet diff --git a/vtkm/worklet/testing/CMakeLists.txt b/vtkm/worklet/testing/CMakeLists.txt index 759ff5aff..cbc6679b0 100644 --- a/vtkm/worklet/testing/CMakeLists.txt +++ b/vtkm/worklet/testing/CMakeLists.txt @@ -26,7 +26,6 @@ set(unit_tests UnitTestMaskSelect.cxx UnitTestNormalize.cxx UnitTestNDimsHistMarginalization.cxx - UnitTestParticleAdvection.cxx UnitTestScalarsToColors.cxx UnitTestScatterAndMask.cxx UnitTestScatterCounting.cxx @@ -34,8 +33,6 @@ set(unit_tests UnitTestSplatKernels.cxx UnitTestScatterAndMaskWithTopology.cxx UnitTestStreamLineUniformGrid.cxx - UnitTestStreamSurface.cxx - UnitTestTemporalAdvection.cxx UnitTestTriangleWinding.cxx UnitTestWholeCellSetIn.cxx UnitTestWorkletMapField.cxx diff --git a/vtkm/worklet/testing/GenerateTestDataSets.h b/vtkm/worklet/testing/GenerateTestDataSets.h index 2abddcdfa..cbf13d69b 100644 --- a/vtkm/worklet/testing/GenerateTestDataSets.h +++ b/vtkm/worklet/testing/GenerateTestDataSets.h @@ -192,7 +192,10 @@ inline vtkm::cont::DataSet CreateExplicitFromStructuredDataSet(const vtkm::Bound } if (addGhost) - output.AddField(input.GetField("vtkmGhostCells")); + { + output.AddGhostCellField(input.GetGhostCellField()); + } + return output; } diff --git a/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx b/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx index 41e773088..e5c68258f 100644 --- a/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx +++ b/vtkm/worklet/testing/UnitTestContourTreeUniformDistributed.cxx @@ -55,7 +55,6 @@ #include #include -#include #include #include #include @@ -154,7 +153,6 @@ void TestHierarchicalHyperSweeper() "misc/8x9test_HierarchicalAugmentedTree_Block2.dat", "misc/8x9test_HierarchicalAugmentedTree_Block3.dat" }; vtkm::Id3 globalSize{ 9, 8, 1 }; - vtkm::Id3 blocksPerDim{ 2, 2, 1 }; vtkm::Id3 sizes[numBlocks] = { { 5, 4, 1 }, { 5, 5, 1 }, { 5, 4, 1 }, { 5, 5, 1 } }; vtkm::Id3 origins[numBlocks] = { { 0, 0, 0 }, { 0, 3, 0 }, { 4, 0, 0 }, { 4, 3, 0 } }; vtkm::Id3 blockIndices[numBlocks] = { { 0, 0, 0 }, { 0, 1, 0 }, { 1, 0, 0 }, { 1, 1, 0 } }; @@ -174,14 +172,6 @@ void TestHierarchicalHyperSweeper() vtkm::cont::make_ArrayHandle({ 6, 9, 18, 24, 46, 72, 2 }) }; - // Create spatial decomposition - vtkm::filter::scalar_topology::internal::SpatialDecomposition spatialDecomp( - blocksPerDim, - globalSize, - vtkm::cont::make_ArrayHandle(blockIndices, numBlocks, vtkm::CopyFlag::Off), - vtkm::cont::make_ArrayHandle(origins, numBlocks, vtkm::CopyFlag::Off), - vtkm::cont::make_ArrayHandle(sizes, numBlocks, vtkm::CopyFlag::Off)); - // Load trees vtkm::worklet::contourtree_distributed::HierarchicalContourTree hct[numBlocks]; @@ -209,22 +199,21 @@ void TestHierarchicalHyperSweeper() RegularDecomposer::CoordinateVector ghosts(3, 1); RegularDecomposer::DivisionsVector diyDivisions{ 2, 2, 1 }; // HARDCODED FOR TEST - int numDims = static_cast(globalSize[2] > 1 ? 3 : 2); - RegularDecomposer decomposer(numDims, - spatialDecomp.GetVTKmDIYBounds(), - static_cast(spatialDecomp.GetGlobalNumberOfBlocks()), - shareFace, - wrap, - ghosts, - diyDivisions); + int numDims = 2; + vtkmdiy::DiscreteBounds diyBounds(2); + diyBounds.min[0] = diyBounds.min[1] = 0; + diyBounds.max[0] = static_cast(globalSize[0]); + diyBounds.max[1] = static_cast(globalSize[1]); + + RegularDecomposer decomposer( + numDims, diyBounds, numBlocks, shareFace, wrap, ghosts, diyDivisions); // ... coordinates of local blocks - auto localBlockIndicesPortal = spatialDecomp.LocalBlockIndices.ReadPortal(); std::vector vtkmdiyLocalBlockGids(numBlocks); for (vtkm::Id bi = 0; bi < numBlocks; bi++) { RegularDecomposer::DivisionsVector diyCoords(static_cast(numDims)); - auto currentCoords = localBlockIndicesPortal.Get(bi); + auto currentCoords = blockIndices[bi]; for (vtkm::IdComponent d = 0; d < numDims; ++d) { diyCoords[d] = static_cast(currentCoords[d]); @@ -234,8 +223,7 @@ void TestHierarchicalHyperSweeper() } // Define which blocks live on which rank so that vtkmdiy can manage them - vtkmdiy::DynamicAssigner assigner( - comm, comm.size(), static_cast(spatialDecomp.GetGlobalNumberOfBlocks())); + vtkmdiy::DynamicAssigner assigner(comm, comm.size(), numBlocks); for (vtkm::Id bi = 0; bi < numBlocks; bi++) { assigner.set_rank(static_cast(rank),