diff --git a/vtkm/filter/flow/CMakeLists.txt b/vtkm/filter/flow/CMakeLists.txt index 961830490..ffbc522ad 100644 --- a/vtkm/filter/flow/CMakeLists.txt +++ b/vtkm/filter/flow/CMakeLists.txt @@ -29,6 +29,7 @@ set(flow_sources ) set(flow_device_sources + worklet/Analysis.cxx Lagrangian.cxx LagrangianStructures.cxx FilterParticleAdvectionSteadyState.cxx diff --git a/vtkm/filter/flow/testing/CMakeLists.txt b/vtkm/filter/flow/testing/CMakeLists.txt index efd06d577..b8bbaa7d2 100644 --- a/vtkm/filter/flow/testing/CMakeLists.txt +++ b/vtkm/filter/flow/testing/CMakeLists.txt @@ -28,7 +28,7 @@ if (TARGET vtkm_rendering_testing) endif() vtkm_unit_tests( - DEVICE_SOURCES ${filter_unit_tests} + SOURCES ${filter_unit_tests} DEVICE_SOURCES ${worklet_unit_tests} USE_VTKM_JOB_POOL ) diff --git a/vtkm/filter/flow/worklet/Analysis.cxx b/vtkm/filter/flow/worklet/Analysis.cxx index 73e268e3b..d3ce3e8de 100644 --- a/vtkm/filter/flow/worklet/Analysis.cxx +++ b/vtkm/filter/flow/worklet/Analysis.cxx @@ -1,4 +1,5 @@ -//============================================================================ +//============================================================================= +// // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. @@ -6,6 +7,221 @@ // 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 + +#include +#include +#include +#include +#include +#include +#include + +namespace vtkm +{ +namespace worklet +{ +namespace flow +{ + +template +VTKM_CONT bool NoAnalysis::MakeDataSet( + vtkm::cont::DataSet& dataset, + const std::vector>& results) +{ + size_t nResults = results.size(); + std::vector> allParticles; + allParticles.reserve(nResults); + for (const auto& vres : results) + allParticles.emplace_back(vres.Particles); + + vtkm::cont::ArrayHandle pts; + vtkm::cont::ParticleArrayCopy(allParticles, pts); + + vtkm::Id numPoints = pts.GetNumberOfValues(); + if (numPoints > 0) + { + //Create coordinate system and vertex cell set. + dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", pts)); + + vtkm::cont::CellSetSingleType<> cells; + vtkm::cont::ArrayHandleIndex conn(numPoints); + vtkm::cont::ArrayHandle connectivity; + + vtkm::cont::ArrayCopy(conn, connectivity); + cells.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity); + dataset.SetCellSet(cells); + } + return true; +} + +namespace detail +{ +class GetSteps : public vtkm::worklet::WorkletMapField +{ +public: + VTKM_CONT + GetSteps() {} + using ControlSignature = void(FieldIn, FieldOut); + using ExecutionSignature = void(_1, _2); + + template + VTKM_EXEC void operator()(const ParticleType& p, vtkm::Id& numSteps) const + { + numSteps = p.GetNumberOfSteps(); + } +}; + +class ComputeNumPoints : public vtkm::worklet::WorkletMapField +{ +public: + VTKM_CONT + ComputeNumPoints() {} + using ControlSignature = void(FieldIn, FieldIn, FieldOut); + using ExecutionSignature = void(_1, _2, _3); + + // Offset is number of points in streamline. + // 1 (inital point) + number of steps taken (p.NumSteps - initalNumSteps) + template + VTKM_EXEC void operator()(const ParticleType& p, + const vtkm::Id& initialNumSteps, + vtkm::Id& diff) const + { + diff = 1 + p.GetNumberOfSteps() - initialNumSteps; + } +}; + +} // namespace detail + +template +VTKM_CONT void StreamlineAnalysis::InitializeAnalysis( + const vtkm::cont::ArrayHandle& particles) +{ + this->NumParticles = particles.GetNumberOfValues(); + + //Create ValidPointArray initialized to zero. + vtkm::cont::ArrayHandleConstant validity(0, this->NumParticles * (this->MaxSteps + 1)); + vtkm::cont::ArrayCopy(validity, this->Validity); + //Create StepCountArray initialized to zero. + vtkm::cont::ArrayHandleConstant streamLengths(0, this->NumParticles); + vtkm::cont::ArrayCopy(streamLengths, this->StreamLengths); + + // Initialize InitLengths + vtkm::Id numSeeds = static_cast(particles.GetNumberOfValues()); + vtkm::cont::ArrayHandleIndex idxArray(numSeeds); + vtkm::cont::Invoker invoker; + invoker(detail::GetSteps{}, particles, this->InitialLengths); +} + +template +VTKM_CONT void StreamlineAnalysis::FinalizeAnalysis( + vtkm::cont::ArrayHandle& particles) +{ + vtkm::Id numSeeds = particles.GetNumberOfValues(); + vtkm::cont::ArrayHandle positions; + vtkm::cont::Algorithm::CopyIf(this->Streams, this->Validity, positions, IsOne()); + vtkm::cont::Algorithm::Copy(positions, this->Streams); + + // Create the cells + vtkm::cont::ArrayHandle numPoints; + vtkm::cont::Invoker invoker; + invoker(detail::ComputeNumPoints{}, particles, this->InitialLengths, numPoints); + + vtkm::cont::ArrayHandle cellIndex; + vtkm::Id connectivityLen = vtkm::cont::Algorithm::ScanExclusive(numPoints, cellIndex); + vtkm::cont::ArrayHandleIndex connCount(connectivityLen); + vtkm::cont::ArrayHandle connectivity; + vtkm::cont::ArrayCopy(connCount, connectivity); + + vtkm::cont::ArrayHandle cellTypes; + auto polyLineShape = + vtkm::cont::make_ArrayHandleConstant(vtkm::CELL_SHAPE_POLY_LINE, numSeeds); + vtkm::cont::ArrayCopy(polyLineShape, cellTypes); + + auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPoints); + + this->PolyLines.Fill(this->Streams.GetNumberOfValues(), cellTypes, connectivity, offsets); + this->Particles = particles; +} + +template +VTKM_CONT bool StreamlineAnalysis::MakeDataSet( + vtkm::cont::DataSet& dataset, + const std::vector>& results) +{ + size_t nResults = results.size(); + if (nResults == 1) + { + const auto& res = results[0]; + dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", res.Streams)); + dataset.SetCellSet(res.PolyLines); + } + else + { + std::vector posOffsets(nResults, 0); + vtkm::Id totalNumCells = 0, totalNumPts = 0; + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = results[i]; + if (i == 0) + posOffsets[i] = 0; + else + posOffsets[i] = totalNumPts; + + totalNumPts += res.Streams.GetNumberOfValues(); + totalNumCells += res.PolyLines.GetNumberOfCells(); + } + + //Append all the points together. + vtkm::cont::ArrayHandle appendPts; + appendPts.Allocate(totalNumPts); + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = results[i]; + // copy all values into appendPts starting at offset. + vtkm::cont::Algorithm::CopySubRange( + res.Streams, 0, res.Streams.GetNumberOfValues(), appendPts, posOffsets[i]); + } + dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", appendPts)); + + //Create polylines. + std::vector numPtsPerCell(static_cast(totalNumCells)); + std::size_t off = 0; + for (std::size_t i = 0; i < nResults; i++) + { + const auto& res = results[i]; + vtkm::Id nCells = res.PolyLines.GetNumberOfCells(); + for (vtkm::Id j = 0; j < nCells; j++) + numPtsPerCell[off++] = static_cast(res.PolyLines.GetNumberOfPointsInCell(j)); + } + + auto numPointsPerCellArray = vtkm::cont::make_ArrayHandle(numPtsPerCell, vtkm::CopyFlag::Off); + + vtkm::cont::ArrayHandle cellIndex; + vtkm::Id connectivityLen = + vtkm::cont::Algorithm::ScanExclusive(numPointsPerCellArray, cellIndex); + vtkm::cont::ArrayHandleIndex connCount(connectivityLen); + vtkm::cont::ArrayHandle connectivity; + vtkm::cont::ArrayCopy(connCount, connectivity); + + vtkm::cont::ArrayHandle cellTypes; + auto polyLineShape = + vtkm::cont::make_ArrayHandleConstant(vtkm::CELL_SHAPE_POLY_LINE, totalNumCells); + vtkm::cont::ArrayCopy(polyLineShape, cellTypes); + auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPointsPerCellArray); + + vtkm::cont::CellSetExplicit<> polyLines; + polyLines.Fill(totalNumPts, cellTypes, connectivity, offsets); + dataset.SetCellSet(polyLines); + } + return true; +} + +} // namespace flow +} // namespace worklet +} // namespace vtkm + +#include diff --git a/vtkm/filter/flow/worklet/Analysis.h b/vtkm/filter/flow/worklet/Analysis.h index 39f928d45..f51162ced 100644 --- a/vtkm/filter/flow/worklet/Analysis.h +++ b/vtkm/filter/flow/worklet/Analysis.h @@ -13,13 +13,10 @@ #ifndef vtkm_worklet_particleadvection_analysis #define vtkm_worklet_particleadvection_analysis -#include -#include -#include -#include -#include - -#include +#include +#include +#include +#include namespace vtkm { @@ -94,33 +91,7 @@ public: VTKM_CONT bool SupportPushOutOfBounds() const { return true; } VTKM_CONT static bool MakeDataSet(vtkm::cont::DataSet& dataset, - const std::vector& results) - { - size_t nResults = results.size(); - std::vector> allParticles; - allParticles.reserve(nResults); - for (const auto& vres : results) - allParticles.emplace_back(vres.Particles); - - vtkm::cont::ArrayHandle pts; - vtkm::cont::ParticleArrayCopy(allParticles, pts); - - vtkm::Id numPoints = pts.GetNumberOfValues(); - if (numPoints > 0) - { - //Create coordinate system and vertex cell set. - dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", pts)); - - vtkm::cont::CellSetSingleType<> cells; - vtkm::cont::ArrayHandleIndex conn(numPoints); - vtkm::cont::ArrayHandle connectivity; - - vtkm::cont::ArrayCopy(conn, connectivity); - cells.Fill(numPoints, vtkm::CELL_SHAPE_VERTEX, 1, connectivity); - dataset.SetCellSet(cells); - } - return true; - } + const std::vector& results); }; template @@ -189,44 +160,6 @@ private: IdPortal Validity; }; -namespace detail -{ -class GetSteps : public vtkm::worklet::WorkletMapField -{ -public: - VTKM_CONT - GetSteps() {} - using ControlSignature = void(FieldIn, FieldOut); - using ExecutionSignature = void(_1, _2); - - template - VTKM_EXEC void operator()(const ParticleType& p, vtkm::Id& numSteps) const - { - numSteps = p.GetNumberOfSteps(); - } -}; - -class ComputeNumPoints : public vtkm::worklet::WorkletMapField -{ -public: - VTKM_CONT - ComputeNumPoints() {} - using ControlSignature = void(FieldIn, FieldIn, FieldOut); - using ExecutionSignature = void(_1, _2, _3); - - // Offset is number of points in streamline. - // 1 (inital point) + number of steps taken (p.NumSteps - initalNumSteps) - template - VTKM_EXEC void operator()(const ParticleType& p, - const vtkm::Id& initialNumSteps, - vtkm::Id& diff) const - { - diff = 1 + p.GetNumberOfSteps() - initialNumSteps; - } -}; - -} // namespace detail - template class StreamlineAnalysis : public vtkm::cont::ExecutionObjectBase { @@ -279,128 +212,15 @@ public: VTKM_CONT bool SupportPushOutOfBounds() const { return true; } VTKM_CONT - //template - void InitializeAnalysis(const vtkm::cont::ArrayHandle& particles) - { - this->NumParticles = particles.GetNumberOfValues(); - - //Create ValidPointArray initialized to zero. - vtkm::cont::ArrayHandleConstant validity(0, - this->NumParticles * (this->MaxSteps + 1)); - vtkm::cont::ArrayCopy(validity, this->Validity); - //Create StepCountArray initialized to zero. - vtkm::cont::ArrayHandleConstant streamLengths(0, this->NumParticles); - vtkm::cont::ArrayCopy(streamLengths, this->StreamLengths); - - // Initialize InitLengths - vtkm::Id numSeeds = static_cast(particles.GetNumberOfValues()); - vtkm::cont::ArrayHandleIndex idxArray(numSeeds); - vtkm::cont::Invoker invoker; - invoker(detail::GetSteps{}, particles, this->InitialLengths); - } + void InitializeAnalysis(const vtkm::cont::ArrayHandle& particles); VTKM_CONT //template - void FinalizeAnalysis(vtkm::cont::ArrayHandle& particles) - { - vtkm::Id numSeeds = particles.GetNumberOfValues(); - vtkm::cont::ArrayHandle positions; - vtkm::cont::Algorithm::CopyIf(this->Streams, this->Validity, positions, IsOne()); - vtkm::cont::Algorithm::Copy(positions, this->Streams); - - // Create the cells - vtkm::cont::ArrayHandle numPoints; - vtkm::cont::Invoker invoker; - invoker(detail::ComputeNumPoints{}, particles, this->InitialLengths, numPoints); - - vtkm::cont::ArrayHandle cellIndex; - vtkm::Id connectivityLen = vtkm::cont::Algorithm::ScanExclusive(numPoints, cellIndex); - vtkm::cont::ArrayHandleIndex connCount(connectivityLen); - vtkm::cont::ArrayHandle connectivity; - vtkm::cont::ArrayCopy(connCount, connectivity); - - vtkm::cont::ArrayHandle cellTypes; - auto polyLineShape = - vtkm::cont::make_ArrayHandleConstant(vtkm::CELL_SHAPE_POLY_LINE, numSeeds); - vtkm::cont::ArrayCopy(polyLineShape, cellTypes); - - auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPoints); - - this->PolyLines.Fill(this->Streams.GetNumberOfValues(), cellTypes, connectivity, offsets); - this->Particles = particles; - } + void FinalizeAnalysis(vtkm::cont::ArrayHandle& particles); VTKM_CONT static bool MakeDataSet(vtkm::cont::DataSet& dataset, - const std::vector& results) - { - size_t nResults = results.size(); - if (nResults == 1) - { - const auto& res = results[0]; - dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", res.Streams)); - dataset.SetCellSet(res.PolyLines); - } - else - { - std::vector posOffsets(nResults, 0); - vtkm::Id totalNumCells = 0, totalNumPts = 0; - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = results[i]; - if (i == 0) - posOffsets[i] = 0; - else - posOffsets[i] = totalNumPts; - - totalNumPts += res.Streams.GetNumberOfValues(); - totalNumCells += res.PolyLines.GetNumberOfCells(); - } - - //Append all the points together. - vtkm::cont::ArrayHandle appendPts; - appendPts.Allocate(totalNumPts); - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = results[i]; - // copy all values into appendPts starting at offset. - vtkm::cont::Algorithm::CopySubRange( - res.Streams, 0, res.Streams.GetNumberOfValues(), appendPts, posOffsets[i]); - } - dataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", appendPts)); - - //Create polylines. - std::vector numPtsPerCell(static_cast(totalNumCells)); - std::size_t off = 0; - for (std::size_t i = 0; i < nResults; i++) - { - const auto& res = results[i]; - vtkm::Id nCells = res.PolyLines.GetNumberOfCells(); - for (vtkm::Id j = 0; j < nCells; j++) - numPtsPerCell[off++] = static_cast(res.PolyLines.GetNumberOfPointsInCell(j)); - } - - auto numPointsPerCellArray = vtkm::cont::make_ArrayHandle(numPtsPerCell, vtkm::CopyFlag::Off); - - vtkm::cont::ArrayHandle cellIndex; - vtkm::Id connectivityLen = - vtkm::cont::Algorithm::ScanExclusive(numPointsPerCellArray, cellIndex); - vtkm::cont::ArrayHandleIndex connCount(connectivityLen); - vtkm::cont::ArrayHandle connectivity; - vtkm::cont::ArrayCopy(connCount, connectivity); - - vtkm::cont::ArrayHandle cellTypes; - auto polyLineShape = vtkm::cont::make_ArrayHandleConstant( - vtkm::CELL_SHAPE_POLY_LINE, totalNumCells); - vtkm::cont::ArrayCopy(polyLineShape, cellTypes); - auto offsets = vtkm::cont::ConvertNumComponentsToOffsets(numPointsPerCellArray); - - vtkm::cont::CellSetExplicit<> polyLines; - polyLines.Fill(totalNumPts, cellTypes, connectivity, offsets); - dataset.SetCellSet(polyLines); - } - return true; - } + const std::vector& results); private: vtkm::Id NumParticles; diff --git a/vtkm/filter/flow/worklet/Analysis.inl b/vtkm/filter/flow/worklet/Analysis.inl new file mode 100644 index 000000000..c17045972 --- /dev/null +++ b/vtkm/filter/flow/worklet/Analysis.inl @@ -0,0 +1,15 @@ +namespace vtkm +{ +namespace worklet +{ +namespace flow +{ + +template class NoAnalysis; +template class NoAnalysis; +template class StreamlineAnalysis; +template class StreamlineAnalysis; + +} // namespace particleadvection +} // namespace worklet +} // namespace vtkm