vtk-m2/vtkm/filter/GhostCellClassify.hxx
Robert Maynard 16a6af5857 Some filters had unnecessary DoMapField methods.
The CrossProduct and DotProduct are field filters and therefore
fields are automatically propagated instead of calling DoMapField.

As GhostCellClassify is passing through all fields, it can
override `MapFieldOntoOutput` and skip the deduction of the
Field to an ArrayHandle for better compile time.
2019-09-10 15:26:16 -04:00

183 lines
5.6 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/CellClassification.h>
#include <vtkm/RangeId.h>
#include <vtkm/RangeId2.h>
#include <vtkm/RangeId3.h>
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/worklet/WorkletMapField.h>
namespace
{
struct TypeUInt8 : vtkm::ListTagBase<vtkm::UInt8>
{
};
class SetStructuredGhostCells1D : public vtkm::worklet::WorkletMapField
{
public:
SetStructuredGhostCells1D(const vtkm::Id& dim, const vtkm::Id& numLayers = 1)
: Dim(dim)
, NumLayers(numLayers)
, Range(NumLayers, Dim - NumLayers)
{
}
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
template <typename T>
VTKM_EXEC void operator()(const vtkm::Id& cellIndex, T& value) const
{
value = (Range.Contains(cellIndex) ? NormalCell : DuplicateCell);
}
private:
vtkm::Id Dim;
vtkm::Id NumLayers;
vtkm::RangeId Range;
static constexpr vtkm::UInt8 NormalCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::NORMAL);
static constexpr vtkm::UInt8 DuplicateCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::GHOST);
};
class SetStructuredGhostCells2D : public vtkm::worklet::WorkletMapField
{
public:
SetStructuredGhostCells2D(const vtkm::Id2& dims, const vtkm::Id& numLayers = 1)
: Dims(dims)
, NumLayers(numLayers)
, Range(NumLayers, Dims[0] - NumLayers, NumLayers, Dims[1] - NumLayers)
{
}
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
template <typename T>
VTKM_EXEC void operator()(const vtkm::Id& cellIndex, T& value) const
{
vtkm::Id2 ij(cellIndex % Dims[0], cellIndex / Dims[0]);
value = (Range.Contains(ij) ? NormalCell : DuplicateCell);
}
private:
vtkm::Id2 Dims;
vtkm::Id NumLayers;
vtkm::RangeId2 Range;
static constexpr vtkm::UInt8 NormalCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::NORMAL);
static constexpr vtkm::UInt8 DuplicateCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::GHOST);
};
class SetStructuredGhostCells3D : public vtkm::worklet::WorkletMapField
{
public:
SetStructuredGhostCells3D(const vtkm::Id3& dims, const vtkm::Id& numLayers = 1)
: Dims(dims)
, NumLayers(numLayers)
, Range(NumLayers,
Dims[0] - NumLayers,
NumLayers,
Dims[1] - NumLayers,
NumLayers,
Dims[2] - NumLayers)
{
}
using ControlSignature = void(FieldIn, FieldOut);
using ExecutionSignature = void(_1, _2);
template <typename T>
VTKM_EXEC void operator()(const vtkm::Id& cellIndex, T& value) const
{
vtkm::Id3 ijk(
cellIndex % Dims[0], (cellIndex / Dims[0]) % Dims[1], cellIndex / (Dims[0] * Dims[1]));
value = (Range.Contains(ijk) ? NormalCell : DuplicateCell);
}
private:
vtkm::Id3 Dims;
vtkm::Id NumLayers;
vtkm::RangeId3 Range;
static constexpr vtkm::UInt8 NormalCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::NORMAL);
static constexpr vtkm::UInt8 DuplicateCell =
static_cast<vtkm::UInt8>(vtkm::CellClassification::GHOST);
};
};
namespace vtkm
{
namespace filter
{
inline VTKM_CONT GhostCellClassify::GhostCellClassify()
{
}
template <typename Policy>
inline VTKM_CONT vtkm::cont::DataSet GhostCellClassify::DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<Policy>)
{
const vtkm::cont::DynamicCellSet& cellset = input.GetCellSet();
vtkm::Id numCells = cellset.GetNumberOfCells();
vtkm::cont::ArrayHandleIndex indexArray(numCells);
vtkm::cont::ArrayHandle<vtkm::UInt8> ghosts;
ghosts.Allocate(numCells);
//Structured cases are easy...
if (cellset.template IsType<vtkm::cont::CellSetStructured<1>>())
{
if (numCells <= 2)
throw vtkm::cont::ErrorFilterExecution("insufficient number of cells for GhostCellClassify.");
vtkm::cont::CellSetStructured<1> cellset1d = cellset.Cast<vtkm::cont::CellSetStructured<1>>();
SetStructuredGhostCells1D structuredGhosts1D(cellset1d.GetCellDimensions());
this->Invoke(structuredGhosts1D, indexArray, ghosts);
}
else if (cellset.template IsType<vtkm::cont::CellSetStructured<2>>())
{
if (numCells <= 4)
throw vtkm::cont::ErrorFilterExecution("insufficient number of cells for GhostCellClassify.");
vtkm::cont::CellSetStructured<2> cellset2d = cellset.Cast<vtkm::cont::CellSetStructured<2>>();
SetStructuredGhostCells2D structuredGhosts2D(cellset2d.GetCellDimensions());
this->Invoke(structuredGhosts2D, indexArray, ghosts);
}
else if (cellset.template IsType<vtkm::cont::CellSetStructured<3>>())
{
if (numCells <= 8)
throw vtkm::cont::ErrorFilterExecution("insufficient number of cells for GhostCellClassify.");
vtkm::cont::CellSetStructured<3> cellset3d = cellset.Cast<vtkm::cont::CellSetStructured<3>>();
SetStructuredGhostCells3D structuredGhosts3D(cellset3d.GetCellDimensions());
this->Invoke(structuredGhosts3D, indexArray, ghosts);
}
else
{
throw vtkm::cont::ErrorFilterExecution("Unsupported cellset type for GhostCellClassify.");
}
return CreateResultFieldCell(input, ghosts, "vtkmGhostCells");
}
}
}