Commit f78e763b authored by Sujin Philip's avatar Sujin Philip
Browse files

Add CellLocatorGeneral

A general purpose `CellLocator` that should work with any type of dataset.
Internally, it tries to chose one of the existing cell locators that would be
optimal for the input data.

Also removes `CellLocatorHelper`.
parent c6bead83
......@@ -53,7 +53,7 @@ set(headers
BoundsGlobalCompute.h
CellLocator.h
CellLocatorBoundingIntervalHierarchy.h
CellLocatorHelper.h
CellLocatorGeneral.h
CellLocatorRectilinearGrid.h
CellLocatorUniformBins.h
CellLocatorUniformGrid.h
......@@ -155,6 +155,7 @@ set(device_sources
BoundsCompute.cxx
BoundsGlobalCompute.cxx
CellLocatorBoundingIntervalHierarchy.cxx
CellLocatorGeneral.cxx
CellLocatorRectilinearGrid.cxx
CellLocatorUniformBins.cxx
CellLocatorUniformGrid.cxx
......
//============================================================================
// 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 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2019 UT-Battelle, LLC.
// Copyright 2019 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/CellLocatorGeneral.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/CellLocatorRectilinearGrid.h>
#include <vtkm/cont/CellLocatorUniformBins.h>
#include <vtkm/cont/CellLocatorUniformGrid.h>
#include <vtkm/cont/CellSetStructured.h>
namespace
{
VTKM_CONT
void DefaultConfigurator(std::unique_ptr<vtkm::cont::CellLocator>& locator,
const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords)
{
using StructuredCellSet = vtkm::cont::CellSetStructured<3>;
using UniformCoordinates = vtkm::cont::ArrayHandleUniformPointCoordinates;
using RectilinearCoordinates =
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>;
if (cellSet.IsType<StructuredCellSet>() && coords.GetData().IsType<UniformCoordinates>())
{
if (!dynamic_cast<vtkm::cont::CellLocatorUniformGrid*>(locator.get()))
{
locator.reset(new vtkm::cont::CellLocatorUniformGrid);
}
}
else if (cellSet.IsType<StructuredCellSet>() && coords.GetData().IsType<RectilinearCoordinates>())
{
if (!dynamic_cast<vtkm::cont::CellLocatorRectilinearGrid*>(locator.get()))
{
locator.reset(new vtkm::cont::CellLocatorRectilinearGrid);
}
}
else if (!dynamic_cast<vtkm::cont::CellLocatorUniformBins*>(locator.get()))
{
locator.reset(new vtkm::cont::CellLocatorUniformBins);
}
locator->SetCellSet(cellSet);
locator->SetCoordinates(coords);
}
} // anonymous namespace
namespace vtkm
{
namespace cont
{
VTKM_CONT CellLocatorGeneral::CellLocatorGeneral()
: Configurator(DefaultConfigurator)
{
}
VTKM_CONT CellLocatorGeneral::~CellLocatorGeneral() = default;
VTKM_CONT const vtkm::exec::CellLocator* CellLocatorGeneral::PrepareForExecution(
vtkm::cont::DeviceAdapterId device) const
{
if (this->Locator)
{
return this->Locator->PrepareForExecution(device);
}
return nullptr;
}
VTKM_CONT void CellLocatorGeneral::Build()
{
this->Configurator(this->Locator, this->GetCellSet(), this->GetCoordinates());
this->Locator->Update();
}
VTKM_CONT void CellLocatorGeneral::ResetToDefaultConfigurator()
{
this->SetConfigurator(DefaultConfigurator);
}
}
} // vtkm::cont
......@@ -6,9 +6,9 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2019 UT-Battelle, LLC.
// Copyright 2019 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
......@@ -17,50 +17,62 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/CellLocatorHelper.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/testing/Testing.h>
#ifndef vtk_m_cont_CellLocatorGeneral_h
#define vtk_m_cont_CellLocatorGeneral_h
namespace
#include <vtkm/cont/CellLocator.h>
#include <functional>
#include <memory>
namespace vtkm
{
namespace cont
{
void TestCellLocator()
class VTKM_CONT_EXPORT CellLocatorGeneral : public vtkm::cont::CellLocator
{
using PointType = vtkm::Vec<vtkm::FloatDefault, 3>;
public:
VTKM_CONT CellLocatorGeneral();
const vtkm::Id SIZE = 4;
auto ds =
vtkm::cont::DataSetBuilderUniform::Create(vtkm::Id3(SIZE), PointType(0.0f), PointType(1.0f));
VTKM_CONT ~CellLocatorGeneral() override;
vtkm::cont::CellLocatorHelper locator;
locator.SetCellSet(ds.GetCellSet());
locator.SetCoordinates(ds.GetCoordinateSystem());
locator.Build();
/// Get the current underlying cell locator
///
VTKM_CONT const vtkm::cont::CellLocator* GetCurrentLocator() const { return this->Locator.get(); }
PointType points[] = {
{ 0.25, 0.25, 0.25 }, { 1.25, 1.25, 1.25 }, { 2.25, 2.25, 2.25 }, { 3.25, 3.25, 3.25 }
};
/// A configurator can be provided to select an appropriate
/// cell locator implementation and configure its parameters, based on the
/// input cell set and cooridinates.
/// If unset, a resonable default is used.
///
using ConfiguratorSignature = void(std::unique_ptr<vtkm::cont::CellLocator>&,
const vtkm::cont::DynamicCellSet&,
const vtkm::cont::CoordinateSystem&);
vtkm::cont::ArrayHandle<vtkm::Id> cellIds;
vtkm::cont::ArrayHandle<PointType> parametricCoords;
locator.FindCells(vtkm::cont::make_ArrayHandle(points, 4), cellIds, parametricCoords);
VTKM_CONT void SetConfigurator(const std::function<ConfiguratorSignature>& configurator)
{
this->Configurator = configurator;
}
const vtkm::Id NCELLS_PER_AXIS = SIZE - 1;
const vtkm::Id DIA_STRIDE = (NCELLS_PER_AXIS * NCELLS_PER_AXIS) + NCELLS_PER_AXIS + 1;
for (int i = 0; i < 3; ++i)
VTKM_CONT const std::function<ConfiguratorSignature>& GetConfigurator() const
{
VTKM_TEST_ASSERT(cellIds.GetPortalConstControl().Get(i) == (i * DIA_STRIDE),
"Incorrect cell-id value");
VTKM_TEST_ASSERT(parametricCoords.GetPortalConstControl().Get(i) == PointType(0.25f),
"Incorrect parametric coordinate value");
return this->Configurator;
}
VTKM_TEST_ASSERT(cellIds.GetPortalConstControl().Get(3) == -1, "Incorrect cell-id value");
}
} // anonymous namespace
VTKM_CONT void ResetToDefaultConfigurator();
int UnitTestCellLocator(int argc, char* argv[])
{
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
return vtkm::cont::testing::Testing::Run(TestCellLocator, argc, argv);
VTKM_CONT const vtkm::exec::CellLocator* PrepareForExecution(
vtkm::cont::DeviceAdapterId device) const override;
protected:
VTKM_CONT void Build() override;
private:
std::unique_ptr<vtkm::cont::CellLocator> Locator;
std::function<ConfiguratorSignature> Configurator;
};
}
} // vtkm::cont
#endif // vtk_m_cont_CellLocatorGeneral_h
//============================================================================
// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_CellLocatorHelper_h
#define vtk_m_cont_CellLocatorHelper_h
#include <vtkm/cont/CellLocatorUniformBins.h>
#include <vtkm/exec/ParametricCoordinates.h>
namespace vtkm
{
namespace cont
{
class CellLocatorHelper
{
private:
using StructuredCellSetList = vtkm::ListTagBase<vtkm::cont::CellSetStructured<1>,
vtkm::cont::CellSetStructured<2>,
vtkm::cont::CellSetStructured<3>>;
VTKM_CONT static bool IsUniformGrid(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::cont::CoordinateSystem& coordinates)
{
return coordinates.GetData().IsType<vtkm::cont::ArrayHandleUniformPointCoordinates>() &&
(cellset.IsType<vtkm::cont::CellSetStructured<1>>() ||
cellset.IsType<vtkm::cont::CellSetStructured<2>>() ||
cellset.IsType<vtkm::cont::CellSetStructured<3>>());
}
public:
void SetCellSet(const vtkm::cont::DynamicCellSet& cellset) { this->CellSet = cellset; }
const vtkm::cont::DynamicCellSet& GetCellSet() const { return this->CellSet; }
void SetCoordinates(const vtkm::cont::CoordinateSystem& coords) { this->Coordinates = coords; }
const vtkm::cont::CoordinateSystem& GetCoordinates() const { return this->Coordinates; }
/// Builds the cell locator lookup structure
///
void Build()
{
if (IsUniformGrid(this->CellSet, this->Coordinates))
{
// nothing to build for uniform grid
}
else
{
this->Locator.SetCellSet(this->CellSet);
this->Locator.SetCoordinates(this->Coordinates);
this->Locator.Update();
}
}
class FindCellWorklet : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn points,
ExecObject locator,
FieldOut cellIds,
FieldOut pcoords);
using ExecutionSignature = void(_1, _2, _3, _4);
template <typename LocatorType>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::FloatDefault, 3>& point,
const LocatorType& locator,
vtkm::Id& cellId,
vtkm::Vec<vtkm::FloatDefault, 3>& pcoords) const
{
locator->FindCell(point, cellId, pcoords, *this);
}
};
class FindCellWorkletUG : public vtkm::worklet::WorkletMapField
{
private:
template <vtkm::IdComponent DIM>
using ConnectivityType = vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagPoint,
vtkm::TopologyElementTagCell,
DIM>;
public:
using ControlSignature = void(FieldIn points,
WholeCellSetIn<> cellSet,
WholeArrayIn coordinates,
FieldOut cellIds,
FieldOut parametricCoordinates);
using ExecutionSignature = void(_1, _2, _3, _4, _5);
template <typename CoordsPortalType, vtkm::IdComponent DIM>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::FloatDefault, 3>& point,
const ConnectivityType<DIM>& cellset,
const CoordsPortalType& coordinates,
vtkm::Id& cellId,
vtkm::Vec<vtkm::FloatDefault, 3>& pc) const
{
auto coords = coordinates.GetPortal();
static_assert(
std::is_same<decltype(coords), vtkm::internal::ArrayPortalUniformPointCoordinates>::value,
"expecting ArrayHandleUniformPointCoordinates for coordinates");
auto cellId3 = static_cast<vtkm::Id3>((point - coords.GetOrigin()) / coords.GetSpacing());
auto cellDim = vtkm::Max(vtkm::Id3(1), coords.GetDimensions() - vtkm::Id3(1));
if (cellId3[0] < 0 || cellId3[0] >= cellDim[0] || cellId3[1] < 0 ||
cellId3[1] >= cellDim[1] || cellId3[2] < 0 || cellId3[2] >= cellDim[2])
{
cellId = -1;
}
else
{
cellId = cellId3[0] + cellDim[0] * (cellId3[1] + cellDim[1] * cellId3[2]);
auto cellPoints =
vtkm::VecAxisAlignedPointCoordinates<DIM>(coords.Get(cellId3), coords.GetSpacing());
bool success;
pc = vtkm::exec::WorldCoordinatesToParametricCoordinates(
cellPoints, point, cellset.GetCellShape(cellId), success, *this);
VTKM_ASSERT(success);
}
}
};
/// Finds the containing cells for the given array of points. Returns the cell ids
/// in the `cellIds` arrays. If a cell could not be found due to the point being
/// outside all the cells or due to numerical errors, the cell id is set to -1.
/// Parametric coordinates of the point inside the cell is returned in the
/// `parametricCoords` array.
///
template <typename PointComponentType,
typename PointStorageType,
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<vtkm::FloatDefault, 3>>& parametricCoords,
CellSetList cellSetTypes = CellSetList()) const
{
(void)cellSetTypes; // unused for now
if (IsUniformGrid(this->CellSet, this->Coordinates))
{
auto coordinates =
this->Coordinates.GetData().Cast<vtkm::cont::ArrayHandleUniformPointCoordinates>();
auto cellset = this->CellSet.ResetCellSetList(StructuredCellSetList());
vtkm::worklet::DispatcherMapField<FindCellWorkletUG> dispatcher;
dispatcher.Invoke(points, cellset, coordinates, cellIds, parametricCoords);
}
else
{
vtkm::worklet::DispatcherMapField<FindCellWorklet> dispatcher;
dispatcher.Invoke(points, this->Locator, cellIds, parametricCoords);
}
}
private:
vtkm::cont::DynamicCellSet CellSet;
vtkm::cont::CoordinateSystem Coordinates;
vtkm::cont::CellLocatorUniformBins Locator;
};
}
} // vtkm::cont
#endif // vtk_m_cont_CellLocatorHelper_h
......@@ -60,7 +60,7 @@ set(unit_tests
UnitTestArrayHandleVirtual.cxx
UnitTestVariantArrayHandle.cxx
UnitTestArrayPortalToIterators.cxx
UnitTestCellLocator.cxx
UnitTestCellLocatorGeneral.cxx
UnitTestCellSet.cxx
UnitTestCellSetExplicit.cxx
UnitTestCellSetPermutation.cxx
......
//============================================================================
// 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 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/CellLocatorGeneral.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/exec/CellInterpolate.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/ScatterPermutation.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <ctime>
#include <random>
namespace
{
std::default_random_engine RandomGenerator;
using PointType = vtkm::Vec<vtkm::FloatDefault, 3>;
//-----------------------------------------------------------------------------
vtkm::cont::DataSet MakeTestDataSetUniform()
{
return vtkm::cont::DataSetBuilderUniform::Create(
vtkm::Id3{ 64 }, PointType{ -32.0f }, PointType{ 1.0f / 64.0f });
}
vtkm::cont::DataSet MakeTestDataSetRectilinear()
{
std::uniform_real_distribution<vtkm::FloatDefault> coordGen(1.0f / 128.0f, 1.0f / 32.0f);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> coords[3];
for (int i = 0; i < 3; ++i)
{
coords[i].Allocate(64);
auto portal = coords[i].GetPortalControl();
vtkm::FloatDefault cur = 0.0f;
for (vtkm::Id j = 0; j < portal.GetNumberOfValues(); ++j)
{
cur += coordGen(RandomGenerator);
portal.Set(j, cur);
}
}
return vtkm::cont::DataSetBuilderRectilinear::Create(coords[0], coords[1], coords[2]);
}
vtkm::cont::DataSet MakeTestDataSetCurvilinear()
{
auto recti = MakeTestDataSetRectilinear();
auto coords = recti.GetCoordinateSystem().GetData();
vtkm::cont::ArrayHandle<PointType> sheared;
sheared.Allocate(coords.GetNumberOfValues());
auto inPortal = coords.GetPortalConstControl();
auto outPortal = sheared.GetPortalControl();
for (vtkm::Id i = 0; i < inPortal.GetNumberOfValues(); ++i)
{
auto val = inPortal.Get(i);
outPortal.Set(i, val + vtkm::make_Vec(val[1], val[2], val[0]));
}
vtkm::cont::DataSet curvi;
curvi.AddCellSet(recti.GetCellSet());
curvi.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", sheared));
return curvi;
}
//-----------------------------------------------------------------------------
class ParametricToWorldCoordinates : public vtkm::worklet::WorkletMapPointToCell
{
public:
using ControlSignature = void(CellSetIn cellset,
FieldInPoint coords,
FieldInOutCell pcs,
FieldOutCell wcs);
using ExecutionSignature = void(CellShape, _2, _3, _4);
using ScatterType = vtkm::worklet::ScatterPermutation<>;
VTKM_CONT
static ScatterType MakeScatter(const vtkm::cont::ArrayHandle<vtkm::Id>& cellIds)
{
return ScatterType(cellIds);
}
template <typename CellShapeTagType, typename PointsVecType>
VTKM_EXEC void operator()(CellShapeTagType cellShape,
PointsVecType points,
const PointType& pc,
PointType& wc) const
{
wc = vtkm::exec::CellInterpolate(points, pc, cellShape, *this);
}
};
void GenerateRandomInput(const vtkm::cont::DataSet& ds,
vtkm::Id count,
vtkm::cont::ArrayHandle<vtkm::Id>& cellIds,
vtkm::cont::ArrayHandle<PointType>& pcoords,
vtkm::cont::ArrayHandle<PointType>& wcoords)
{
vtkm::Id numberOfCells = ds.GetCellSet().GetNumberOfCells();
std::uniform_int_distribution<vtkm::Id> cellIdGen(0, numberOfCells - 1);
std::uniform_real_distribution<vtkm::FloatDefault> pcoordGen(0.0f, 1.0f);
cellIds.Allocate(count);
pcoords.Allocate(count);
wcoords.Allocate(count);
for (vtkm::Id i = 0; i < count; ++i)
{
cellIds.GetPortalControl().Set(i, cellIdGen(RandomGenerator));
PointType pc{ pcoordGen(RandomGenerator),
pcoordGen(RandomGenerator),
pcoordGen(RandomGenerator) };
pcoords.GetPortalControl().Set(i, pc);
}
vtkm::worklet::DispatcherMapTopology<ParametricToWorldCoordinates> dispatcher(
ParametricToWorldCoordinates::MakeScatter(cellIds));
dispatcher.Invoke(ds.GetCellSet(), ds.GetCoordinateSystem().GetData(), pcoords, wcoords);
}
//-----------------------------------------------------------------------------
class FindCellWorklet : public vtkm::worklet::WorkletMapField
{
public:
using ControlSignature = void(FieldIn points,
ExecObject locator,
FieldOut cellIds,
FieldOut pcoords);
using ExecutionSignature = void(_1, _2, _3, _4);
template <typename LocatorType>
VTKM_EXEC void operator()(const vtkm::Vec<vtkm::FloatDefault, 3>& point,
const LocatorType& locator,
vtkm::Id& cellId,
vtkm::Vec<vtkm::FloatDefault, 3>& pcoords) const
{
locator->FindCell(point, cellId, pcoords, *this);
}
};
void TestWithDataSet(vtkm::cont::CellLocatorGeneral& locator, const vtkm::cont::DataSet& dataset)
{
locator.SetCellSet(dataset.GetCellSet());
locator.SetCoordinates(dataset.GetCoordinateSystem());
locator.Update();
const vtkm::cont::CellLocator& curLoc = *locator.GetCurrentLocator();
std::cout << "using locator: " << typeid(curLoc).name() << "\n";
vtkm::cont::ArrayHandle<vtkm::Id> expCellIds;
vtkm::cont::ArrayHandle<PointType> expPCoords;
vtkm::cont::ArrayHandle<PointType> points;
GenerateRandomInput(dataset, 128, expCellIds, expPCoords, points);