Skip to content

Standard API for VTK-m Search Structures

Standard API for VTK-m Search Structures

This issue is the result of the discussion between the U of O, ORNL, LANL, and SNL people to come up with a common interface for the available search structures in VTKm. The current search structures VTK-m supports are

  • Point Locators

  • KD Tree Nearest Neighbor Point Locator

  • Two Level Uniform Grid Nearest Neighbor Point Locator

  • Cell Locators

  • Two Level Uniform Grid Cell Locator

  • Bounding Volume Hierarchy Cell Locator (Rendering specific)

  • Bounding Interval Volume Cell Locator (yet to be merged)

The following desired properties for the Search Structure were discussed

  • Support for a common interface for users to Build the Search Structures. This can be done by having a interface with some virtual methods that the deriving classes could implement.
  • Support for a common interface for users to find point/cells in the Search Structures.
    • Batch searches from the Control Environment
    • Support for look-ups in an Execution Environment This need the structure to maintain a ExecutionObject

Also does VTKm need separate interfaces for Point and Cell Locators? For now I'll go ahead with Yes.

Following is what Manish and I came up with for the interface for a Cell Locator. Again, this might not be the final, but something to get us started.

Cell Locator Interface

template<typename DerivedLocator>
class CellLocator
{
public:

  CellLocator() = default;

  vtkm::cont::DynamicCellSet GetCellSet() const;
  void SetCellSet(const vtkm::cont::DynamicCellSet& cellSet);

  vtkm::cont::CoordinateSystem GetCoords() const;
  void SetCoords(const vtkm::cont::CoordinateSystem& coords);

  // This method was added to address Matt's input of having a method
  //  that will that sets the data and creates a tree.
  template<typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
  void Build(const vtkm::cont::DynamicCellSet& cellSet,
             const vtkm::cont::CoordinateSystem& coords,
             CellSetList cellSetTypes = CellSetList())
  {
    SetCellSet(cellSet);
    SetCoords(coords);
    // Call CellLocator::Build(DeviceAdapter, ...) wrapped around a TryExecute
  }

  template<typename DeviceAdapter, typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
  void Build(DeviceAdapter, CellSetList cellSetTypes = CellSetList())
  {
    GetDerived()->Build(DeviceAdapter(), cellSetTypes);
  }

  template<typename PointComponentType,
           typename PointStorageType,
           typename ParametricCoordType,
           typename DeviceAdapter,
           typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
  void FindCells(
    const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& points,
    vtkm::cont::ArrayHandle<vtkm::Id>& cellIds,
    vtkm::cont::ArrayHandle<vtkm::Vec<ParametricCoordType, 3>>& parametricCoords,
    DeviceAdapter,
    CellSetList cellSetTypes = CellSetList()) const
  {
    GetDerived()->FindCells(points, cellIds, parametricCoords, DeviceAdapter(), cellSetTypes);
  }

  template<typename DeviceAdapter, typename... ExecArgs>
  typename DerivedLocator::ExecutionObjectType<DeviceAdapter,... ExecArgs>
    PrepareForExecution(DeviceAdapter, ExecArgs... args) const
  {
    return GetDerived()->GetExecutionObjectFactory().PrepareForDevice(DeviceAdapter, args...);
  }

protected:
  virtual typename DerivedLocator::ExecutionObjectFactoryType GetExecutionObjectFactory() = 0;

  vtkm::cont::DynamicCellSet CellSet;
  vtkm::cont::CoordinateSystem Coordinates;

private:
  Derived* GetDerived() const
  {
    return static_cast<Derived*>(this);
  }
};

class CellLocatorExecutionObject {
public:
  template<typename PointComponentType,
           typename ParametricCoordType>
  virtual void FindCell(
    const vtkm::Vec<PointComponentType, 3>& point,
    vtkm::Id& cellId,
    vtkm::Vec<ParametricCoordType, 3>& parametricCoords) const = 0;
};

And, following is what we came up with for the interface for a Point Locator.

Point Locator Interface

te<typename DerievedLocator>
class PointLocator
{
public:
  PointLocator() = default;

  vtkm::cont::CoordinateSystem GetCoords() const;

  void SetCoords(const vtkm::cont::CoordinateSystem& coords);

  template<typename DeviceAdapter>
  void Build(const vtkm::cont::CoordinateSystem& coords)
  {
    SetCoords(coords);
    // Call PointLocator::Build(DeviceAdapter, ...) wrapped around a TryExecute
  }

  template<typename DeviceAdapter>
  void Build(DeviceAdapter)
  {
    GetDerived()->Build(DeviceAdapter());
  }

  template<typename PointComponentType,
           typename PointStorageType,
           typename DeviceAdapter>
  void FindNearestNeighbors(
    const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& queryPoints,
    vtkm::cont::ArrayHandle<vtkm::Id>& nearestNeighborIds,
    vtkm::cont::ArrayHandle<PointComponentType> distances,
    DeviceAdapter) const
  {
    GetDerived()->FindNearestNeighbors(queryPoints, nearestNeighborIds, distances, DeviceAdapter());
  }

  template<typename DeviceAdapter, typename... ExecArgs>
  typename DerivedLocator::ExecutionObjectType<DeviceAdapter,... ExecArgs>
    PrepareForExecution(DeviceAdapter, ExecArgs... args)
  {
    return GetDerived()->GetExecutionObjectFactory().PrepareForDevice(DeviceAdapter, args...);
  }

protected:
  virtual typename DerivedLocator::ExecutionObjectFactoryType GetExecutionObjectFactory() = 0;

protected:
  vtkm::cont::CoordinateSystem coordinates;
  vtkm::cont::ExecutionObjectFactoryBase executionObject;

private:
  Derived* GetDerived()
  {
    return static_cast<Derived*>(this);
  }
};

class PointLocatorExecutionObject {
public:
  template<typename PointComponentType>
  virtual void FindNearestNeighbor(
    const vtkm::Vec<PointComponentType, 3>& point,
    vtkm::Id& nearestNeighborId,
    PointComponentType& distance) const = 0;
};

Any deriving cell locator or point locator needs to provide two typedefs, along with implementing all virtual methods;

class DerivedLocator : public CellLocator {

public:
using ExecutionObjectType = ...;
using ExecutionObjectFactoryType = ...;

};
Edited by Abhishek Yenpure