Merge topic 'bounding-interval-hierarchy-in-vtkm-cont'
5960b8abf Suppress nvlink warnings about virtual methods not used 0af017b03 Move virtual methods of other CellLocators to vtkm_cont e87864b0e Put CellLocatorBoundingIntervalHierarchy in vtkm_cont library Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !1594
This commit is contained in:
commit
07fe1060a0
@ -57,5 +57,8 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION
|
||||
"nvlink warning : Stack size for entry function.*ArrayPortalWrapper.*"
|
||||
"nvlink warning : .*ArrayPortalWrapper.* has address taken but no possible call to it"
|
||||
"nvlink warning : .*ArrayPortalVirtual.* has address taken but no possible call to it"
|
||||
"nvlink warning : .*CellLocatorBoundingIntervalHierarchyExec.* has address taken but no possible call to it"
|
||||
"nvlink warning : .*CellLocatorRectilinearGrid.* has address taken but no possible call to it"
|
||||
"nvlink warning : .*CellLocatorUniformGrid.* has address taken but no possible call to it"
|
||||
|
||||
)
|
||||
|
10
docs/changelog/bounding-interval-hierarchy-in-vtkm-cont.md
Normal file
10
docs/changelog/bounding-interval-hierarchy-in-vtkm-cont.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Put CellLocatorBoundingIntervalHierarchy in vtkm_cont library
|
||||
|
||||
All of the methods in CellLocatorBoundingIntervalHierarchy were listed in
|
||||
header files. This is sometimes problematic with virtual methods. Since
|
||||
everything implemented in it can just be embedded in a library, move the
|
||||
code into the vtkm_cont library.
|
||||
|
||||
These changes caused some warnings in clang to show up based on virtual
|
||||
methods in other cell locators. Hence, the rest of the cell locators
|
||||
have also had some of their code moved to vtkm_cont.
|
@ -114,7 +114,6 @@ set(template_sources
|
||||
ArrayHandle.hxx
|
||||
ArrayHandleVirtual.hxx
|
||||
ArrayRangeCompute.hxx
|
||||
CellLocatorBoundingIntervalHierarchy.hxx
|
||||
CellSetExplicit.hxx
|
||||
CellSetStructured.hxx
|
||||
ColorTable.hxx
|
||||
@ -132,6 +131,7 @@ set(sources
|
||||
AssignerMultiBlock.cxx
|
||||
BoundsCompute.cxx
|
||||
BoundsGlobalCompute.cxx
|
||||
CellLocator.cxx
|
||||
CellSet.cxx
|
||||
CellSetStructured.cxx
|
||||
ColorTable.cxx
|
||||
@ -166,6 +166,9 @@ set(sources
|
||||
# compiled with a device-specific compiler (like CUDA).
|
||||
set(device_sources
|
||||
ArrayRangeCompute.cxx
|
||||
CellLocatorBoundingIntervalHierarchy.cxx
|
||||
CellLocatorRectilinearGrid.cxx
|
||||
CellLocatorUniformGrid.cxx
|
||||
CellSetExplicit.cxx
|
||||
CoordinateSystem.cxx
|
||||
StorageVirtual.cxx
|
||||
|
23
vtkm/cont/CellLocator.cxx
Normal file
23
vtkm/cont/CellLocator.cxx
Normal file
@ -0,0 +1,23 @@
|
||||
//============================================================================
|
||||
// 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/CellLocator.h>
|
||||
|
||||
vtkm::cont::CellLocator::~CellLocator() = default;
|
@ -36,7 +36,7 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class VTKM_ALWAYS_EXPORT CellLocator : public vtkm::cont::ExecutionObjectBase
|
||||
class VTKM_CONT_EXPORT CellLocator : public vtkm::cont::ExecutionObjectBase
|
||||
{
|
||||
|
||||
public:
|
||||
@ -45,6 +45,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CellLocator();
|
||||
|
||||
vtkm::cont::DynamicCellSet GetCellSet() const { return CellSet; }
|
||||
|
||||
void SetCellSet(const vtkm::cont::DynamicCellSet& cellSet)
|
||||
|
541
vtkm/cont/CellLocatorBoundingIntervalHierarchy.cxx
Normal file
541
vtkm/cont/CellLocatorBoundingIntervalHierarchy.cxx
Normal file
@ -0,0 +1,541 @@
|
||||
//============================================================================
|
||||
// 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 <vtkm/Bounds.h>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecFromPortalPermute.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleReverse.h>
|
||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/exec/CellLocatorBoundingIntervalHierarchyExec.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/Invoker.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
using IdArrayHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using IdPermutationArrayHandle = vtkm::cont::ArrayHandlePermutation<IdArrayHandle, IdArrayHandle>;
|
||||
using BoundsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Bounds>;
|
||||
using CoordsArrayHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
|
||||
using CoordsPermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, CoordsArrayHandle>;
|
||||
using CountingIdArrayHandle = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
|
||||
using RangeArrayHandle = vtkm::cont::ArrayHandle<vtkm::Range>;
|
||||
using RangePermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, RangeArrayHandle>;
|
||||
using SplitArrayHandle = vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::TreeNode>;
|
||||
using SplitPermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, SplitArrayHandle>;
|
||||
using SplitPropertiesArrayHandle =
|
||||
vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::SplitProperties>;
|
||||
using HandleType = vtkm::cont::VirtualObjectHandle<vtkm::exec::CellLocator>;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
VTKM_CONT IdArrayHandle CalculateSegmentSizes(const IdArrayHandle& segmentIds, vtkm::Id numCells)
|
||||
{
|
||||
IdArrayHandle discardKeys;
|
||||
IdArrayHandle segmentSizes;
|
||||
vtkm::cont::Algorithm::ReduceByKey(segmentIds,
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::Id>(1, numCells),
|
||||
discardKeys,
|
||||
segmentSizes,
|
||||
vtkm::Add());
|
||||
return segmentSizes;
|
||||
}
|
||||
|
||||
VTKM_CONT IdArrayHandle GenerateSegmentIds(const IdArrayHandle& segmentSizes, vtkm::Id numCells)
|
||||
{
|
||||
// Compact segment ids, removing non-contiguous values.
|
||||
|
||||
// 1. Perform ScanInclusive to calculate the end positions of each segment
|
||||
IdArrayHandle segmentEnds;
|
||||
vtkm::cont::Algorithm::ScanInclusive(segmentSizes, segmentEnds);
|
||||
// 2. Perform UpperBounds to perform the final compaction.
|
||||
IdArrayHandle segmentIds;
|
||||
vtkm::cont::Algorithm::UpperBounds(
|
||||
segmentEnds, vtkm::cont::ArrayHandleCounting<vtkm::Id>(0, 1, numCells), segmentIds);
|
||||
return segmentIds;
|
||||
}
|
||||
|
||||
VTKM_CONT void CalculatePlaneSplitCost(vtkm::IdComponent planeIndex,
|
||||
vtkm::IdComponent numPlanes,
|
||||
RangePermutationArrayHandle& segmentRanges,
|
||||
RangeArrayHandle& ranges,
|
||||
CoordsArrayHandle& coords,
|
||||
IdArrayHandle& segmentIds,
|
||||
SplitPropertiesArrayHandle& splits,
|
||||
vtkm::IdComponent index,
|
||||
vtkm::IdComponent numTotalPlanes)
|
||||
{
|
||||
vtkm::worklet::Invoker invoker;
|
||||
|
||||
// Make candidate split plane array
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> splitPlanes;
|
||||
vtkm::worklet::spatialstructure::SplitPlaneCalculatorWorklet splitPlaneCalcWorklet(planeIndex,
|
||||
numPlanes);
|
||||
invoker(splitPlaneCalcWorklet, segmentRanges, splitPlanes);
|
||||
|
||||
// Check if a point is to the left of the split plane or right
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> isLEQOfSplitPlane, isROfSplitPlane;
|
||||
invoker(vtkm::worklet::spatialstructure::LEQWorklet{},
|
||||
coords,
|
||||
splitPlanes,
|
||||
isLEQOfSplitPlane,
|
||||
isROfSplitPlane);
|
||||
|
||||
// Count of points to the left
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointsToLeft;
|
||||
IdArrayHandle discardKeys;
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, isLEQOfSplitPlane, discardKeys, pointsToLeft, vtkm::Add());
|
||||
|
||||
// Count of points to the right
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointsToRight;
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, isROfSplitPlane, discardKeys, pointsToRight, vtkm::Add());
|
||||
|
||||
isLEQOfSplitPlane.ReleaseResourcesExecution();
|
||||
isROfSplitPlane.ReleaseResourcesExecution();
|
||||
|
||||
// Calculate Lmax and Rmin
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> lMaxRanges;
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> leqRanges;
|
||||
vtkm::worklet::spatialstructure::FilterRanges<true> worklet;
|
||||
invoker(worklet, coords, splitPlanes, ranges, leqRanges);
|
||||
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, leqRanges, discardKeys, lMaxRanges, vtkm::worklet::spatialstructure::RangeAdd());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rMinRanges;
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rRanges;
|
||||
vtkm::worklet::spatialstructure::FilterRanges<false> worklet;
|
||||
invoker(worklet, coords, splitPlanes, ranges, rRanges);
|
||||
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, rRanges, discardKeys, rMinRanges, vtkm::worklet::spatialstructure::RangeAdd());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> segmentedSplitPlanes;
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, splitPlanes, discardKeys, segmentedSplitPlanes, vtkm::Minimum());
|
||||
|
||||
// Calculate costs
|
||||
vtkm::worklet::spatialstructure::SplitPropertiesCalculator splitPropertiesCalculator(
|
||||
index, numTotalPlanes + 1);
|
||||
invoker(splitPropertiesCalculator,
|
||||
pointsToLeft,
|
||||
pointsToRight,
|
||||
lMaxRanges,
|
||||
rMinRanges,
|
||||
segmentedSplitPlanes,
|
||||
splits);
|
||||
}
|
||||
|
||||
VTKM_CONT void CalculateSplitCosts(vtkm::IdComponent numPlanes,
|
||||
RangePermutationArrayHandle& segmentRanges,
|
||||
RangeArrayHandle& ranges,
|
||||
CoordsArrayHandle& coords,
|
||||
IdArrayHandle& segmentIds,
|
||||
SplitPropertiesArrayHandle& splits)
|
||||
{
|
||||
for (vtkm::IdComponent planeIndex = 0; planeIndex < numPlanes; ++planeIndex)
|
||||
{
|
||||
CalculatePlaneSplitCost(planeIndex,
|
||||
numPlanes,
|
||||
segmentRanges,
|
||||
ranges,
|
||||
coords,
|
||||
segmentIds,
|
||||
splits,
|
||||
planeIndex,
|
||||
numPlanes);
|
||||
}
|
||||
// Calculate median costs
|
||||
CalculatePlaneSplitCost(
|
||||
0, 1, segmentRanges, ranges, coords, segmentIds, splits, numPlanes, numPlanes);
|
||||
}
|
||||
|
||||
VTKM_CONT IdArrayHandle CalculateSplitScatterIndices(const IdArrayHandle& cellIds,
|
||||
const IdArrayHandle& leqFlags,
|
||||
const IdArrayHandle& segmentIds)
|
||||
{
|
||||
vtkm::worklet::Invoker invoker;
|
||||
|
||||
// Count total number of true flags preceding in segment
|
||||
IdArrayHandle trueFlagCounts;
|
||||
vtkm::cont::Algorithm::ScanExclusiveByKey(segmentIds, leqFlags, trueFlagCounts);
|
||||
|
||||
// Make a counting iterator.
|
||||
CountingIdArrayHandle counts(0, 1, cellIds.GetNumberOfValues());
|
||||
|
||||
// Total number of elements in previous segment
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> countPreviousSegments;
|
||||
vtkm::cont::Algorithm::ScanInclusiveByKey(
|
||||
segmentIds, counts, countPreviousSegments, vtkm::Minimum());
|
||||
|
||||
// Total number of false flags so far in segment
|
||||
vtkm::cont::ArrayHandleTransform<IdArrayHandle, vtkm::worklet::spatialstructure::Invert>
|
||||
flagsInverse(leqFlags, vtkm::worklet::spatialstructure::Invert());
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> runningFalseFlagCount;
|
||||
vtkm::cont::Algorithm::ScanInclusiveByKey(
|
||||
segmentIds, flagsInverse, runningFalseFlagCount, vtkm::Add());
|
||||
|
||||
// Total number of false flags in segment
|
||||
IdArrayHandle totalFalseFlagSegmentCount =
|
||||
vtkm::worklet::spatialstructure::ReverseScanInclusiveByKey(
|
||||
segmentIds, runningFalseFlagCount, vtkm::Maximum());
|
||||
|
||||
// if point is to the left,
|
||||
// index = total number in previous segments + total number of false flags in this segment + total number of trues in previous segment
|
||||
// else
|
||||
// index = total number in previous segments + number of falses preceding it in the segment.
|
||||
IdArrayHandle scatterIndices;
|
||||
invoker(vtkm::worklet::spatialstructure::SplitIndicesCalculator{},
|
||||
leqFlags,
|
||||
trueFlagCounts,
|
||||
countPreviousSegments,
|
||||
runningFalseFlagCount,
|
||||
totalFalseFlagSegmentCount,
|
||||
scatterIndices);
|
||||
return scatterIndices;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
VTKM_CONT CellLocatorBoundingIntervalHierarchy::~CellLocatorBoundingIntervalHierarchy() = default;
|
||||
|
||||
VTKM_CONT
|
||||
void CellLocatorBoundingIntervalHierarchy::Build()
|
||||
{
|
||||
vtkm::worklet::Invoker invoker;
|
||||
|
||||
vtkm::cont::DynamicCellSet cellSet = this->GetCellSet();
|
||||
vtkm::Id numCells = cellSet.GetNumberOfCells();
|
||||
vtkm::cont::CoordinateSystem coords = this->GetCoordinates();
|
||||
vtkm::cont::ArrayHandleVirtualCoordinates points = coords.GetData();
|
||||
|
||||
//std::cout << "No of cells: " << numCells << "\n";
|
||||
//std::cout.precision(3);
|
||||
//START_TIMER(s11);
|
||||
IdArrayHandle cellIds;
|
||||
vtkm::cont::Algorithm::Copy(CountingIdArrayHandle(0, 1, numCells), cellIds);
|
||||
IdArrayHandle segmentIds;
|
||||
vtkm::cont::Algorithm::Copy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numCells), segmentIds);
|
||||
//PRINT_TIMER("1.1", s11);
|
||||
|
||||
//START_TIMER(s12);
|
||||
CoordsArrayHandle centerXs, centerYs, centerZs;
|
||||
RangeArrayHandle xRanges, yRanges, zRanges;
|
||||
invoker(vtkm::worklet::spatialstructure::CellRangesExtracter{},
|
||||
cellSet,
|
||||
points,
|
||||
xRanges,
|
||||
yRanges,
|
||||
zRanges,
|
||||
centerXs,
|
||||
centerYs,
|
||||
centerZs);
|
||||
//PRINT_TIMER("1.2", s12);
|
||||
|
||||
bool done = false;
|
||||
//vtkm::IdComponent iteration = 0;
|
||||
vtkm::Id nodesIndexOffset = 0;
|
||||
vtkm::Id numSegments = 1;
|
||||
IdArrayHandle discardKeys;
|
||||
IdArrayHandle segmentSizes;
|
||||
segmentSizes.Allocate(1);
|
||||
segmentSizes.GetPortalControl().Set(0, numCells);
|
||||
this->ProcessedCellIds.Allocate(numCells);
|
||||
vtkm::Id cellIdsOffset = 0;
|
||||
|
||||
IdArrayHandle parentIndices;
|
||||
parentIndices.Allocate(1);
|
||||
parentIndices.GetPortalControl().Set(0, -1);
|
||||
|
||||
while (!done)
|
||||
{
|
||||
//std::cout << "**** Iteration " << (++iteration) << " ****\n";
|
||||
//Output(segmentSizes);
|
||||
//START_TIMER(s21);
|
||||
// Calculate the X, Y, Z bounding ranges for each segment
|
||||
RangeArrayHandle perSegmentXRanges, perSegmentYRanges, perSegmentZRanges;
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, xRanges, discardKeys, perSegmentXRanges, vtkm::Add());
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, yRanges, discardKeys, perSegmentYRanges, vtkm::Add());
|
||||
vtkm::cont::Algorithm::ReduceByKey(
|
||||
segmentIds, zRanges, discardKeys, perSegmentZRanges, vtkm::Add());
|
||||
//PRINT_TIMER("2.1", s21);
|
||||
|
||||
// Expand the per segment bounding ranges, to per cell;
|
||||
RangePermutationArrayHandle segmentXRanges(segmentIds, perSegmentXRanges);
|
||||
RangePermutationArrayHandle segmentYRanges(segmentIds, perSegmentYRanges);
|
||||
RangePermutationArrayHandle segmentZRanges(segmentIds, perSegmentZRanges);
|
||||
|
||||
//START_TIMER(s22);
|
||||
// Calculate split costs for NumPlanes split planes, across X, Y and Z dimensions
|
||||
vtkm::Id numSplitPlanes = numSegments * (this->NumPlanes + 1);
|
||||
vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::SplitProperties> xSplits, ySplits,
|
||||
zSplits;
|
||||
xSplits.Allocate(numSplitPlanes);
|
||||
ySplits.Allocate(numSplitPlanes);
|
||||
zSplits.Allocate(numSplitPlanes);
|
||||
CalculateSplitCosts(this->NumPlanes, segmentXRanges, xRanges, centerXs, segmentIds, xSplits);
|
||||
CalculateSplitCosts(this->NumPlanes, segmentYRanges, yRanges, centerYs, segmentIds, ySplits);
|
||||
CalculateSplitCosts(this->NumPlanes, segmentZRanges, zRanges, centerZs, segmentIds, zSplits);
|
||||
//PRINT_TIMER("2.2", s22);
|
||||
|
||||
segmentXRanges.ReleaseResourcesExecution();
|
||||
segmentYRanges.ReleaseResourcesExecution();
|
||||
segmentZRanges.ReleaseResourcesExecution();
|
||||
|
||||
//START_TIMER(s23);
|
||||
// Select best split plane and dimension across X, Y, Z dimension, per segment
|
||||
SplitArrayHandle segmentSplits;
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> segmentPlanes;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> splitChoices;
|
||||
CountingIdArrayHandle indices(0, 1, numSegments);
|
||||
|
||||
vtkm::worklet::spatialstructure::SplitSelector worklet(
|
||||
this->NumPlanes, this->MaxLeafSize, this->NumPlanes + 1);
|
||||
invoker(worklet,
|
||||
indices,
|
||||
xSplits,
|
||||
ySplits,
|
||||
zSplits,
|
||||
segmentSizes,
|
||||
segmentSplits,
|
||||
segmentPlanes,
|
||||
splitChoices);
|
||||
//PRINT_TIMER("2.3", s23);
|
||||
|
||||
// Expand the per segment split plane to per cell
|
||||
SplitPermutationArrayHandle splits(segmentIds, segmentSplits);
|
||||
CoordsPermutationArrayHandle planes(segmentIds, segmentPlanes);
|
||||
|
||||
//START_TIMER(s31);
|
||||
IdArrayHandle leqFlags;
|
||||
invoker(vtkm::worklet::spatialstructure::CalculateSplitDirectionFlag{},
|
||||
centerXs,
|
||||
centerYs,
|
||||
centerZs,
|
||||
splits,
|
||||
planes,
|
||||
leqFlags);
|
||||
//PRINT_TIMER("3.1", s31);
|
||||
|
||||
//START_TIMER(s32);
|
||||
IdArrayHandle scatterIndices = CalculateSplitScatterIndices(cellIds, leqFlags, segmentIds);
|
||||
IdArrayHandle newSegmentIds;
|
||||
IdPermutationArrayHandle sizes(segmentIds, segmentSizes);
|
||||
invoker(vtkm::worklet::spatialstructure::SegmentSplitter{ this->MaxLeafSize },
|
||||
segmentIds,
|
||||
leqFlags,
|
||||
sizes,
|
||||
newSegmentIds);
|
||||
//PRINT_TIMER("3.2", s32);
|
||||
|
||||
//START_TIMER(s33);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> choices;
|
||||
vtkm::cont::Algorithm::Copy(IdPermutationArrayHandle(segmentIds, splitChoices), choices);
|
||||
cellIds = vtkm::worklet::spatialstructure::ScatterArray(cellIds, scatterIndices);
|
||||
segmentIds = vtkm::worklet::spatialstructure::ScatterArray(segmentIds, scatterIndices);
|
||||
newSegmentIds = vtkm::worklet::spatialstructure::ScatterArray(newSegmentIds, scatterIndices);
|
||||
xRanges = vtkm::worklet::spatialstructure::ScatterArray(xRanges, scatterIndices);
|
||||
yRanges = vtkm::worklet::spatialstructure::ScatterArray(yRanges, scatterIndices);
|
||||
zRanges = vtkm::worklet::spatialstructure::ScatterArray(zRanges, scatterIndices);
|
||||
centerXs = vtkm::worklet::spatialstructure::ScatterArray(centerXs, scatterIndices);
|
||||
centerYs = vtkm::worklet::spatialstructure::ScatterArray(centerYs, scatterIndices);
|
||||
centerZs = vtkm::worklet::spatialstructure::ScatterArray(centerZs, scatterIndices);
|
||||
choices = vtkm::worklet::spatialstructure::ScatterArray(choices, scatterIndices);
|
||||
//PRINT_TIMER("3.3", s33);
|
||||
|
||||
// Move the cell ids at leafs to the processed cellids list
|
||||
//START_TIMER(s41);
|
||||
IdArrayHandle nonSplitSegmentSizes;
|
||||
invoker(vtkm::worklet::spatialstructure::NonSplitIndexCalculator{ this->MaxLeafSize },
|
||||
segmentSizes,
|
||||
nonSplitSegmentSizes);
|
||||
IdArrayHandle nonSplitSegmentIndices;
|
||||
vtkm::cont::Algorithm::ScanExclusive(nonSplitSegmentSizes, nonSplitSegmentIndices);
|
||||
IdArrayHandle runningSplitSegmentCounts;
|
||||
vtkm::Id numNewSegments =
|
||||
vtkm::cont::Algorithm::ScanExclusive(splitChoices, runningSplitSegmentCounts);
|
||||
//PRINT_TIMER("4.1", s41);
|
||||
|
||||
//START_TIMER(s42);
|
||||
IdArrayHandle doneCellIds;
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
cellIds, choices, doneCellIds, vtkm::worklet::spatialstructure::Invert());
|
||||
vtkm::cont::Algorithm::CopySubRange(
|
||||
doneCellIds, 0, doneCellIds.GetNumberOfValues(), this->ProcessedCellIds, cellIdsOffset);
|
||||
|
||||
cellIds = vtkm::worklet::spatialstructure::CopyIfArray(cellIds, choices);
|
||||
newSegmentIds = vtkm::worklet::spatialstructure::CopyIfArray(newSegmentIds, choices);
|
||||
xRanges = vtkm::worklet::spatialstructure::CopyIfArray(xRanges, choices);
|
||||
yRanges = vtkm::worklet::spatialstructure::CopyIfArray(yRanges, choices);
|
||||
zRanges = vtkm::worklet::spatialstructure::CopyIfArray(zRanges, choices);
|
||||
centerXs = vtkm::worklet::spatialstructure::CopyIfArray(centerXs, choices);
|
||||
centerYs = vtkm::worklet::spatialstructure::CopyIfArray(centerYs, choices);
|
||||
centerZs = vtkm::worklet::spatialstructure::CopyIfArray(centerZs, choices);
|
||||
//PRINT_TIMER("4.2", s42);
|
||||
|
||||
//START_TIMER(s43);
|
||||
// Make a new nodes with enough nodes for the current level, copying over the old one
|
||||
vtkm::Id nodesSize = this->Nodes.GetNumberOfValues() + numSegments;
|
||||
vtkm::cont::ArrayHandle<vtkm::exec::CellLocatorBoundingIntervalHierarchyNode> newTree;
|
||||
newTree.Allocate(nodesSize);
|
||||
vtkm::cont::Algorithm::CopySubRange(this->Nodes, 0, this->Nodes.GetNumberOfValues(), newTree);
|
||||
|
||||
IdArrayHandle nextParentIndices;
|
||||
nextParentIndices.Allocate(2 * numNewSegments);
|
||||
|
||||
CountingIdArrayHandle nodesIndices(nodesIndexOffset, 1, numSegments);
|
||||
vtkm::worklet::spatialstructure::TreeLevelAdder nodesAdder(
|
||||
cellIdsOffset, nodesSize, this->MaxLeafSize);
|
||||
invoker(nodesAdder,
|
||||
nodesIndices,
|
||||
segmentSplits,
|
||||
nonSplitSegmentIndices,
|
||||
segmentSizes,
|
||||
runningSplitSegmentCounts,
|
||||
parentIndices,
|
||||
newTree,
|
||||
nextParentIndices);
|
||||
nodesIndexOffset = nodesSize;
|
||||
cellIdsOffset += doneCellIds.GetNumberOfValues();
|
||||
this->Nodes = newTree;
|
||||
//PRINT_TIMER("4.3", s43);
|
||||
//START_TIMER(s51);
|
||||
segmentIds = newSegmentIds;
|
||||
segmentSizes = CalculateSegmentSizes(segmentIds, segmentIds.GetNumberOfValues());
|
||||
segmentIds = GenerateSegmentIds(segmentSizes, segmentIds.GetNumberOfValues());
|
||||
IdArrayHandle uniqueSegmentIds;
|
||||
vtkm::cont::Algorithm::Copy(segmentIds, uniqueSegmentIds);
|
||||
vtkm::cont::Algorithm::Unique(uniqueSegmentIds);
|
||||
numSegments = uniqueSegmentIds.GetNumberOfValues();
|
||||
done = segmentIds.GetNumberOfValues() == 0;
|
||||
parentIndices = nextParentIndices;
|
||||
//PRINT_TIMER("5.1", s51);
|
||||
//std::cout << "Iteration time: " << iterationTimer.GetElapsedTime() << "\n";
|
||||
}
|
||||
//std::cout << "Total time: " << totalTimer.GetElapsedTime() << "\n";
|
||||
}
|
||||
|
||||
class CellLocatorBoundingIntervalHierarchy::PrepareForExecutionFunctor
|
||||
{
|
||||
public:
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorBoundingIntervalHierarchy& bih,
|
||||
HandleType& bihExec) const
|
||||
{
|
||||
vtkm::cont::DynamicCellSet cellSet = bih.GetCellSet();
|
||||
if (cellSet.IsType<vtkm::cont::CellSetExplicit<>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetExplicit<>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<2>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetStructured<2>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<3>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetStructured<3>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetSingleType<>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetSingleType<>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT
|
||||
const HandleType CellLocatorBoundingIntervalHierarchy::PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("BoundingIntervalHierarchy", deviceId);
|
||||
}
|
||||
|
||||
return this->ExecHandle;
|
||||
}
|
||||
|
||||
} //namespace cont
|
||||
} //namespace vtkm
|
@ -35,7 +35,7 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class VTKM_ALWAYS_EXPORT CellLocatorBoundingIntervalHierarchy : public vtkm::cont::CellLocator
|
||||
class VTKM_CONT_EXPORT CellLocatorBoundingIntervalHierarchy : public vtkm::cont::CellLocator
|
||||
{
|
||||
private:
|
||||
using IdArrayHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
@ -50,37 +50,6 @@ private:
|
||||
class BuildFunctor;
|
||||
class PrepareForExecutionFunctor;
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle CalculateSegmentSizes(const IdArrayHandle&, vtkm::Id);
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle GenerateSegmentIds(const IdArrayHandle&, vtkm::Id);
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void CalculateSplitCosts(RangePermutationArrayHandle&,
|
||||
RangeArrayHandle&,
|
||||
CoordsArrayHandle&,
|
||||
IdArrayHandle&,
|
||||
SplitPropertiesArrayHandle&,
|
||||
DeviceAdapter);
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void CalculatePlaneSplitCost(vtkm::IdComponent,
|
||||
vtkm::IdComponent,
|
||||
RangePermutationArrayHandle&,
|
||||
RangeArrayHandle&,
|
||||
CoordsArrayHandle&,
|
||||
IdArrayHandle&,
|
||||
SplitPropertiesArrayHandle&,
|
||||
vtkm::IdComponent,
|
||||
DeviceAdapter);
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle CalculateSplitScatterIndices(const IdArrayHandle&,
|
||||
const IdArrayHandle&,
|
||||
const IdArrayHandle&,
|
||||
DeviceAdapter);
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CellLocatorBoundingIntervalHierarchy(vtkm::IdComponent numPlanes = 4,
|
||||
@ -92,6 +61,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT ~CellLocatorBoundingIntervalHierarchy() override;
|
||||
|
||||
VTKM_CONT
|
||||
void SetNumberOfSplittingPlanes(vtkm::IdComponent numPlanes)
|
||||
{
|
||||
|
@ -1,573 +0,0 @@
|
||||
//============================================================================
|
||||
// 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 <vtkm/Bounds.h>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecFromPortalPermute.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleReverse.h>
|
||||
#include <vtkm/cont/ArrayHandleTransform.h>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/exec/CellLocatorBoundingIntervalHierarchyExec.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/Invoker.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
using IdArrayHandle = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
using IdPermutationArrayHandle = vtkm::cont::ArrayHandlePermutation<IdArrayHandle, IdArrayHandle>;
|
||||
using BoundsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Bounds>;
|
||||
using CoordsArrayHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
|
||||
using CoordsPermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, CoordsArrayHandle>;
|
||||
using CountingIdArrayHandle = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
|
||||
using RangeArrayHandle = vtkm::cont::ArrayHandle<vtkm::Range>;
|
||||
using RangePermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, RangeArrayHandle>;
|
||||
using SplitArrayHandle = vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::TreeNode>;
|
||||
using SplitPermutationArrayHandle =
|
||||
vtkm::cont::ArrayHandlePermutation<IdArrayHandle, SplitArrayHandle>;
|
||||
using SplitPropertiesArrayHandle =
|
||||
vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::SplitProperties>;
|
||||
using HandleType = vtkm::cont::VirtualObjectHandle<vtkm::exec::CellLocator>;
|
||||
|
||||
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle
|
||||
CellLocatorBoundingIntervalHierarchy::CalculateSegmentSizes(const IdArrayHandle& segmentIds,
|
||||
vtkm::Id numCells)
|
||||
{
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
IdArrayHandle discardKeys;
|
||||
IdArrayHandle segmentSizes;
|
||||
Algorithms::ReduceByKey(segmentIds,
|
||||
vtkm::cont::ArrayHandleConstant<vtkm::Id>(1, numCells),
|
||||
discardKeys,
|
||||
segmentSizes,
|
||||
vtkm::Add());
|
||||
return segmentSizes;
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle
|
||||
CellLocatorBoundingIntervalHierarchy::GenerateSegmentIds(const IdArrayHandle& segmentSizes,
|
||||
vtkm::Id numCells)
|
||||
{
|
||||
// Compact segment ids, removing non-contiguous values.
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
// 1. Perform ScanInclusive to calculate the end positions of each segment
|
||||
IdArrayHandle segmentEnds;
|
||||
Algorithms::ScanInclusive(segmentSizes, segmentEnds);
|
||||
// 2. Perform UpperBounds to perform the final compaction.
|
||||
IdArrayHandle segmentIds;
|
||||
Algorithms::UpperBounds(
|
||||
segmentEnds, vtkm::cont::ArrayHandleCounting<vtkm::Id>(0, 1, numCells), segmentIds);
|
||||
return segmentIds;
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void CellLocatorBoundingIntervalHierarchy::CalculateSplitCosts(
|
||||
RangePermutationArrayHandle& segmentRanges,
|
||||
RangeArrayHandle& ranges,
|
||||
CoordsArrayHandle& coords,
|
||||
IdArrayHandle& segmentIds,
|
||||
SplitPropertiesArrayHandle& splits,
|
||||
DeviceAdapter)
|
||||
{
|
||||
for (vtkm::IdComponent planeIndex = 0; planeIndex < NumPlanes; ++planeIndex)
|
||||
{
|
||||
CalculatePlaneSplitCost(planeIndex,
|
||||
NumPlanes,
|
||||
segmentRanges,
|
||||
ranges,
|
||||
coords,
|
||||
segmentIds,
|
||||
splits,
|
||||
planeIndex,
|
||||
DeviceAdapter());
|
||||
}
|
||||
// Calculate median costs
|
||||
CalculatePlaneSplitCost(
|
||||
0, 1, segmentRanges, ranges, coords, segmentIds, splits, NumPlanes, DeviceAdapter());
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void CellLocatorBoundingIntervalHierarchy::CalculatePlaneSplitCost(
|
||||
vtkm::IdComponent planeIndex,
|
||||
vtkm::IdComponent numPlanes,
|
||||
RangePermutationArrayHandle& segmentRanges,
|
||||
RangeArrayHandle& ranges,
|
||||
CoordsArrayHandle& coords,
|
||||
IdArrayHandle& segmentIds,
|
||||
SplitPropertiesArrayHandle& splits,
|
||||
vtkm::IdComponent index,
|
||||
DeviceAdapter)
|
||||
{
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
vtkm::worklet::Invoker invoker(DeviceAdapter{});
|
||||
|
||||
// Make candidate split plane array
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> splitPlanes;
|
||||
vtkm::worklet::spatialstructure::SplitPlaneCalculatorWorklet splitPlaneCalcWorklet(planeIndex,
|
||||
numPlanes);
|
||||
invoker(splitPlaneCalcWorklet, segmentRanges, splitPlanes);
|
||||
|
||||
// Check if a point is to the left of the split plane or right
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> isLEQOfSplitPlane, isROfSplitPlane;
|
||||
invoker(vtkm::worklet::spatialstructure::LEQWorklet{},
|
||||
coords,
|
||||
splitPlanes,
|
||||
isLEQOfSplitPlane,
|
||||
isROfSplitPlane);
|
||||
|
||||
// Count of points to the left
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointsToLeft;
|
||||
IdArrayHandle discardKeys;
|
||||
Algorithms::ReduceByKey(segmentIds, isLEQOfSplitPlane, discardKeys, pointsToLeft, vtkm::Add());
|
||||
|
||||
// Count of points to the right
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> pointsToRight;
|
||||
Algorithms::ReduceByKey(segmentIds, isROfSplitPlane, discardKeys, pointsToRight, vtkm::Add());
|
||||
|
||||
isLEQOfSplitPlane.ReleaseResourcesExecution();
|
||||
isROfSplitPlane.ReleaseResourcesExecution();
|
||||
|
||||
// Calculate Lmax and Rmin
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> lMaxRanges;
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> leqRanges;
|
||||
vtkm::worklet::spatialstructure::FilterRanges<true> worklet;
|
||||
invoker(worklet, coords, splitPlanes, ranges, leqRanges);
|
||||
|
||||
Algorithms::ReduceByKey(
|
||||
segmentIds, leqRanges, discardKeys, lMaxRanges, vtkm::worklet::spatialstructure::RangeAdd());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rMinRanges;
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> rRanges;
|
||||
vtkm::worklet::spatialstructure::FilterRanges<false> worklet;
|
||||
invoker(worklet, coords, splitPlanes, ranges, rRanges);
|
||||
|
||||
Algorithms::ReduceByKey(
|
||||
segmentIds, rRanges, discardKeys, rMinRanges, vtkm::worklet::spatialstructure::RangeAdd());
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> segmentedSplitPlanes;
|
||||
Algorithms::ReduceByKey(
|
||||
segmentIds, splitPlanes, discardKeys, segmentedSplitPlanes, vtkm::Minimum());
|
||||
|
||||
// Calculate costs
|
||||
vtkm::worklet::spatialstructure::SplitPropertiesCalculator splitPropertiesCalculator(
|
||||
index, NumPlanes + 1);
|
||||
invoker(splitPropertiesCalculator,
|
||||
pointsToLeft,
|
||||
pointsToRight,
|
||||
lMaxRanges,
|
||||
rMinRanges,
|
||||
segmentedSplitPlanes,
|
||||
splits);
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT IdArrayHandle
|
||||
CellLocatorBoundingIntervalHierarchy::CalculateSplitScatterIndices(const IdArrayHandle& cellIds,
|
||||
const IdArrayHandle& leqFlags,
|
||||
const IdArrayHandle& segmentIds,
|
||||
DeviceAdapter)
|
||||
{
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
vtkm::worklet::Invoker invoker(DeviceAdapter{});
|
||||
|
||||
// Count total number of true flags preceding in segment
|
||||
IdArrayHandle trueFlagCounts;
|
||||
Algorithms::ScanExclusiveByKey(segmentIds, leqFlags, trueFlagCounts);
|
||||
|
||||
// Make a counting iterator.
|
||||
CountingIdArrayHandle counts(0, 1, cellIds.GetNumberOfValues());
|
||||
|
||||
// Total number of elements in previous segment
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> countPreviousSegments;
|
||||
Algorithms::ScanInclusiveByKey(segmentIds, counts, countPreviousSegments, vtkm::Minimum());
|
||||
|
||||
// Total number of false flags so far in segment
|
||||
vtkm::cont::ArrayHandleTransform<IdArrayHandle, vtkm::worklet::spatialstructure::Invert>
|
||||
flagsInverse(leqFlags, vtkm::worklet::spatialstructure::Invert());
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> runningFalseFlagCount;
|
||||
Algorithms::ScanInclusiveByKey(segmentIds, flagsInverse, runningFalseFlagCount, vtkm::Add());
|
||||
|
||||
// Total number of false flags in segment
|
||||
IdArrayHandle totalFalseFlagSegmentCount =
|
||||
vtkm::worklet::spatialstructure::ReverseScanInclusiveByKey(
|
||||
segmentIds, runningFalseFlagCount, vtkm::Maximum(), DeviceAdapter());
|
||||
|
||||
// if point is to the left,
|
||||
// index = total number in previous segments + total number of false flags in this segment + total number of trues in previous segment
|
||||
// else
|
||||
// index = total number in previous segments + number of falses preceding it in the segment.
|
||||
IdArrayHandle scatterIndices;
|
||||
invoker(vtkm::worklet::spatialstructure::SplitIndicesCalculator{},
|
||||
leqFlags,
|
||||
trueFlagCounts,
|
||||
countPreviousSegments,
|
||||
runningFalseFlagCount,
|
||||
totalFalseFlagSegmentCount,
|
||||
scatterIndices);
|
||||
return scatterIndices;
|
||||
}
|
||||
|
||||
class CellLocatorBoundingIntervalHierarchy::BuildFunctor
|
||||
{
|
||||
protected:
|
||||
CellLocatorBoundingIntervalHierarchy* Self;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
BuildFunctor(CellLocatorBoundingIntervalHierarchy* self)
|
||||
: Self(self)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter)
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapter);
|
||||
// Accommodate into a Functor, so that this could be used with TryExecute
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
|
||||
vtkm::worklet::Invoker invoker(DeviceAdapter{});
|
||||
|
||||
vtkm::cont::DynamicCellSet cellSet = Self->GetCellSet();
|
||||
vtkm::Id numCells = cellSet.GetNumberOfCells();
|
||||
vtkm::cont::CoordinateSystem coords = Self->GetCoordinates();
|
||||
vtkm::cont::ArrayHandleVirtualCoordinates points = coords.GetData();
|
||||
|
||||
//std::cout << "No of cells: " << numCells << "\n";
|
||||
//std::cout.precision(3);
|
||||
//START_TIMER(s11);
|
||||
IdArrayHandle cellIds;
|
||||
Algorithms::Copy(CountingIdArrayHandle(0, 1, numCells), cellIds);
|
||||
IdArrayHandle segmentIds;
|
||||
Algorithms::Copy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numCells), segmentIds);
|
||||
//PRINT_TIMER("1.1", s11);
|
||||
|
||||
//START_TIMER(s12);
|
||||
CoordsArrayHandle centerXs, centerYs, centerZs;
|
||||
RangeArrayHandle xRanges, yRanges, zRanges;
|
||||
invoker(vtkm::worklet::spatialstructure::CellRangesExtracter{},
|
||||
cellSet,
|
||||
points,
|
||||
xRanges,
|
||||
yRanges,
|
||||
zRanges,
|
||||
centerXs,
|
||||
centerYs,
|
||||
centerZs);
|
||||
//PRINT_TIMER("1.2", s12);
|
||||
|
||||
bool done = false;
|
||||
//vtkm::IdComponent iteration = 0;
|
||||
vtkm::Id nodesIndexOffset = 0;
|
||||
vtkm::Id numSegments = 1;
|
||||
IdArrayHandle discardKeys;
|
||||
IdArrayHandle segmentSizes;
|
||||
segmentSizes.Allocate(1);
|
||||
segmentSizes.GetPortalControl().Set(0, numCells);
|
||||
Self->ProcessedCellIds.Allocate(numCells);
|
||||
vtkm::Id cellIdsOffset = 0;
|
||||
|
||||
IdArrayHandle parentIndices;
|
||||
parentIndices.Allocate(1);
|
||||
parentIndices.GetPortalControl().Set(0, -1);
|
||||
|
||||
while (!done)
|
||||
{
|
||||
//std::cout << "**** Iteration " << (++iteration) << " ****\n";
|
||||
//Output(segmentSizes);
|
||||
//START_TIMER(s21);
|
||||
// Calculate the X, Y, Z bounding ranges for each segment
|
||||
RangeArrayHandle perSegmentXRanges, perSegmentYRanges, perSegmentZRanges;
|
||||
Algorithms::ReduceByKey(segmentIds, xRanges, discardKeys, perSegmentXRanges, vtkm::Add());
|
||||
Algorithms::ReduceByKey(segmentIds, yRanges, discardKeys, perSegmentYRanges, vtkm::Add());
|
||||
Algorithms::ReduceByKey(segmentIds, zRanges, discardKeys, perSegmentZRanges, vtkm::Add());
|
||||
//PRINT_TIMER("2.1", s21);
|
||||
|
||||
// Expand the per segment bounding ranges, to per cell;
|
||||
RangePermutationArrayHandle segmentXRanges(segmentIds, perSegmentXRanges);
|
||||
RangePermutationArrayHandle segmentYRanges(segmentIds, perSegmentYRanges);
|
||||
RangePermutationArrayHandle segmentZRanges(segmentIds, perSegmentZRanges);
|
||||
|
||||
//START_TIMER(s22);
|
||||
// Calculate split costs for NumPlanes split planes, across X, Y and Z dimensions
|
||||
vtkm::Id numSplitPlanes = numSegments * (Self->NumPlanes + 1);
|
||||
vtkm::cont::ArrayHandle<vtkm::worklet::spatialstructure::SplitProperties> xSplits, ySplits,
|
||||
zSplits;
|
||||
xSplits.Allocate(numSplitPlanes);
|
||||
ySplits.Allocate(numSplitPlanes);
|
||||
zSplits.Allocate(numSplitPlanes);
|
||||
Self->CalculateSplitCosts(
|
||||
segmentXRanges, xRanges, centerXs, segmentIds, xSplits, DeviceAdapter());
|
||||
Self->CalculateSplitCosts(
|
||||
segmentYRanges, yRanges, centerYs, segmentIds, ySplits, DeviceAdapter());
|
||||
Self->CalculateSplitCosts(
|
||||
segmentZRanges, zRanges, centerZs, segmentIds, zSplits, DeviceAdapter());
|
||||
//PRINT_TIMER("2.2", s22);
|
||||
|
||||
segmentXRanges.ReleaseResourcesExecution();
|
||||
segmentYRanges.ReleaseResourcesExecution();
|
||||
segmentZRanges.ReleaseResourcesExecution();
|
||||
|
||||
//START_TIMER(s23);
|
||||
// Select best split plane and dimension across X, Y, Z dimension, per segment
|
||||
SplitArrayHandle segmentSplits;
|
||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> segmentPlanes;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> splitChoices;
|
||||
CountingIdArrayHandle indices(0, 1, numSegments);
|
||||
|
||||
vtkm::worklet::spatialstructure::SplitSelector worklet(
|
||||
Self->NumPlanes, Self->MaxLeafSize, Self->NumPlanes + 1);
|
||||
invoker(worklet,
|
||||
indices,
|
||||
xSplits,
|
||||
ySplits,
|
||||
zSplits,
|
||||
segmentSizes,
|
||||
segmentSplits,
|
||||
segmentPlanes,
|
||||
splitChoices);
|
||||
//PRINT_TIMER("2.3", s23);
|
||||
|
||||
// Expand the per segment split plane to per cell
|
||||
SplitPermutationArrayHandle splits(segmentIds, segmentSplits);
|
||||
CoordsPermutationArrayHandle planes(segmentIds, segmentPlanes);
|
||||
|
||||
//START_TIMER(s31);
|
||||
IdArrayHandle leqFlags;
|
||||
invoker(vtkm::worklet::spatialstructure::CalculateSplitDirectionFlag{},
|
||||
centerXs,
|
||||
centerYs,
|
||||
centerZs,
|
||||
splits,
|
||||
planes,
|
||||
leqFlags);
|
||||
//PRINT_TIMER("3.1", s31);
|
||||
|
||||
//START_TIMER(s32);
|
||||
IdArrayHandle scatterIndices =
|
||||
Self->CalculateSplitScatterIndices(cellIds, leqFlags, segmentIds, DeviceAdapter());
|
||||
IdArrayHandle newSegmentIds;
|
||||
IdPermutationArrayHandle sizes(segmentIds, segmentSizes);
|
||||
invoker(vtkm::worklet::spatialstructure::SegmentSplitter{ Self->MaxLeafSize },
|
||||
segmentIds,
|
||||
leqFlags,
|
||||
sizes,
|
||||
newSegmentIds);
|
||||
//PRINT_TIMER("3.2", s32);
|
||||
|
||||
//START_TIMER(s33);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> choices;
|
||||
Algorithms::Copy(IdPermutationArrayHandle(segmentIds, splitChoices), choices);
|
||||
cellIds = vtkm::worklet::spatialstructure::ScatterArray(cellIds, scatterIndices);
|
||||
segmentIds = vtkm::worklet::spatialstructure::ScatterArray(segmentIds, scatterIndices);
|
||||
newSegmentIds = vtkm::worklet::spatialstructure::ScatterArray(newSegmentIds, scatterIndices);
|
||||
xRanges = vtkm::worklet::spatialstructure::ScatterArray(xRanges, scatterIndices);
|
||||
yRanges = vtkm::worklet::spatialstructure::ScatterArray(yRanges, scatterIndices);
|
||||
zRanges = vtkm::worklet::spatialstructure::ScatterArray(zRanges, scatterIndices);
|
||||
centerXs = vtkm::worklet::spatialstructure::ScatterArray(centerXs, scatterIndices);
|
||||
centerYs = vtkm::worklet::spatialstructure::ScatterArray(centerYs, scatterIndices);
|
||||
centerZs = vtkm::worklet::spatialstructure::ScatterArray(centerZs, scatterIndices);
|
||||
choices = vtkm::worklet::spatialstructure::ScatterArray(choices, scatterIndices);
|
||||
//PRINT_TIMER("3.3", s33);
|
||||
|
||||
// Move the cell ids at leafs to the processed cellids list
|
||||
//START_TIMER(s41);
|
||||
IdArrayHandle nonSplitSegmentSizes;
|
||||
invoker(vtkm::worklet::spatialstructure::NonSplitIndexCalculator{ Self->MaxLeafSize },
|
||||
segmentSizes,
|
||||
nonSplitSegmentSizes);
|
||||
IdArrayHandle nonSplitSegmentIndices;
|
||||
Algorithms::ScanExclusive(nonSplitSegmentSizes, nonSplitSegmentIndices);
|
||||
IdArrayHandle runningSplitSegmentCounts;
|
||||
vtkm::Id numNewSegments = Algorithms::ScanExclusive(splitChoices, runningSplitSegmentCounts);
|
||||
//PRINT_TIMER("4.1", s41);
|
||||
|
||||
//START_TIMER(s42);
|
||||
IdArrayHandle doneCellIds;
|
||||
Algorithms::CopyIf(cellIds, choices, doneCellIds, vtkm::worklet::spatialstructure::Invert());
|
||||
Algorithms::CopySubRange(
|
||||
doneCellIds, 0, doneCellIds.GetNumberOfValues(), Self->ProcessedCellIds, cellIdsOffset);
|
||||
|
||||
cellIds = vtkm::worklet::spatialstructure::CopyIfArray(cellIds, choices, DeviceAdapter());
|
||||
newSegmentIds =
|
||||
vtkm::worklet::spatialstructure::CopyIfArray(newSegmentIds, choices, DeviceAdapter());
|
||||
xRanges = vtkm::worklet::spatialstructure::CopyIfArray(xRanges, choices, DeviceAdapter());
|
||||
yRanges = vtkm::worklet::spatialstructure::CopyIfArray(yRanges, choices, DeviceAdapter());
|
||||
zRanges = vtkm::worklet::spatialstructure::CopyIfArray(zRanges, choices, DeviceAdapter());
|
||||
centerXs = vtkm::worklet::spatialstructure::CopyIfArray(centerXs, choices, DeviceAdapter());
|
||||
centerYs = vtkm::worklet::spatialstructure::CopyIfArray(centerYs, choices, DeviceAdapter());
|
||||
centerZs = vtkm::worklet::spatialstructure::CopyIfArray(centerZs, choices, DeviceAdapter());
|
||||
//PRINT_TIMER("4.2", s42);
|
||||
|
||||
//START_TIMER(s43);
|
||||
// Make a new nodes with enough nodes for the current level, copying over the old one
|
||||
vtkm::Id nodesSize = Self->Nodes.GetNumberOfValues() + numSegments;
|
||||
vtkm::cont::ArrayHandle<vtkm::exec::CellLocatorBoundingIntervalHierarchyNode> newTree;
|
||||
newTree.Allocate(nodesSize);
|
||||
Algorithms::CopySubRange(Self->Nodes, 0, Self->Nodes.GetNumberOfValues(), newTree);
|
||||
|
||||
IdArrayHandle nextParentIndices;
|
||||
nextParentIndices.Allocate(2 * numNewSegments);
|
||||
|
||||
CountingIdArrayHandle nodesIndices(nodesIndexOffset, 1, numSegments);
|
||||
vtkm::worklet::spatialstructure::TreeLevelAdder nodesAdder(
|
||||
cellIdsOffset, nodesSize, Self->MaxLeafSize);
|
||||
invoker(nodesAdder,
|
||||
nodesIndices,
|
||||
segmentSplits,
|
||||
nonSplitSegmentIndices,
|
||||
segmentSizes,
|
||||
runningSplitSegmentCounts,
|
||||
parentIndices,
|
||||
newTree,
|
||||
nextParentIndices);
|
||||
nodesIndexOffset = nodesSize;
|
||||
cellIdsOffset += doneCellIds.GetNumberOfValues();
|
||||
Self->Nodes = newTree;
|
||||
//PRINT_TIMER("4.3", s43);
|
||||
//START_TIMER(s51);
|
||||
segmentIds = newSegmentIds;
|
||||
segmentSizes =
|
||||
Self->CalculateSegmentSizes<DeviceAdapter>(segmentIds, segmentIds.GetNumberOfValues());
|
||||
segmentIds =
|
||||
Self->GenerateSegmentIds<DeviceAdapter>(segmentSizes, segmentIds.GetNumberOfValues());
|
||||
IdArrayHandle uniqueSegmentIds;
|
||||
Algorithms::Copy(segmentIds, uniqueSegmentIds);
|
||||
Algorithms::Unique(uniqueSegmentIds);
|
||||
numSegments = uniqueSegmentIds.GetNumberOfValues();
|
||||
done = segmentIds.GetNumberOfValues() == 0;
|
||||
parentIndices = nextParentIndices;
|
||||
//PRINT_TIMER("5.1", s51);
|
||||
//std::cout << "Iteration time: " << iterationTimer.GetElapsedTime() << "\n";
|
||||
}
|
||||
//std::cout << "Total time: " << totalTimer.GetElapsedTime() << "\n";
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class CellLocatorBoundingIntervalHierarchy::PrepareForExecutionFunctor
|
||||
{
|
||||
public:
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorBoundingIntervalHierarchy& bih,
|
||||
HandleType& bihExec) const
|
||||
{
|
||||
vtkm::cont::DynamicCellSet cellSet = bih.GetCellSet();
|
||||
if (cellSet.IsType<vtkm::cont::CellSetExplicit<>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetExplicit<>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<2>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetStructured<2>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<3>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetStructured<3>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetSingleType<>>())
|
||||
{
|
||||
using CellSetType = vtkm::cont::CellSetSingleType<>;
|
||||
using ExecutionType =
|
||||
vtkm::exec::CellLocatorBoundingIntervalHierarchyExec<DeviceAdapter, CellSetType>;
|
||||
ExecutionType* execObject = new ExecutionType(bih.Nodes,
|
||||
bih.ProcessedCellIds,
|
||||
bih.GetCellSet().Cast<CellSetType>(),
|
||||
bih.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
bihExec.Reset(execObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT
|
||||
void CellLocatorBoundingIntervalHierarchy::Build()
|
||||
{
|
||||
BuildFunctor functor(this);
|
||||
vtkm::cont::TryExecute(functor);
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
const HandleType CellLocatorBoundingIntervalHierarchy::PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("BoundingIntervalHierarchy", deviceId);
|
||||
}
|
||||
|
||||
return this->ExecHandle;
|
||||
}
|
||||
|
||||
} //namespace cont
|
||||
} //namespace vtkm
|
76
vtkm/cont/CellLocatorRectilinearGrid.cxx
Normal file
76
vtkm/cont/CellLocatorRectilinearGrid.cxx
Normal file
@ -0,0 +1,76 @@
|
||||
//============================================================================
|
||||
// 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/CellLocatorRectilinearGrid.h>
|
||||
|
||||
#include <vtkm/exec/CellLocatorRectilinearGrid.h>
|
||||
|
||||
vtkm::cont::CellLocatorRectilinearGrid::CellLocatorRectilinearGrid() = default;
|
||||
|
||||
vtkm::cont::CellLocatorRectilinearGrid::~CellLocatorRectilinearGrid() = default;
|
||||
|
||||
void vtkm::cont::CellLocatorRectilinearGrid::Build()
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coords = this->GetCoordinates();
|
||||
vtkm::cont::DynamicCellSet cellSet = this->GetCellSet();
|
||||
|
||||
if (!coords.GetData().IsType<RectilinearType>())
|
||||
throw vtkm::cont::ErrorInternal("Coordinates are not rectilinear.");
|
||||
if (!cellSet.IsSameType(StructuredType()))
|
||||
throw vtkm::cont::ErrorInternal("Cells are not 3D structured.");
|
||||
|
||||
vtkm::Vec<vtkm::Id, 3> celldims =
|
||||
cellSet.Cast<StructuredType>().GetSchedulingRange(vtkm::TopologyElementTagCell());
|
||||
|
||||
this->PlaneSize = celldims[0] * celldims[1];
|
||||
this->RowSize = celldims[0];
|
||||
}
|
||||
|
||||
struct vtkm::cont::CellLocatorRectilinearGrid::PrepareForExecutionFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorRectilinearGrid& contLocator,
|
||||
HandleType& execLocator) const
|
||||
{
|
||||
using ExecutionType = vtkm::exec::CellLocatorRectilinearGrid<DeviceAdapter>;
|
||||
ExecutionType* execObject =
|
||||
new ExecutionType(contLocator.PlaneSize,
|
||||
contLocator.RowSize,
|
||||
contLocator.GetCellSet().template Cast<StructuredType>(),
|
||||
contLocator.GetCoordinates().GetData().template Cast<RectilinearType>(),
|
||||
DeviceAdapter());
|
||||
execLocator.Reset(execObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const vtkm::cont::CellLocator::HandleType
|
||||
vtkm::cont::CellLocatorRectilinearGrid::PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("CellLocatorRectilinearGrid", deviceId);
|
||||
}
|
||||
return this->ExecHandle;
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
|
||||
#include <vtkm/cont/CellLocator.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
|
||||
#include <vtkm/exec/CellLocatorRectilinearGrid.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -33,7 +29,7 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class CellLocatorRectilinearGrid : public vtkm::cont::CellLocator
|
||||
class VTKM_CONT_EXPORT CellLocatorRectilinearGrid : public vtkm::cont::CellLocator
|
||||
{
|
||||
public:
|
||||
using StructuredType = vtkm::cont::CellSetStructured<3>;
|
||||
@ -41,64 +37,23 @@ public:
|
||||
using RectilinearType =
|
||||
vtkm::cont::ArrayHandleCartesianProduct<AxisHandle, AxisHandle, AxisHandle>;
|
||||
|
||||
VTKM_CONT
|
||||
CellLocatorRectilinearGrid() = default;
|
||||
VTKM_CONT CellLocatorRectilinearGrid();
|
||||
|
||||
VTKM_CONT
|
||||
void Build() override
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coords = this->GetCoordinates();
|
||||
vtkm::cont::DynamicCellSet cellSet = this->GetCellSet();
|
||||
VTKM_CONT ~CellLocatorRectilinearGrid() override;
|
||||
|
||||
if (!coords.GetData().IsType<RectilinearType>())
|
||||
throw vtkm::cont::ErrorInternal("Coordinates are not rectilinear.");
|
||||
if (!cellSet.IsSameType(StructuredType()))
|
||||
throw vtkm::cont::ErrorInternal("Cells are not 3D structured.");
|
||||
|
||||
vtkm::Vec<vtkm::Id, 3> celldims =
|
||||
cellSet.Cast<StructuredType>().GetSchedulingRange(vtkm::TopologyElementTagCell());
|
||||
|
||||
this->PlaneSize = celldims[0] * celldims[1];
|
||||
this->RowSize = celldims[0];
|
||||
}
|
||||
|
||||
struct PrepareForExecutionFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorRectilinearGrid& contLocator,
|
||||
HandleType& execLocator) const
|
||||
{
|
||||
using ExecutionType = vtkm::exec::CellLocatorRectilinearGrid<DeviceAdapter>;
|
||||
ExecutionType* execObject =
|
||||
new ExecutionType(contLocator.PlaneSize,
|
||||
contLocator.RowSize,
|
||||
contLocator.GetCellSet().template Cast<StructuredType>(),
|
||||
contLocator.GetCoordinates().GetData().template Cast<RectilinearType>(),
|
||||
DeviceAdapter());
|
||||
execLocator.Reset(execObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
VTKM_CONT void Build() override;
|
||||
|
||||
VTKM_CONT
|
||||
const HandleType PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const override
|
||||
{
|
||||
const bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("CellLocatorRectilinearGrid", deviceId);
|
||||
}
|
||||
return this->ExecHandle;
|
||||
}
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const override;
|
||||
|
||||
private:
|
||||
vtkm::Bounds Bounds;
|
||||
vtkm::Id PlaneSize;
|
||||
vtkm::Id RowSize;
|
||||
mutable HandleType ExecHandle;
|
||||
|
||||
struct PrepareForExecutionFunctor;
|
||||
};
|
||||
|
||||
} //namespace cont
|
||||
|
82
vtkm/cont/CellLocatorUniformGrid.cxx
Normal file
82
vtkm/cont/CellLocatorUniformGrid.cxx
Normal file
@ -0,0 +1,82 @@
|
||||
//============================================================================
|
||||
// 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/Algorithm.h>
|
||||
#include <vtkm/cont/CellLocatorUniformGrid.h>
|
||||
|
||||
#include <vtkm/exec/CellLocatorUniformGrid.h>
|
||||
|
||||
vtkm::cont::CellLocatorUniformGrid::CellLocatorUniformGrid() = default;
|
||||
|
||||
vtkm::cont::CellLocatorUniformGrid::~CellLocatorUniformGrid() = default;
|
||||
|
||||
void vtkm::cont::CellLocatorUniformGrid::Build()
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coords = this->GetCoordinates();
|
||||
vtkm::cont::DynamicCellSet cellSet = this->GetCellSet();
|
||||
|
||||
if (!coords.GetData().IsType<UniformType>())
|
||||
throw vtkm::cont::ErrorBadType("Coordinate system is not uniform type");
|
||||
if (!cellSet.IsSameType(StructuredType()))
|
||||
throw vtkm::cont::ErrorBadType("Cell set is not 3D structured type");
|
||||
|
||||
Bounds = coords.GetBounds();
|
||||
CellDims = cellSet.Cast<StructuredType>().GetSchedulingRange(vtkm::TopologyElementTagCell());
|
||||
|
||||
RangeTransform[0] = static_cast<vtkm::FloatDefault>(CellDims[0]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.X.Length());
|
||||
RangeTransform[1] = static_cast<vtkm::FloatDefault>(CellDims[1]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.Y.Length());
|
||||
RangeTransform[2] = static_cast<vtkm::FloatDefault>(CellDims[2]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.Z.Length());
|
||||
}
|
||||
|
||||
struct vtkm::cont::CellLocatorUniformGrid::PrepareForExecutionFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorUniformGrid& contLocator,
|
||||
HandleType& execLocator) const
|
||||
{
|
||||
using ExecutionType = vtkm::exec::CellLocatorUniformGrid<DeviceAdapter>;
|
||||
ExecutionType* execObject =
|
||||
new ExecutionType(contLocator.Bounds,
|
||||
contLocator.RangeTransform,
|
||||
contLocator.CellDims,
|
||||
contLocator.GetCellSet().template Cast<StructuredType>(),
|
||||
contLocator.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
execLocator.Reset(execObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const vtkm::cont::CellLocator::HandleType
|
||||
vtkm::cont::CellLocatorUniformGrid::PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("CellLocatorUniformGrid", deviceId);
|
||||
}
|
||||
return this->ExecHandle;
|
||||
}
|
@ -22,10 +22,6 @@
|
||||
|
||||
#include <vtkm/cont/CellLocator.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
|
||||
#include <vtkm/exec/CellLocatorUniformGrid.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -33,71 +29,25 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class CellLocatorUniformGrid : public vtkm::cont::CellLocator
|
||||
class VTKM_CONT_EXPORT CellLocatorUniformGrid : public vtkm::cont::CellLocator
|
||||
{
|
||||
public:
|
||||
VTKM_CONT
|
||||
CellLocatorUniformGrid() = default;
|
||||
VTKM_CONT CellLocatorUniformGrid();
|
||||
|
||||
VTKM_CONT
|
||||
void Build() override
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coords = this->GetCoordinates();
|
||||
vtkm::cont::DynamicCellSet cellSet = this->GetCellSet();
|
||||
VTKM_CONT ~CellLocatorUniformGrid() override;
|
||||
|
||||
if (!coords.GetData().IsType<UniformType>())
|
||||
throw vtkm::cont::ErrorBadType("Coordinate system is not uniform type");
|
||||
if (!cellSet.IsSameType(StructuredType()))
|
||||
throw vtkm::cont::ErrorBadType("Cell set is not 3D structured type");
|
||||
|
||||
Bounds = coords.GetBounds();
|
||||
CellDims = cellSet.Cast<StructuredType>().GetSchedulingRange(vtkm::TopologyElementTagCell());
|
||||
|
||||
RangeTransform[0] = static_cast<vtkm::FloatDefault>(CellDims[0]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.X.Length());
|
||||
RangeTransform[1] = static_cast<vtkm::FloatDefault>(CellDims[1]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.Y.Length());
|
||||
RangeTransform[2] = static_cast<vtkm::FloatDefault>(CellDims[2]) /
|
||||
static_cast<vtkm::FloatDefault>(Bounds.Z.Length());
|
||||
}
|
||||
|
||||
struct PrepareForExecutionFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::CellLocatorUniformGrid& contLocator,
|
||||
HandleType& execLocator) const
|
||||
{
|
||||
using ExecutionType = vtkm::exec::CellLocatorUniformGrid<DeviceAdapter>;
|
||||
ExecutionType* execObject =
|
||||
new ExecutionType(contLocator.Bounds,
|
||||
contLocator.RangeTransform,
|
||||
contLocator.CellDims,
|
||||
contLocator.GetCellSet().template Cast<StructuredType>(),
|
||||
contLocator.GetCoordinates().GetData(),
|
||||
DeviceAdapter());
|
||||
execLocator.Reset(execObject);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
VTKM_CONT void Build() override;
|
||||
|
||||
VTKM_CONT
|
||||
const HandleType PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const override
|
||||
{
|
||||
const bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("CellLocatorUniformGrid", deviceId);
|
||||
}
|
||||
return this->ExecHandle;
|
||||
}
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const override;
|
||||
|
||||
private:
|
||||
using UniformType = vtkm::cont::ArrayHandleUniformPointCoordinates;
|
||||
using StructuredType = vtkm::cont::CellSetStructured<3>;
|
||||
|
||||
struct PrepareForExecutionFunctor;
|
||||
|
||||
vtkm::Bounds Bounds;
|
||||
vtkm::Vec<vtkm::FloatDefault, 3> RangeTransform;
|
||||
vtkm::Vec<vtkm::Id, 3> CellDims;
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.h>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.hxx>
|
||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
@ -40,6 +40,8 @@ namespace exec
|
||||
class CellInterpolationHelper : public vtkm::VirtualObjectBase
|
||||
{
|
||||
public:
|
||||
VTKM_EXEC_CONT virtual ~CellInterpolationHelper() = default;
|
||||
|
||||
VTKM_EXEC
|
||||
virtual void GetCellInfo(const vtkm::Id& cellId,
|
||||
vtkm::UInt8& cellShape,
|
||||
@ -194,6 +196,8 @@ class CellInterpolationHelper : public vtkm::cont::ExecutionObjectBase
|
||||
public:
|
||||
using HandleType = vtkm::cont::VirtualObjectHandle<vtkm::exec::CellInterpolationHelper>;
|
||||
|
||||
VTKM_CONT virtual ~CellInterpolationHelper() = default;
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT const vtkm::exec::CellInterpolationHelper* PrepareForExecution(
|
||||
DeviceAdapter device) const
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <vtkm/Bounds.h>
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecFromPortalPermute.h>
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
@ -558,34 +559,28 @@ struct TreeLevelAdder : public vtkm::worklet::WorkletMapField
|
||||
vtkm::IdComponent MaxLeafSize;
|
||||
}; // struct TreeLevelAdder
|
||||
|
||||
template <typename T, class BinaryFunctor, typename DeviceAdapter>
|
||||
template <typename T, class BinaryFunctor>
|
||||
vtkm::cont::ArrayHandle<T> ReverseScanInclusiveByKey(const vtkm::cont::ArrayHandle<T>& keys,
|
||||
const vtkm::cont::ArrayHandle<T>& values,
|
||||
BinaryFunctor binaryFunctor,
|
||||
DeviceAdapter)
|
||||
BinaryFunctor binaryFunctor)
|
||||
{
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
|
||||
vtkm::cont::ArrayHandle<T> result;
|
||||
auto reversedResult = vtkm::cont::make_ArrayHandleReverse(result);
|
||||
|
||||
Algorithms::ScanInclusiveByKey(vtkm::cont::make_ArrayHandleReverse(keys),
|
||||
vtkm::cont::make_ArrayHandleReverse(values),
|
||||
reversedResult,
|
||||
binaryFunctor);
|
||||
vtkm::cont::Algorithm::ScanInclusiveByKey(vtkm::cont::make_ArrayHandleReverse(keys),
|
||||
vtkm::cont::make_ArrayHandleReverse(values),
|
||||
reversedResult,
|
||||
binaryFunctor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T, typename U, typename DeviceAdapter>
|
||||
template <typename T, typename U>
|
||||
vtkm::cont::ArrayHandle<T> CopyIfArray(const vtkm::cont::ArrayHandle<T>& input,
|
||||
const vtkm::cont::ArrayHandle<U>& stencil,
|
||||
DeviceAdapter)
|
||||
const vtkm::cont::ArrayHandle<U>& stencil)
|
||||
{
|
||||
using Algorithms = typename vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
||||
|
||||
vtkm::cont::ArrayHandle<T> result;
|
||||
Algorithms::CopyIf(input, stencil, result);
|
||||
vtkm::cont::Algorithm::CopyIf(input, stencil, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.h>
|
||||
#include <vtkm/cont/CellLocatorBoundingIntervalHierarchy.hxx>
|
||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||
#include <vtkm/cont/Timer.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
|
Loading…
Reference in New Issue
Block a user