From 25f2ebf02693bb7f2ac00f08e96cd46783260c49 Mon Sep 17 00:00:00 2001 From: roxana bujack Date: Tue, 1 Nov 2022 11:08:18 +0100 Subject: [PATCH] add partitioned cell locator --- docs/changelog/partitioned-cell-locator.md | 14 +++ vtkm/cont/CMakeLists.txt | 2 + vtkm/cont/CellLocatorPartitioned.cxx | 87 ++++++++++++++++++ vtkm/cont/CellLocatorPartitioned.h | 58 ++++++++++++ vtkm/cont/testing/CMakeLists.txt | 1 + .../UnitTestCellLocatorPartitioned.cxx | 91 +++++++++++++++++++ vtkm/cont/vtkm.module | 2 + vtkm/exec/CMakeLists.txt | 1 + vtkm/exec/CellLocatorPartitioned.h | 82 +++++++++++++++++ 9 files changed, 338 insertions(+) create mode 100644 docs/changelog/partitioned-cell-locator.md create mode 100644 vtkm/cont/CellLocatorPartitioned.cxx create mode 100644 vtkm/cont/CellLocatorPartitioned.h create mode 100644 vtkm/cont/testing/UnitTestCellLocatorPartitioned.cxx create mode 100644 vtkm/exec/CellLocatorPartitioned.h diff --git a/docs/changelog/partitioned-cell-locator.md b/docs/changelog/partitioned-cell-locator.md new file mode 100644 index 000000000..365fe9cf5 --- /dev/null +++ b/docs/changelog/partitioned-cell-locator.md @@ -0,0 +1,14 @@ +# New partitioned cell locator class + +A new version of a locator, `CellLocatorParitioned`, is now available. This version of a +locator takes a `PartitionedDataSet` and builds a structure that will find the partition Ids and +cell Ids for the input array of locations. It runs CellLocatorGeneral for each partition. We +expect multiple hits and only return the first one (lowest partition Id) where the detected cell +is of type REGULAR (no ghost, not blanked) in the vtkGhostType array. If this array does not +exist in a partition, we assume that all cells are regular. + +vtkm::cont::CellLocatorPartitioned produces an Arrayhandle of the size of the number of +partitions filled with the execution objects of CellLocatorGeneral. It further produces an +Arrayhandle filled with the ReadPortals of the vtkGhost arrays to then select the non-blanked +cells from the potentially multiple detected cells on the different partitions. Its counterpart +on the exec side, vtkm::exec::CellLocatorPartitioned, contains the actual FindCell function. diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index 84f9ab0a0..78ebe6aba 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -59,6 +59,7 @@ set(headers CellLocatorBoundingIntervalHierarchy.h CellLocatorChooser.h CellLocatorGeneral.h + CellLocatorPartitioned.h CellLocatorRectilinearGrid.h CellLocatorTwoLevel.h CellLocatorUniformBins.h @@ -147,6 +148,7 @@ set(sources BoundsCompute.cxx BoundsGlobalCompute.cxx CellLocatorGeneral.cxx + CellLocatorPartitioned.cxx CellLocatorRectilinearGrid.cxx CellLocatorUniformGrid.cxx CellSet.cxx diff --git a/vtkm/cont/CellLocatorPartitioned.cxx b/vtkm/cont/CellLocatorPartitioned.cxx new file mode 100644 index 000000000..6993d5729 --- /dev/null +++ b/vtkm/cont/CellLocatorPartitioned.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 +#include + +namespace vtkm +{ +namespace cont +{ + +void CellLocatorPartitioned::Update() +{ + if (this->Modified) + { + this->Build(); + this->Modified = false; + } +} + + +void CellLocatorPartitioned::Build() +{ + vtkm::Id numPartitions = this->Partitions.GetNumberOfPartitions(); + this->LocatorsCont.resize(numPartitions); + this->GhostsCont.resize(numPartitions); + for (vtkm::Id index = 0; index < numPartitions; ++index) + { + const vtkm::cont::DataSet& dataset = this->Partitions.GetPartition(index); + + // fill vector of cellLocators + vtkm::cont::CellLocatorGeneral cellLocator; + cellLocator.SetCellSet(dataset.GetCellSet()); + cellLocator.SetCoordinates(dataset.GetCoordinateSystem()); + cellLocator.Update(); + this->LocatorsCont.at(index) = cellLocator; + + // fill vector of ghostFields + vtkm::cont::ArrayHandle ghostArrayHandle; + if (dataset.HasCellField("vtkGhostType")) + { + dataset.GetField("vtkGhostType").GetData().AsArrayHandle(ghostArrayHandle); + } + else + { + vtkm::cont::ArrayCopy( + vtkm::cont::ArrayHandleConstant(0, dataset.GetNumberOfCells()), + ghostArrayHandle); + } + this->GhostsCont.at(index) = ghostArrayHandle; + } +} + +const vtkm::exec::CellLocatorPartitioned CellLocatorPartitioned::PrepareForExecution( + vtkm::cont::DeviceAdapterId device, + vtkm::cont::Token& token) +{ + this->Update(); + + vtkm::Id numPartitions = this->Partitions.GetNumberOfPartitions(); + this->LocatorsExec.Allocate(numPartitions, vtkm::CopyFlag::Off); + auto portalLocators = this->LocatorsExec.WritePortal(); + this->GhostsExec.Allocate(numPartitions, vtkm::CopyFlag::Off); + auto portalGhosts = this->GhostsExec.WritePortal(); + for (vtkm::Id index = 0; index < numPartitions; ++index) + { + // fill arrayhandle of cellLocators + portalLocators.Set(index, this->LocatorsCont.at(index).PrepareForExecution(device, token)); + + // fill arrayhandle of ghostFields + portalGhosts.Set(index, this->GhostsCont.at(index).PrepareForInput(device, token)); + } + return vtkm::exec::CellLocatorPartitioned(this->LocatorsExec.PrepareForInput(device, token), + this->GhostsExec.PrepareForInput(device, token)); +} + +} // namespace cont +} //namespace vtkm diff --git a/vtkm/cont/CellLocatorPartitioned.h b/vtkm/cont/CellLocatorPartitioned.h new file mode 100644 index 000000000..ebce9b29a --- /dev/null +++ b/vtkm/cont/CellLocatorPartitioned.h @@ -0,0 +1,58 @@ +//============================================================================ +// 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 vtkm_cont_CellLocatorPartitioned_h +#define vtkm_cont_CellLocatorPartitioned_h + +#include +#include +#include + +namespace vtkm +{ +namespace cont +{ +class VTKM_CONT_EXPORT CellLocatorPartitioned : public vtkm::cont::ExecutionObjectBase +{ + +public: + virtual ~CellLocatorPartitioned() = default; + + VTKM_CONT CellLocatorPartitioned() = default; + + void SetPartitions(const vtkm::cont::PartitionedDataSet& partitions) + { + this->Partitions = partitions; + this->SetModified(); + } + const vtkm::cont::PartitionedDataSet& GetPartitions() const { return this->Partitions; } + + void Update(); + + void SetModified() { this->Modified = true; } + bool GetModified() const { return this->Modified; } + + void Build(); + + VTKM_CONT const vtkm::exec::CellLocatorPartitioned PrepareForExecution( + vtkm::cont::DeviceAdapterId device, + vtkm::cont::Token& token); + +private: + vtkm::cont::PartitionedDataSet Partitions; + std::vector LocatorsCont; + std::vector> GhostsCont; + vtkm::cont::ArrayHandle LocatorsExec; + vtkm::cont::ArrayHandle::ReadPortalType> GhostsExec; + bool Modified = true; +}; +} // namespace cont +} //namespace vtkm + +#endif //vtkm_cont_CellLocatorPartitioned_h diff --git a/vtkm/cont/testing/CMakeLists.txt b/vtkm/cont/testing/CMakeLists.txt index 59c464f03..8c6a31fe0 100644 --- a/vtkm/cont/testing/CMakeLists.txt +++ b/vtkm/cont/testing/CMakeLists.txt @@ -99,6 +99,7 @@ set(unit_tests_device UnitTestBitField.cxx UnitTestCellLocatorChooser.cxx UnitTestCellLocatorGeneral.cxx + UnitTestCellLocatorPartitioned.cxx UnitTestCellLocatorRectilinearGrid.cxx UnitTestCellLocatorTwoLevel.cxx UnitTestCellLocatorUniformGrid.cxx diff --git a/vtkm/cont/testing/UnitTestCellLocatorPartitioned.cxx b/vtkm/cont/testing/UnitTestCellLocatorPartitioned.cxx new file mode 100644 index 000000000..c7102c0d5 --- /dev/null +++ b/vtkm/cont/testing/UnitTestCellLocatorPartitioned.cxx @@ -0,0 +1,91 @@ + +//============================================================================ +// 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 +{ +struct QueryCellsWorklet : public vtkm::worklet::WorkletMapField +{ + using ControlSignature = void(FieldIn, ExecObject, FieldOut, FieldOut); + using ExecutionSignature = void(_1, _2, _3, _4); + + template + VTKM_EXEC void operator()(const PointType& point, + const CellLocatorExecObjectType& cellLocator, + vtkm::Id& cellId, + vtkm::Id& partitionId) const + { + vtkm::Vec3f parametric; + vtkm::ErrorCode status = cellLocator.FindCell(point, partitionId, cellId, parametric); + if (status != vtkm::ErrorCode::Success) + { + this->RaiseError(vtkm ::ErrorString(status)); + partitionId = -1; + cellId = -1; + } + } +}; + +void Test() +{ + int dim = 3; + int numberOfLevels = 3; + int cellsPerDimension = 8; + + // Generate AMR + vtkm::source::Amr source(dim, cellsPerDimension, numberOfLevels); + vtkm::cont::PartitionedDataSet amrDataSet = source.Execute(); + + // one point for each partition + vtkm::cont::ArrayHandle queryPoints; + queryPoints.Allocate(7); + queryPoints.WritePortal().Set(0, vtkm::Vec3f(0.1f, 0.9f, 0.1f)); + queryPoints.WritePortal().Set(1, vtkm::Vec3f(0.1f, 0.4f, 0.4f)); + queryPoints.WritePortal().Set(2, vtkm::Vec3f(0.8f, 0.5f, 0.5f)); + queryPoints.WritePortal().Set(3, vtkm::Vec3f(0.0f)); + queryPoints.WritePortal().Set(4, vtkm::Vec3f(0.4999999f)); + queryPoints.WritePortal().Set(5, vtkm::Vec3f(0.5000001f)); + queryPoints.WritePortal().Set(6, vtkm::Vec3f(1.0f)); + + // generate cellLocator on cont side + vtkm::cont::CellLocatorPartitioned cellLocator; + cellLocator.SetPartitions(amrDataSet); + cellLocator.Update(); + vtkm::cont::ArrayHandle cellIds; + vtkm::cont::ArrayHandle partitionIds; + vtkm::cont::Invoker invoke; + invoke(QueryCellsWorklet{}, queryPoints, &cellLocator, cellIds, partitionIds); + + for (vtkm::Id index = 0; index < queryPoints.GetNumberOfValues(); ++index) + { + VTKM_TEST_ASSERT(partitionIds.ReadPortal().Get(index) == index, "Incorrect partitionId"); + } +} + +} // anonymous namespace + +int UnitTestCellLocatorPartitioned(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(Test, argc, argv); +} diff --git a/vtkm/cont/vtkm.module b/vtkm/cont/vtkm.module index 39e9c8a47..33396e7ae 100644 --- a/vtkm/cont/vtkm.module +++ b/vtkm/cont/vtkm.module @@ -10,3 +10,5 @@ OPTIONAL_DEPENDS vtkm_loguru TEST_OPTIONAL_DEPENDS vtkm_filter_field_conversion +TEST_DEPENDS + vtkm_source diff --git a/vtkm/exec/CMakeLists.txt b/vtkm/exec/CMakeLists.txt index 450648cef..be120be3c 100644 --- a/vtkm/exec/CMakeLists.txt +++ b/vtkm/exec/CMakeLists.txt @@ -18,6 +18,7 @@ set(headers CellInterpolate.h CellLocatorBoundingIntervalHierarchy.h CellLocatorMultiplexer.h + CellLocatorPartitioned.h CellLocatorRectilinearGrid.h CellLocatorTwoLevel.h CellLocatorUniformGrid.h diff --git a/vtkm/exec/CellLocatorPartitioned.h b/vtkm/exec/CellLocatorPartitioned.h new file mode 100644 index 000000000..c89ce8149 --- /dev/null +++ b/vtkm/exec/CellLocatorPartitioned.h @@ -0,0 +1,82 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//============================================================================ +#ifndef vtk_m_exec_CellLocatorPartitioned_h +#define vtk_m_exec_CellLocatorPartitioned_h + +#include +#include +#include + +namespace vtkm +{ +namespace exec +{ +class VTKM_ALWAYS_EXPORT CellLocatorPartitioned +{ +private: + vtkm::cont::ArrayHandle::ReadPortalType Locators; + vtkm::cont::ArrayHandle::ReadPortalType>::ReadPortalType + Ghosts; + +public: + VTKM_CONT CellLocatorPartitioned() = default; + VTKM_CONT CellLocatorPartitioned( + const vtkm::cont::ArrayHandle::ReadPortalType& + locators, + vtkm::cont::ArrayHandle::ReadPortalType>::ReadPortalType + ghosts) + : Locators(locators) + , Ghosts(ghosts) + { + } + + VTKM_EXEC + vtkm::ErrorCode FindCell(const vtkm::Vec3f& point, + vtkm::Id& partitionId, + vtkm::Id& cellId, + vtkm::Vec3f& parametric) const + { + bool found = 0; + for (vtkm::Id partitionIndex = 0; partitionIndex < this->Locators.GetNumberOfValues(); + ++partitionIndex) + { + vtkm::Id cellIndex; + vtkm ::Vec3f parametricLocal; + vtkm ::ErrorCode status = + Locators.Get(partitionIndex).FindCell(point, cellIndex, parametricLocal); + if (status != vtkm ::ErrorCode ::Success) + { + } + else + { + if (Ghosts.Get(partitionIndex).Get(cellIndex) == 0) + { + partitionId = partitionIndex; + cellId = cellIndex; + parametric = parametricLocal; + found = true; + break; + } + } + } + if (found) + { + return vtkm::ErrorCode::Success; + } + else + { + return vtkm::ErrorCode::CellNotFound; + } + } +}; +} //namespace exec +} //namespace vtkm + +#endif //vtk_m_exec_CellLocatorPartitioned_h