Support scatter/mask for CellSetExtrude
Scheduling topology map workets for `CellSetExtrude` always worked, but the there were indexing problems when a `Scatter` or a `Mask` was used. This has been corrected, and now `Scatter`s and `Mask`s are supported on topology maps on `CellSetExtrude`.
This commit is contained in:
parent
2abeec79de
commit
36352912bc
6
docs/changelog/scatter-extrude-cells.md
Normal file
6
docs/changelog/scatter-extrude-cells.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Support scatter/mask for CellSetExtrude
|
||||
|
||||
Scheduling topology map workets for `CellSetExtrude` always worked, but the
|
||||
there were indexing problems when a `Scatter` or a `Mask` was used. This
|
||||
has been corrected, and now `Scatter`s and `Mask`s are supported on
|
||||
topology maps on `CellSetExtrude`.
|
@ -7,11 +7,14 @@
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
|
||||
#include <vtkm/worklet/ScatterPermutation.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleXGCCoordinates.h>
|
||||
#include <vtkm/cont/CellSetExtrude.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <vtkm/filter/PointAverage.h>
|
||||
@ -37,6 +40,20 @@ struct CopyTopo : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
}
|
||||
};
|
||||
|
||||
struct CopyTopoScatter : public vtkm::worklet::WorkletVisitCellsWithPoints
|
||||
{
|
||||
typedef void ControlSignature(CellSetIn, FieldOutCell);
|
||||
typedef _2 ExecutionSignature(CellShape, PointIndices);
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterPermutation<vtkm::cont::StorageTagCounting>;
|
||||
|
||||
template <typename T>
|
||||
VTKM_EXEC T&& operator()(vtkm::CellShapeTagWedge, T&& t) const
|
||||
{
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
};
|
||||
|
||||
struct CopyReverseCellCount : public vtkm::worklet::WorkletVisitPointsWithCells
|
||||
{
|
||||
typedef void ControlSignature(CellSetIn, FieldOutPoint);
|
||||
@ -52,7 +69,32 @@ struct CopyReverseCellCount : public vtkm::worklet::WorkletVisitPointsWithCells
|
||||
bool valid = true;
|
||||
for (vtkm::IdComponent i = 0; i < count; ++i)
|
||||
{
|
||||
valid = valid && t[i] > 0;
|
||||
valid = valid && t[i] >= 0;
|
||||
}
|
||||
return (valid && count == t.GetNumberOfComponents()) ? count : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct CopyReverseCellCountScatter : public vtkm::worklet::WorkletVisitPointsWithCells
|
||||
{
|
||||
typedef void ControlSignature(CellSetIn, FieldOutPoint);
|
||||
typedef _2 ExecutionSignature(CellShape, CellCount, CellIndices);
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterPermutation<vtkm::cont::StorageTagCounting>;
|
||||
|
||||
template <typename T>
|
||||
VTKM_EXEC vtkm::Int32 operator()(vtkm::CellShapeTagVertex shape,
|
||||
vtkm::IdComponent count,
|
||||
T&& t) const
|
||||
{
|
||||
if (shape.Id == vtkm::CELL_SHAPE_VERTEX)
|
||||
{
|
||||
bool valid = true;
|
||||
for (vtkm::IdComponent i = 0; i < count; ++i)
|
||||
{
|
||||
valid = valid && t[i] >= 0;
|
||||
}
|
||||
return (valid && count == t.GetNumberOfComponents()) ? count : -1;
|
||||
}
|
||||
@ -61,52 +103,47 @@ struct CopyReverseCellCount : public vtkm::worklet::WorkletVisitPointsWithCells
|
||||
};
|
||||
|
||||
template <typename T, typename S>
|
||||
void verify_topo(vtkm::cont::ArrayHandle<vtkm::Vec<T, 6>, S> const& handle, vtkm::Id expectedLen)
|
||||
void verify_topo(vtkm::cont::ArrayHandle<vtkm::Vec<T, 6>, S> const& handle,
|
||||
vtkm::Id expectedLen,
|
||||
vtkm::Id skip)
|
||||
{
|
||||
auto portal = handle.ReadPortal();
|
||||
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLen, "topology portal size is incorrect");
|
||||
VTKM_TEST_ASSERT((portal.GetNumberOfValues() * skip) == expectedLen,
|
||||
"topology portal size is incorrect");
|
||||
|
||||
for (vtkm::Id i = 0; i < expectedLen - 1; ++i)
|
||||
for (vtkm::Id i = 0; i < expectedLen; i += skip)
|
||||
{
|
||||
auto v = portal.Get(i);
|
||||
auto v = portal.Get(i / skip);
|
||||
vtkm::Vec<vtkm::Id, 6> e;
|
||||
e[0] = (static_cast<vtkm::Id>(topology[0]) + (i * static_cast<vtkm::Id>(topology.size())));
|
||||
e[1] = (static_cast<vtkm::Id>(topology[1]) + (i * static_cast<vtkm::Id>(topology.size())));
|
||||
e[2] = (static_cast<vtkm::Id>(topology[2]) + (i * static_cast<vtkm::Id>(topology.size())));
|
||||
e[3] =
|
||||
(static_cast<vtkm::Id>(topology[0]) + ((i + 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
e[4] =
|
||||
(static_cast<vtkm::Id>(topology[1]) + ((i + 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
e[5] =
|
||||
(static_cast<vtkm::Id>(topology[2]) + ((i + 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
vtkm::Id offset1 = i * static_cast<vtkm::Id>(topology.size());
|
||||
vtkm::Id offset2 =
|
||||
(i < expectedLen - 1) ? (offset1 + static_cast<vtkm::Id>(topology.size())) : 0;
|
||||
e[0] = (static_cast<vtkm::Id>(topology[0]) + offset1);
|
||||
e[1] = (static_cast<vtkm::Id>(topology[1]) + offset1);
|
||||
e[2] = (static_cast<vtkm::Id>(topology[2]) + offset1);
|
||||
e[3] = (static_cast<vtkm::Id>(topology[0]) + offset2);
|
||||
e[4] = (static_cast<vtkm::Id>(topology[1]) + offset2);
|
||||
e[5] = (static_cast<vtkm::Id>(topology[2]) + offset2);
|
||||
std::cout << "v, e: " << v << ", " << e << "\n";
|
||||
VTKM_TEST_ASSERT(test_equal(v, e), "incorrect conversion of topology to Cartesian space");
|
||||
}
|
||||
|
||||
auto v = portal.Get(expectedLen - 1);
|
||||
vtkm::Vec<vtkm::Id, 6> e;
|
||||
e[0] = (static_cast<vtkm::Id>(topology[0]) +
|
||||
((expectedLen - 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
e[1] = (static_cast<vtkm::Id>(topology[1]) +
|
||||
((expectedLen - 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
e[2] = (static_cast<vtkm::Id>(topology[2]) +
|
||||
((expectedLen - 1) * static_cast<vtkm::Id>(topology.size())));
|
||||
e[3] = (static_cast<vtkm::Id>(topology[0]));
|
||||
e[4] = (static_cast<vtkm::Id>(topology[1]));
|
||||
e[5] = (static_cast<vtkm::Id>(topology[2]));
|
||||
VTKM_TEST_ASSERT(test_equal(v, e), "incorrect conversion of topology to Cartesian space");
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
void verify_reverse_topo(vtkm::cont::ArrayHandle<T, S> const& handle, vtkm::Id expectedLen)
|
||||
void verify_reverse_topo(vtkm::cont::ArrayHandle<T, S> const& handle,
|
||||
vtkm::Id expectedLen,
|
||||
vtkm::Id skip)
|
||||
{
|
||||
auto portal = handle.ReadPortal();
|
||||
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLen, "topology portal size is incorrect");
|
||||
for (vtkm::Id i = 0; i < expectedLen - 1; ++i)
|
||||
VTKM_TEST_ASSERT((portal.GetNumberOfValues() * skip) == expectedLen,
|
||||
"topology portal size is incorrect");
|
||||
for (vtkm::Id i = 0; i < expectedLen - 1; i += skip)
|
||||
{
|
||||
auto v = portal.Get(i);
|
||||
VTKM_TEST_ASSERT((v <= 2), "incorrect conversion to reverse topology");
|
||||
auto v = portal.Get(i / skip);
|
||||
std::cout << v << " ";
|
||||
VTKM_TEST_ASSERT((v == 2), "incorrect conversion to reverse topology");
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
int TestCellSetExtrude()
|
||||
{
|
||||
@ -117,22 +154,45 @@ int TestCellSetExtrude()
|
||||
VTKM_TEST_ASSERT(cells.GetNumberOfPoints() == coords.GetNumberOfValues(),
|
||||
"number of points don't match between cells and coordinates");
|
||||
|
||||
// Verify the topology by copying it into another array
|
||||
vtkm::cont::Invoker invoke;
|
||||
|
||||
std::cout << "Verify the topology by copying it into another array\n";
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<int, 6>> output;
|
||||
vtkm::worklet::DispatcherMapTopology<CopyTopo> dispatcher;
|
||||
dispatcher.Invoke(cells, output);
|
||||
verify_topo(output, 8);
|
||||
invoke(CopyTopo{}, cells, output);
|
||||
verify_topo(output, numPlanes, 1);
|
||||
}
|
||||
|
||||
std::cout << "Verify the topology works with a scatter\n";
|
||||
{
|
||||
constexpr vtkm::Id skip = 2;
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<int, 6>> output;
|
||||
invoke(CopyTopoScatter{},
|
||||
CopyTopoScatter::ScatterType(
|
||||
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, skip, numPlanes / skip)),
|
||||
cells,
|
||||
output);
|
||||
verify_topo(output, numPlanes, skip);
|
||||
}
|
||||
|
||||
// Verify the reverse topology by copying the number of cells each point is
|
||||
// used by it into another array
|
||||
std::cout << "Verify the reverse topology by copying the number of cells each point is "
|
||||
<< "used by it into another array.\n";
|
||||
{
|
||||
vtkm::cont::ArrayHandle<int> output;
|
||||
vtkm::worklet::DispatcherMapTopology<CopyReverseCellCount> dispatcher;
|
||||
dispatcher.Invoke(cells, output);
|
||||
verify_reverse_topo(output, 24);
|
||||
invoke(CopyReverseCellCount{}, cells, output);
|
||||
verify_reverse_topo(output, 3 * numPlanes, 1);
|
||||
}
|
||||
|
||||
std::cout << "Verify reverse topology map with scatter\n";
|
||||
{
|
||||
constexpr vtkm::Id skip = 2;
|
||||
vtkm::cont::ArrayHandle<int> output;
|
||||
invoke(CopyReverseCellCountScatter{},
|
||||
CopyTopoScatter::ScatterType(
|
||||
vtkm::cont::make_ArrayHandleCounting<vtkm::Id>(0, skip, (3 * numPlanes) / skip)),
|
||||
cells,
|
||||
output);
|
||||
verify_reverse_topo(output, 3 * numPlanes, skip);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -35,18 +35,17 @@ public:
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
vtkm::Id vtkmNotUsed(inputIndex),
|
||||
vtkm::IdComponent vtkmNotUsed(visitIndex),
|
||||
vtkm::Id vtkmNotUsed(outputIndex),
|
||||
vtkm::Id inputIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outputIndex,
|
||||
const ConnectivityType& connectivity)
|
||||
{
|
||||
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
|
||||
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
|
||||
const LogicalIndexType logicalIndex = connectivity.FlatToLogicalToIndex(inputIndex);
|
||||
|
||||
this->ThreadIndex = index;
|
||||
this->InputIndex = index;
|
||||
this->OutputIndex = index;
|
||||
this->VisitIndex = 0;
|
||||
this->ThreadIndex = threadIndex;
|
||||
this->InputIndex = inputIndex;
|
||||
this->OutputIndex = outputIndex;
|
||||
this->VisitIndex = visitIndex;
|
||||
this->LogicalIndex = logicalIndex;
|
||||
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
|
||||
//this->CellShape = connectivity.GetCellShape(index);
|
||||
@ -198,18 +197,17 @@ public:
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC
|
||||
ThreadIndicesTopologyMap(vtkm::Id& threadIndex,
|
||||
vtkm::Id vtkmNotUsed(inputIndex),
|
||||
vtkm::IdComponent vtkmNotUsed(visitIndex),
|
||||
vtkm::Id vtkmNotUsed(outputIndex),
|
||||
vtkm::Id inputIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outputIndex,
|
||||
const ConnectivityType& connectivity)
|
||||
{
|
||||
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
|
||||
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
|
||||
const LogicalIndexType logicalIndex = connectivity.FlatToLogicalToIndex(inputIndex);
|
||||
|
||||
this->ThreadIndex = index;
|
||||
this->InputIndex = index;
|
||||
this->OutputIndex = index;
|
||||
this->VisitIndex = 0;
|
||||
this->ThreadIndex = threadIndex;
|
||||
this->InputIndex = inputIndex;
|
||||
this->OutputIndex = outputIndex;
|
||||
this->VisitIndex = visitIndex;
|
||||
this->LogicalIndex = logicalIndex;
|
||||
this->IndicesIncident = connectivity.GetIndices(logicalIndex);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user