add partitioned cell locator

This commit is contained in:
roxana bujack 2022-11-01 11:08:18 +01:00
parent f8e5342e14
commit 25f2ebf026
9 changed files with 338 additions and 0 deletions

@ -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.

@ -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

@ -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 <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/CellLocatorPartitioned.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/exec/CellLocatorPartitioned.h>
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<vtkm::UInt8> ghostArrayHandle;
if (dataset.HasCellField("vtkGhostType"))
{
dataset.GetField("vtkGhostType").GetData().AsArrayHandle(ghostArrayHandle);
}
else
{
vtkm::cont::ArrayCopy(
vtkm::cont::ArrayHandleConstant<vtkm::UInt8>(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

@ -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 <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/exec/CellLocatorPartitioned.h>
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<CellLocatorGeneral> LocatorsCont;
std::vector<vtkm::cont::ArrayHandle<vtkm::UInt8>> GhostsCont;
vtkm::cont::ArrayHandle<vtkm::cont::CellLocatorGeneral::ExecObjType> LocatorsExec;
vtkm::cont::ArrayHandle<vtkm::cont::ArrayHandle<vtkm::UInt8>::ReadPortalType> GhostsExec;
bool Modified = true;
};
} // namespace cont
} //namespace vtkm
#endif //vtkm_cont_CellLocatorPartitioned_h

@ -99,6 +99,7 @@ set(unit_tests_device
UnitTestBitField.cxx
UnitTestCellLocatorChooser.cxx
UnitTestCellLocatorGeneral.cxx
UnitTestCellLocatorPartitioned.cxx
UnitTestCellLocatorRectilinearGrid.cxx
UnitTestCellLocatorTwoLevel.cxx
UnitTestCellLocatorUniformGrid.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 <random>
#include <string>
#include <vtkm/cont/CellLocatorPartitioned.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/source/Amr.h>
#include <vtkm/ErrorCode.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace
{
struct QueryCellsWorklet : public vtkm::worklet::WorkletMapField
{
using ControlSignature = void(FieldIn, ExecObject, FieldOut, FieldOut);
using ExecutionSignature = void(_1, _2, _3, _4);
template <typename PointType, typename CellLocatorExecObjectType>
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<vtkm::Vec3f> 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<vtkm::Id> cellIds;
vtkm::cont::ArrayHandle<vtkm::Id> 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);
}

@ -10,3 +10,5 @@ OPTIONAL_DEPENDS
vtkm_loguru
TEST_OPTIONAL_DEPENDS
vtkm_filter_field_conversion
TEST_DEPENDS
vtkm_source

@ -18,6 +18,7 @@ set(headers
CellInterpolate.h
CellLocatorBoundingIntervalHierarchy.h
CellLocatorMultiplexer.h
CellLocatorPartitioned.h
CellLocatorRectilinearGrid.h
CellLocatorTwoLevel.h
CellLocatorUniformGrid.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 <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CellLocatorGeneral.h>
namespace vtkm
{
namespace exec
{
class VTKM_ALWAYS_EXPORT CellLocatorPartitioned
{
private:
vtkm::cont::ArrayHandle<vtkm::cont::CellLocatorGeneral::ExecObjType>::ReadPortalType Locators;
vtkm::cont::ArrayHandle<vtkm::cont::ArrayHandle<vtkm::UInt8>::ReadPortalType>::ReadPortalType
Ghosts;
public:
VTKM_CONT CellLocatorPartitioned() = default;
VTKM_CONT CellLocatorPartitioned(
const vtkm::cont::ArrayHandle<vtkm::cont::CellLocatorGeneral::ExecObjType>::ReadPortalType&
locators,
vtkm::cont::ArrayHandle<vtkm::cont::ArrayHandle<vtkm::UInt8>::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