vtk-m/vtkm/worklet/testing/UnitTestParticleAdvection.cxx
Kenneth Moreland c3a3184d51 Update copyright for Sandia
Sandia National Laboratories recently changed management from the
Sandia Corporation to the National Technology & Engineering Solutions
of Sandia, LLC (NTESS). The copyright statements need to be updated
accordingly.
2017-09-20 15:33:44 -06:00

500 lines
22 KiB
C++

//============================================================================
// 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 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 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 <typeinfo>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderRectilinear.h>
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/exec/ExecutionWholeArray.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/GridEvaluators.h>
#include <vtkm/worklet/particleadvection/Integrators.h>
#include <vtkm/worklet/particleadvection/Particles.h>
namespace
{
vtkm::Float32 vecData[125 * 3] = {
-0.00603248f, -0.0966396f, -0.000732792f, 0.000530014f, -0.0986189f, -0.000806706f,
0.00684929f, -0.100098f, -0.000876566f, 0.0129235f, -0.101102f, -0.000942341f,
0.0187515f, -0.101656f, -0.00100401f, 0.0706091f, -0.083023f, -0.00144278f,
0.0736404f, -0.0801616f, -0.00145784f, 0.0765194f, -0.0772063f, -0.00147036f,
0.0792559f, -0.0741751f, -0.00148051f, 0.0818589f, -0.071084f, -0.00148843f,
0.103585f, -0.0342287f, -0.001425f, 0.104472f, -0.0316147f, -0.00140433f,
0.105175f, -0.0291574f, -0.00138057f, 0.105682f, -0.0268808f, -0.00135357f,
0.105985f, -0.0248099f, -0.00132315f, -0.00244603f, -0.0989576f, -0.000821705f,
0.00389525f, -0.100695f, -0.000894513f, 0.00999301f, -0.10193f, -0.000963114f,
0.0158452f, -0.102688f, -0.00102747f, 0.0214509f, -0.102995f, -0.00108757f,
0.0708166f, -0.081799f, -0.00149941f, 0.0736939f, -0.0787879f, -0.00151236f,
0.0764359f, -0.0756944f, -0.00152297f, 0.0790546f, -0.0725352f, -0.00153146f,
0.0815609f, -0.0693255f, -0.001538f, -0.00914287f, -0.104658f, -0.001574f,
-0.00642891f, -0.10239f, -0.00159659f, -0.00402289f, -0.0994835f, -0.00160731f,
-0.00194792f, -0.0959752f, -0.00160528f, -0.00022818f, -0.0919077f, -0.00158957f,
-0.0134913f, -0.0274735f, -9.50056e-05f, -0.0188683f, -0.023273f, 0.000194107f,
-0.0254516f, -0.0197589f, 0.000529693f, -0.0312798f, -0.0179514f, 0.00083619f,
-0.0360426f, -0.0177537f, 0.00110164f, 0.0259929f, -0.0204479f, -0.000304646f,
0.033336f, -0.0157385f, -0.000505569f, 0.0403427f, -0.0104637f, -0.000693529f,
0.0469371f, -0.00477766f, -0.000865609f, 0.0530722f, 0.0011701f, -0.00102f,
-0.0121869f, -0.10317f, -0.0015868f, -0.0096549f, -0.100606f, -0.00160377f,
-0.00743038f, -0.0973796f, -0.00160783f, -0.00553901f, -0.0935261f, -0.00159792f,
-0.00400821f, -0.0890871f, -0.00157287f, -0.0267803f, -0.0165823f, 0.000454173f,
-0.0348303f, -0.011642f, 0.000881271f, -0.0424964f, -0.00870761f, 0.00129226f,
-0.049437f, -0.00781358f, 0.0016728f, -0.0552635f, -0.00888708f, 0.00200659f,
-0.0629746f, -0.0721524f, -0.00160475f, -0.0606813f, -0.0677576f, -0.00158427f,
-0.0582203f, -0.0625009f, -0.00154304f, -0.0555686f, -0.0563905f, -0.00147822f,
-0.0526988f, -0.0494369f, -0.00138643f, 0.0385695f, 0.115704f, 0.00674413f,
0.056434f, 0.128273f, 0.00869052f, 0.0775564f, 0.137275f, 0.0110399f,
0.102515f, 0.140823f, 0.0138637f, 0.131458f, 0.136024f, 0.0171804f,
0.0595175f, -0.0845927f, 0.00512454f, 0.0506615f, -0.0680369f, 0.00376604f,
0.0434904f, -0.0503557f, 0.00261592f, 0.0376711f, -0.0318716f, 0.00163301f,
0.0329454f, -0.0128019f, 0.000785352f, -0.0664062f, -0.0701094f, -0.00160644f,
-0.0641074f, -0.0658893f, -0.00158969f, -0.0616054f, -0.0608302f, -0.00155303f,
-0.0588734f, -0.0549447f, -0.00149385f, -0.0558797f, -0.0482482f, -0.00140906f,
0.0434062f, 0.102969f, 0.00581269f, 0.0619547f, 0.112838f, 0.00742057f,
0.0830229f, 0.118752f, 0.00927516f, 0.106603f, 0.119129f, 0.0113757f,
0.132073f, 0.111946f, 0.0136613f, -0.0135758f, -0.0934604f, -0.000533868f,
-0.00690763f, -0.0958773f, -0.000598878f, -0.000475275f, -0.0977838f, -0.000660985f,
0.00571866f, -0.0992032f, -0.0007201f, 0.0116724f, -0.10016f, -0.000776144f,
0.0651428f, -0.0850475f, -0.00120243f, 0.0682895f, -0.0823666f, -0.00121889f,
0.0712792f, -0.0795772f, -0.00123291f, 0.0741224f, -0.0766981f, -0.00124462f,
0.076829f, -0.0737465f, -0.00125416f, 0.10019f, -0.0375515f, -0.00121866f,
0.101296f, -0.0348723f, -0.00120216f, 0.102235f, -0.0323223f, -0.00118309f,
0.102994f, -0.0299234f, -0.00116131f, 0.103563f, -0.0276989f, -0.0011367f,
-0.00989236f, -0.0958821f, -0.000608883f, -0.00344154f, -0.0980645f, -0.000673641f,
0.00277318f, -0.0997337f, -0.000735354f, 0.00874908f, -0.100914f, -0.000793927f,
0.0144843f, -0.101629f, -0.000849279f, 0.0654428f, -0.0839355f, -0.00125739f,
0.0684225f, -0.0810989f, -0.00127208f, 0.0712599f, -0.0781657f, -0.00128444f,
0.0739678f, -0.0751541f, -0.00129465f, 0.076558f, -0.0720804f, -0.00130286f,
-0.0132841f, -0.103948f, -0.00131159f, -0.010344f, -0.102328f, -0.0013452f,
-0.00768637f, -0.100054f, -0.00136938f, -0.00533293f, -0.0971572f, -0.00138324f,
-0.00330643f, -0.0936735f, -0.00138586f, -0.0116984f, -0.0303752f, -0.000229102f,
-0.0149879f, -0.0265231f, -3.43823e-05f, -0.0212917f, -0.0219544f, 0.000270283f,
-0.0277756f, -0.0186879f, 0.000582781f, -0.0335115f, -0.0171098f, 0.00086919f,
0.0170095f, -0.025299f, -3.73557e-05f, 0.024552f, -0.0214351f, -0.000231975f,
0.0318714f, -0.0168568f, -0.000417463f, 0.0388586f, -0.0117131f, -0.000589883f,
0.0454388f, -0.00615626f, -0.000746594f, -0.0160785f, -0.102675f, -0.00132891f,
-0.0133174f, -0.100785f, -0.00135859f, -0.0108365f, -0.0982184f, -0.00137801f,
-0.00865931f, -0.0950053f, -0.00138614f, -0.00681126f, -0.0911806f, -0.00138185f,
-0.0208973f, -0.0216631f, 0.000111231f, -0.0289373f, -0.0151081f, 0.000512553f,
-0.0368736f, -0.0104306f, 0.000911793f, -0.0444294f, -0.00773838f, 0.00129762f,
-0.0512663f, -0.00706554f, 0.00165611f
};
}
template <typename FieldType>
void RandomPoint(const vtkm::Bounds& bounds, vtkm::Vec<FieldType, 3>& p)
{
FieldType rx = static_cast<FieldType>(rand()) / static_cast<FieldType>(RAND_MAX);
FieldType ry = static_cast<FieldType>(rand()) / static_cast<FieldType>(RAND_MAX);
FieldType rz = static_cast<FieldType>(rand()) / static_cast<FieldType>(RAND_MAX);
p[0] = static_cast<FieldType>(bounds.X.Min + rx * bounds.X.Length());
p[1] = static_cast<FieldType>(bounds.Y.Min + ry * bounds.Y.Length());
p[2] = static_cast<FieldType>(bounds.Z.Min + rz * bounds.Z.Length());
}
template <typename FieldType>
vtkm::cont::DataSet CreateUniformDataSet(const vtkm::Bounds& bounds, const vtkm::Id3& dims)
{
vtkm::Vec<FieldType, 3> origin(static_cast<FieldType>(bounds.X.Min),
static_cast<FieldType>(bounds.Y.Min),
static_cast<FieldType>(bounds.Z.Min));
vtkm::Vec<FieldType, 3> spacing(
static_cast<FieldType>(bounds.X.Length()) / static_cast<FieldType>((dims[0] - 1)),
static_cast<FieldType>(bounds.Y.Length()) / static_cast<FieldType>((dims[1] - 1)),
static_cast<FieldType>(bounds.Z.Length()) / static_cast<FieldType>((dims[2] - 1)));
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
vtkm::cont::DataSet ds = dataSetBuilder.Create(dims, origin, spacing);
return ds;
}
template <typename FieldType>
vtkm::cont::DataSet CreateRectilinearDataSet(const vtkm::Bounds& bounds, const vtkm::Id3& dims)
{
vtkm::cont::DataSetBuilderRectilinear dataSetBuilder;
std::vector<FieldType> xvals, yvals, zvals;
vtkm::Vec<FieldType, 3> spacing(
static_cast<FieldType>(bounds.X.Length()) / static_cast<FieldType>((dims[0] - 1)),
static_cast<FieldType>(bounds.Y.Length()) / static_cast<FieldType>((dims[1] - 1)),
static_cast<FieldType>(bounds.Z.Length()) / static_cast<FieldType>((dims[2] - 1)));
xvals.resize((size_t)dims[0]);
xvals[0] = static_cast<FieldType>(bounds.X.Min);
for (size_t i = 1; i < (size_t)dims[0]; i++)
xvals[i] = xvals[i - 1] + spacing[0];
yvals.resize((size_t)dims[1]);
yvals[0] = static_cast<FieldType>(bounds.Y.Min);
for (size_t i = 1; i < (size_t)dims[1]; i++)
yvals[i] = yvals[i - 1] + spacing[1];
zvals.resize((size_t)dims[2]);
zvals[0] = static_cast<FieldType>(bounds.Z.Min);
for (size_t i = 1; i < (size_t)dims[2]; i++)
zvals[i] = zvals[i - 1] + spacing[2];
vtkm::cont::DataSet ds = dataSetBuilder.Create(xvals, yvals, zvals);
return ds;
}
template <typename FieldType>
void CreateConstantVectorField(vtkm::Id num,
const vtkm::Vec<FieldType, 3>& vec,
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>>& vecField)
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
typedef typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter> DeviceAlgorithm;
vtkm::cont::ArrayHandleConstant<vtkm::Vec<FieldType, 3>> vecConst;
vecConst = vtkm::cont::make_ArrayHandleConstant(vec, num);
DeviceAlgorithm::Copy(vecConst, vecField);
}
template <typename FieldType, typename Evaluator>
class TestEvaluatorWorklet : public vtkm::worklet::WorkletMapField
{
public:
TestEvaluatorWorklet(Evaluator e)
: evaluator(e){};
typedef void ControlSignature(FieldIn<> inputPoint, FieldOut<> validity, FieldOut<> outputPoint);
typedef void ExecutionSignature(_1, _2, _3);
VTKM_EXEC
void operator()(vtkm::Vec<FieldType, 3>& pointIn,
bool& validity,
vtkm::Vec<FieldType, 3>& pointOut) const
{
validity = evaluator.Evaluate(pointIn, pointOut);
}
private:
Evaluator evaluator;
};
template <typename EvalType, typename FieldType>
void ValidateEvaluator(const EvalType& eval,
const std::vector<vtkm::Vec<FieldType, 3>>& pointIns,
const vtkm::Vec<FieldType, 3>& vec,
const std::string& msg)
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
typedef TestEvaluatorWorklet<FieldType, EvalType> EvalTester;
typedef vtkm::worklet::DispatcherMapField<EvalTester> EvalTesterDispatcher;
EvalTester evalTester(eval);
EvalTesterDispatcher evalTesterDispatcher(evalTester);
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> pointsHandle =
vtkm::cont::make_ArrayHandle(pointIns);
vtkm::Id numPoints = pointsHandle.GetNumberOfValues();
pointsHandle.PrepareForInput(DeviceAdapter());
vtkm::cont::ArrayHandle<bool> evalStatus;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> evalResults;
evalStatus.PrepareForOutput(numPoints, DeviceAdapter());
evalResults.PrepareForOutput(numPoints, DeviceAdapter());
evalTesterDispatcher.Invoke(pointsHandle, evalStatus, evalResults);
auto statusPortal = evalStatus.GetPortalConstControl();
auto resultsPortal = evalResults.GetPortalConstControl();
for (vtkm::Id index = 0; index < numPoints; index++)
{
bool status = statusPortal.Get(index);
vtkm::Vec<FieldType, 3> result = resultsPortal.Get(index);
VTKM_TEST_ASSERT(status, "Error in evaluator for " + msg);
VTKM_TEST_ASSERT(result == vec, "Error in evaluator result for " + msg);
}
pointsHandle.ReleaseResources();
evalStatus.ReleaseResources();
evalResults.ReleaseResources();
}
template <typename FieldType, typename Integrator>
class TestIntegratorWorklet : public vtkm::worklet::WorkletMapField
{
public:
TestIntegratorWorklet(Integrator i)
: integrator(i){};
typedef void ControlSignature(FieldIn<> inputPoint, FieldOut<> validity, FieldOut<> outputPoint);
typedef void ExecutionSignature(_1, _2, _3);
VTKM_EXEC
void operator()(vtkm::Vec<FieldType, 3>& pointIn,
vtkm::worklet::particleadvection::ParticleStatus& status,
vtkm::Vec<FieldType, 3>& pointOut) const
{
status = integrator.Step(pointIn, pointOut);
}
private:
Integrator integrator;
};
template <typename IntegratorType, typename FieldType>
void ValidateIntegrator(const IntegratorType& integrator,
const std::vector<vtkm::Vec<FieldType, 3>>& pointIns,
const std::vector<vtkm::Vec<FieldType, 3>>& expStepResults,
const std::string& msg)
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
typedef TestIntegratorWorklet<FieldType, IntegratorType> IntegratorTester;
typedef vtkm::worklet::DispatcherMapField<IntegratorTester> IntegratorTesterDispatcher;
typedef vtkm::worklet::particleadvection::ParticleStatus Status;
IntegratorTester integratorTester(integrator);
IntegratorTesterDispatcher integratorTesterDispatcher(integratorTester);
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> pointsHandle =
vtkm::cont::make_ArrayHandle(pointIns);
vtkm::Id numPoints = pointsHandle.GetNumberOfValues();
pointsHandle.PrepareForInput(DeviceAdapter());
vtkm::cont::ArrayHandle<Status> stepStatus;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> stepResults;
stepStatus.PrepareForOutput(numPoints, DeviceAdapter());
stepResults.PrepareForOutput(numPoints, DeviceAdapter());
integratorTesterDispatcher.Invoke(pointsHandle, stepStatus, stepResults);
auto statusPortal = stepStatus.GetPortalConstControl();
auto resultsPortal = stepResults.GetPortalConstControl();
for (vtkm::Id index = 0; index < numPoints; index++)
{
Status status = statusPortal.Get(index);
vtkm::Vec<FieldType, 3> result = resultsPortal.Get(index);
VTKM_TEST_ASSERT(status == Status::STATUS_OK || status == Status::TERMINATED ||
status == Status::EXITED_SPATIAL_BOUNDARY,
"Error in evaluator for " + msg);
VTKM_TEST_ASSERT(result == expStepResults[(size_t)index],
"Error in evaluator result for " + msg);
}
pointsHandle.ReleaseResources();
stepStatus.ReleaseResources();
stepResults.ReleaseResources();
}
void TestEvaluators()
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
typedef vtkm::Float32 FieldType;
typedef vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> FieldHandle;
typedef FieldHandle::template ExecutionTypes<DeviceAdapter>::PortalConst FieldPortalConstType;
//Constant field evaluator and RK4 integrator.
typedef vtkm::worklet::particleadvection::ConstantField<FieldType> CEvalType;
typedef vtkm::worklet::particleadvection::RK4Integrator<CEvalType, FieldType> RK4CType;
//Uniform grid evaluator and RK4 integrator.
typedef vtkm::worklet::particleadvection::UniformGridEvaluate<FieldPortalConstType,
FieldType,
DeviceAdapter>
UniformEvalType;
typedef vtkm::worklet::particleadvection::RK4Integrator<UniformEvalType, FieldType>
RK4UniformType;
//Rectilinear grid evaluator and RK4 integrator.
typedef vtkm::worklet::particleadvection::RectilinearGridEvaluate<FieldPortalConstType,
FieldType,
DeviceAdapter>
RectilinearEvalType;
typedef vtkm::worklet::particleadvection::RK4Integrator<RectilinearEvalType, FieldType>
RK4RectilinearType;
std::vector<vtkm::Vec<FieldType, 3>> vecs;
vecs.push_back(vtkm::Vec<FieldType, 3>(1, 0, 0));
vecs.push_back(vtkm::Vec<FieldType, 3>(0, 1, 0));
vecs.push_back(vtkm::Vec<FieldType, 3>(0, 0, 1));
vecs.push_back(vtkm::Vec<FieldType, 3>(1, 1, 0));
vecs.push_back(vtkm::Vec<FieldType, 3>(0, 1, 1));
vecs.push_back(vtkm::Vec<FieldType, 3>(1, 0, 1));
vecs.push_back(vtkm::Vec<FieldType, 3>(1, 1, 1));
std::vector<vtkm::Bounds> bounds;
bounds.push_back(vtkm::Bounds(0, 10, 0, 10, 0, 10));
bounds.push_back(vtkm::Bounds(-1, 1, -1, 1, -1, 1));
bounds.push_back(vtkm::Bounds(0, 1, 0, 1, -1, 1));
std::vector<vtkm::Id3> dims;
dims.push_back(vtkm::Id3(5, 5, 5));
dims.push_back(vtkm::Id3(10, 5, 5));
dims.push_back(vtkm::Id3(10, 5, 5));
std::vector<FieldType> steps;
steps.push_back(0.01f);
// steps.push_back(0.05f);
srand(314);
for (std::size_t d = 0; d < dims.size(); d++)
{
vtkm::Id3 dim = dims[d];
for (std::size_t i = 0; i < vecs.size(); i++)
{
vtkm::Vec<FieldType, 3> vec = vecs[i];
for (std::size_t j = 0; j < bounds.size(); j++)
{
//Create uniform and rectilinear data.
vtkm::cont::DataSet uniformData, rectData;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> vecField;
uniformData = CreateUniformDataSet<FieldType>(bounds[j], dim);
rectData = CreateRectilinearDataSet<FieldType>(bounds[j], dim);
CreateConstantVectorField(dim[0] * dim[1] * dim[2], vec, vecField);
for (std::size_t s = 0; s < steps.size(); s++)
{
FieldType stepSize = steps[s];
//Constant vector field evaluator.
CEvalType constEval(bounds[j], vecs[i]);
RK4CType constRK4(constEval, stepSize);
//Uniform vector field evaluator
UniformEvalType uniformEval(
uniformData.GetCoordinateSystem(), uniformData.GetCellSet(0), vecField);
RK4UniformType uniformRK4(uniformEval, stepSize);
//Rectilinear grid evaluator.
RectilinearEvalType rectEval(
rectData.GetCoordinateSystem(), rectData.GetCellSet(0), vecField);
RK4RectilinearType rectRK4(rectEval, stepSize);
std::vector<vtkm::Vec<FieldType, 3>> pointIns;
std::vector<vtkm::Vec<FieldType, 3>> stepResult;
//Create a bunch of random points in the bounds.
for (int k = 0; k < 38; k++)
{
//Generate points 2 steps inside the bounding box.
vtkm::Bounds interiorBounds = bounds[j];
interiorBounds.X.Min += 2 * stepSize;
interiorBounds.Y.Min += 2 * stepSize;
interiorBounds.Z.Min += 2 * stepSize;
interiorBounds.X.Max -= 2 * stepSize;
interiorBounds.Y.Max -= 2 * stepSize;
interiorBounds.Z.Max -= 2 * stepSize;
vtkm::Vec<FieldType, 3> p;
RandomPoint<FieldType>(interiorBounds, p);
pointIns.push_back(p);
stepResult.push_back(p + vec * stepSize);
}
//Test the result for the evaluator
ValidateEvaluator(constEval, pointIns, vec, "constant vector evaluator");
ValidateEvaluator(uniformEval, pointIns, vec, "uniform evaluator");
ValidateEvaluator(rectEval, pointIns, vec, "rectilinear evaluator");
//Test taking one step.
ValidateIntegrator(constRK4, pointIns, stepResult, "constant vector RK4");
ValidateIntegrator(uniformRK4, pointIns, stepResult, "uniform RK4");
ValidateIntegrator(rectRK4, pointIns, stepResult, "rectilinear evaluator");
}
}
}
}
}
void TestParticleWorklets()
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
typedef vtkm::Float32 FieldType;
typedef vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> FieldHandle;
typedef FieldHandle::template ExecutionTypes<DeviceAdapter>::PortalConst FieldPortalConstType;
FieldType stepSize = 0.05f;
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
const vtkm::Id3 dims(5, 5, 5);
vtkm::Id nElements = dims[0] * dims[1] * dims[2] * 3;
std::vector<vtkm::Vec<vtkm::Float32, 3>> field;
for (vtkm::Id i = 0; i < nElements; i++)
{
FieldType x = vecData[i];
FieldType y = vecData[++i];
FieldType z = vecData[++i];
vtkm::Vec<FieldType, 3> vec(x, y, z);
field.push_back(vtkm::Normal(vec));
}
vtkm::cont::DataSet ds = dataSetBuilder.Create(dims);
typedef vtkm::worklet::particleadvection::UniformGridEvaluate<FieldPortalConstType,
FieldType,
DeviceAdapter>
RGEvalType;
typedef vtkm::worklet::particleadvection::RK4Integrator<RGEvalType, FieldType> RK4RGType;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> fieldArray;
fieldArray = vtkm::cont::make_ArrayHandle(field);
RGEvalType eval(ds.GetCoordinateSystem(), ds.GetCellSet(0), fieldArray);
RK4RGType rk4(eval, stepSize);
for (int i = 0; i < 2; i++)
{
std::vector<vtkm::Vec<FieldType, 3>> pts;
pts.push_back(vtkm::Vec<FieldType, 3>(1, 1, 1));
pts.push_back(vtkm::Vec<FieldType, 3>(2, 2, 2));
pts.push_back(vtkm::Vec<FieldType, 3>(3, 3, 3));
vtkm::Id maxSteps = 100;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> seeds;
seeds = vtkm::cont::make_ArrayHandle(pts);
if (i == 0)
{
vtkm::worklet::ParticleAdvection particleAdvection;
vtkm::worklet::ParticleAdvectionResult<FieldType> res;
res = particleAdvection.Run(rk4, seeds, maxSteps, DeviceAdapter());
VTKM_TEST_ASSERT(res.positions.GetNumberOfValues() == seeds.GetNumberOfValues(),
"Number of output particles does not match input.");
}
else if (i == 1)
{
vtkm::worklet::Streamline streamline;
vtkm::worklet::StreamlineResult<FieldType> res;
res = streamline.Run(rk4, seeds, maxSteps, DeviceAdapter());
//Make sure we have the right number of streamlines.
VTKM_TEST_ASSERT(res.polyLines.GetNumberOfCells() == seeds.GetNumberOfValues(),
"Number of output streamlines does not match input.");
//Make sure we have the right number of samples in each streamline.
vtkm::Id nSeeds = static_cast<vtkm::Id>(pts.size());
for (vtkm::Id j = 0; j < nSeeds; j++)
{
vtkm::Id numPoints = static_cast<vtkm::Id>(res.polyLines.GetNumberOfPointsInCell(j));
vtkm::Id numSteps = res.stepsTaken.GetPortalConstControl().Get(j);
VTKM_TEST_ASSERT(numPoints == numSteps, "Invalid number of points in streamline.");
}
}
}
}
void TestParticleAdvection()
{
TestEvaluators();
TestParticleWorklets();
}
int UnitTestParticleAdvection(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestParticleAdvection);
}