vtk-m2/vtkm/cont/testing/TestingCellLocatorUniformGrid.h

175 lines
6.2 KiB
C
Raw Normal View History

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
2019-04-15 23:24:21 +00:00
//
// 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_cont_testing_TestingCellLocatorUniformGrid_h
#define vtk_m_cont_testing_TestingCellLocatorUniformGrid_h
#include <random>
#include <string>
#include <vtkm/cont/CellLocatorUniformGrid.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/exec/CellLocatorUniformGrid.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
class LocatorWorklet : public vtkm::worklet::WorkletMapField
{
public:
LocatorWorklet(vtkm::Bounds& bounds, vtkm::Id3& cellDims)
: Bounds(bounds)
, CellDims(cellDims)
{
}
using ControlSignature =
void(FieldIn pointIn, ExecObject locator, FieldOut cellId, FieldOut parametric, FieldOut match);
using ExecutionSignature = void(_1, _2, _3, _4, _5);
template <typename PointType>
VTKM_EXEC vtkm::Id CalculateCellId(const PointType& point) const
{
if (!Bounds.Contains(point))
return -1;
vtkm::Id3 logical;
logical[0] = (point[0] == Bounds.X.Max)
? CellDims[0] - 1
: static_cast<vtkm::Id>(vtkm::Floor((point[0] / Bounds.X.Length()) *
static_cast<vtkm::FloatDefault>(CellDims[0])));
logical[1] = (point[1] == Bounds.Y.Max)
? CellDims[1] - 1
: static_cast<vtkm::Id>(vtkm::Floor((point[1] / Bounds.Y.Length()) *
static_cast<vtkm::FloatDefault>(CellDims[1])));
logical[2] = (point[2] == Bounds.Z.Max)
? CellDims[2] - 1
: static_cast<vtkm::Id>(vtkm::Floor((point[2] / Bounds.Z.Length()) *
static_cast<vtkm::FloatDefault>(CellDims[2])));
return logical[2] * CellDims[0] * CellDims[1] + logical[1] * CellDims[0] + logical[0];
}
template <typename PointType, typename LocatorType>
VTKM_EXEC void operator()(const PointType& pointIn,
const LocatorType& locator,
vtkm::Id& cellId,
PointType& parametric,
bool& match) const
{
vtkm::Id calculated = CalculateCellId(pointIn);
vtkm::ErrorCode status = locator.FindCell(pointIn, cellId, parametric);
if ((status != vtkm::ErrorCode::Success) && (status != vtkm::ErrorCode::CellNotFound))
{
this->RaiseError(vtkm::ErrorString(status));
match = false;
return;
}
match = (calculated == cellId);
}
private:
vtkm::Bounds Bounds;
vtkm::Id3 CellDims;
};
template <typename DeviceAdapter>
class TestingCellLocatorUniformGrid
{
public:
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
void TestTest() const
{
vtkm::cont::DataSet dataset = vtkm::cont::testing::MakeTestDataSet().Make3DUniformDataSet1();
vtkm::cont::CoordinateSystem coords = dataset.GetCoordinateSystem();
vtkm::cont::DynamicCellSet cellSet = dataset.GetCellSet();
vtkm::Bounds bounds = coords.GetBounds();
std::cout << "X bounds : " << bounds.X.Min << " to " << bounds.X.Max << std::endl;
std::cout << "Y bounds : " << bounds.Y.Min << " to " << bounds.Y.Max << std::endl;
std::cout << "Z bounds : " << bounds.Z.Min << " to " << bounds.Z.Max << std::endl;
using StructuredType = vtkm::cont::CellSetStructured<3>;
vtkm::Id3 cellDims =
cellSet.Cast<StructuredType>().GetSchedulingRange(vtkm::TopologyElementTagCell());
std::cout << "Dimensions of dataset : " << cellDims << std::endl;
vtkm::cont::CellLocatorUniformGrid locator;
locator.SetCoordinates(coords);
locator.SetCellSet(cellSet);
locator.Update();
// Generate some sample points.
using PointType = vtkm::Vec3f;
std::vector<PointType> pointsVec;
std::default_random_engine dre;
std::uniform_real_distribution<vtkm::Float32> inBounds(0.0f, 4.0f);
for (size_t i = 0; i < 10; i++)
{
PointType point = vtkm::make_Vec(inBounds(dre), inBounds(dre), inBounds(dre));
pointsVec.push_back(point);
}
std::uniform_real_distribution<vtkm::Float32> outBounds(4.0f, 5.0f);
for (size_t i = 0; i < 5; i++)
{
PointType point = vtkm::make_Vec(outBounds(dre), outBounds(dre), outBounds(dre));
pointsVec.push_back(point);
}
std::uniform_real_distribution<vtkm::Float32> outBounds2(-1.0f, 0.0f);
for (size_t i = 0; i < 5; i++)
{
PointType point = vtkm::make_Vec(outBounds2(dre), outBounds2(dre), outBounds2(dre));
pointsVec.push_back(point);
}
// Add points right on the boundary.
pointsVec.push_back(vtkm::make_Vec(0, 0, 0));
pointsVec.push_back(vtkm::make_Vec(4, 4, 4));
pointsVec.push_back(vtkm::make_Vec(4, 0, 0));
pointsVec.push_back(vtkm::make_Vec(0, 4, 0));
pointsVec.push_back(vtkm::make_Vec(0, 0, 4));
pointsVec.push_back(vtkm::make_Vec(4, 4, 0));
pointsVec.push_back(vtkm::make_Vec(0, 4, 4));
pointsVec.push_back(vtkm::make_Vec(4, 0, 4));
Improvements to moving data into ArrayHandle We have made several improvements to adding data into an `ArrayHandle`. ## Moving data from an `std::vector` For numerous reasons, it is convenient to define data in a `std::vector` and then wrap that into an `ArrayHandle`. It is often the case that an `std::vector` is filled and then becomes unused once it is converted to an `ArrayHandle`. In this case, what we really want is to pass the data off to the `ArrayHandle` so that the `ArrayHandle` is now managing the data and not the `std::vector`. C++11 has a mechanism to do this: move semantics. You can now pass variables to functions as an "rvalue" (right-hand value). When something is passed as an rvalue, it can pull state out of that variable and move it somewhere else. `std::vector` implements this movement so that an rvalue can be moved to another `std::vector` without actually copying the data. `make_ArrayHandle` now also takes advantage of this feature to move rvalue `std::vector`s. There is a special form of `make_ArrayHandle` named `make_ArrayHandleMove` that takes an rvalue. There is also a special overload of `make_ArrayHandle` itself that handles an rvalue `vector`. (However, using the explicit move version is better if you want to make sure the data is actually moved.) ## Make `ArrayHandle` from initalizer list A common use case for using `std::vector` (particularly in our unit tests) is to quickly add an initalizer list into an `ArrayHandle`. Now you can by simply passing an initializer list to `make_ArrayHandle`. ## Deprecated `make_ArrayHandle` with default shallow copy For historical reasons, passing an `std::vector` or a pointer to `make_ArrayHandle` does a shallow copy (i.e. `CopyFlag` defaults to `Off`). Although more efficient, this mode is inherintly unsafe, and making it the default is asking for trouble. To combat this, calling `make_ArrayHandle` without a copy flag is deprecated. In this way, if you wish to do the faster but more unsafe creation of an `ArrayHandle` you should explicitly express that. This requried quite a few changes through the VTK-m source (particularly in the tests). ## Similar changes to `Field` `vtkm::cont::Field` has a `make_Field` helper function that is similar to `make_ArrayHandle`. It also features the ability to create fields from `std::vector`s and C arrays. It also likewise had the same unsafe behavior by default of not copying from the source of the arrays. That behavior has similarly been depreciated. You now have to specify a copy flag. The ability to construct a `Field` from an initializer list of values has also been added.
2020-07-16 16:32:32 +00:00
vtkm::cont::ArrayHandle<PointType> points =
vtkm::cont::make_ArrayHandle(pointsVec, vtkm::CopyFlag::Off);
// Query the points using the locators.
vtkm::cont::ArrayHandle<vtkm::Id> cellIds;
vtkm::cont::ArrayHandle<PointType> parametric;
vtkm::cont::ArrayHandle<bool> match;
LocatorWorklet worklet(bounds, cellDims);
2018-08-30 17:19:00 +00:00
vtkm::worklet::DispatcherMapField<LocatorWorklet> dispatcher(worklet);
dispatcher.SetDevice(DeviceAdapter());
dispatcher.Invoke(points, locator, cellIds, parametric, match);
auto matchPortal = match.ReadPortal();
for (vtkm::Id index = 0; index < match.GetNumberOfValues(); index++)
{
VTKM_TEST_ASSERT(matchPortal.Get(index), "Points do not match");
}
std::cout << "Test finished successfully." << std::endl;
}
void operator()() const
{
vtkm::cont::GetRuntimeDeviceTracker().ForceDevice(DeviceAdapter());
this->TestTest();
}
};
#endif