2015-07-09 03:10:19 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2015-07-09 03:10:19 +00:00
|
|
|
// 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.
|
|
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_worklet_ExternalFaces_h
|
|
|
|
#define vtk_m_worklet_ExternalFaces_h
|
|
|
|
|
2015-08-28 18:48:00 +00:00
|
|
|
#include <vtkm/CellShape.h>
|
2017-08-24 18:11:45 +00:00
|
|
|
#include <vtkm/Hash.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
#include <vtkm/Math.h>
|
|
|
|
|
2016-12-02 03:26:49 +00:00
|
|
|
#include <vtkm/exec/CellFace.h>
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
#include <vtkm/cont/Algorithm.h>
|
|
|
|
#include <vtkm/cont/ArrayCopy.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
2017-08-03 15:19:22 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleConcatenate.h>
|
2015-08-17 18:42:58 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleConstant.h>
|
2017-07-19 19:35:31 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleGroupVec.h>
|
2017-05-18 14:51:24 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
|
2015-09-15 04:11:09 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
2015-08-17 18:42:58 +00:00
|
|
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
2017-08-03 15:19:22 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleTransform.h>
|
2015-08-17 18:42:58 +00:00
|
|
|
#include <vtkm/cont/CellSetExplicit.h>
|
|
|
|
#include <vtkm/cont/DataSet.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
#include <vtkm/cont/Field.h>
|
2015-07-14 20:33:55 +00:00
|
|
|
#include <vtkm/cont/Timer.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
|
|
|
|
#include <vtkm/worklet/DispatcherMapTopology.h>
|
2016-12-06 00:30:57 +00:00
|
|
|
#include <vtkm/worklet/DispatcherReduceByKey.h>
|
|
|
|
#include <vtkm/worklet/Keys.h>
|
|
|
|
#include <vtkm/worklet/ScatterCounting.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
#include <vtkm/worklet/WorkletMapTopology.h>
|
2016-12-06 00:30:57 +00:00
|
|
|
#include <vtkm/worklet/WorkletReduceByKey.h>
|
2015-07-09 03:10:19 +00:00
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace worklet
|
|
|
|
{
|
|
|
|
|
2015-08-14 19:47:25 +00:00
|
|
|
struct ExternalFaces
|
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
//Worklet that returns the number of external faces for each structured cell
|
|
|
|
class NumExternalFacesPerStructuredCell : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn inCellSet,
|
2019-01-10 18:59:25 +00:00
|
|
|
FieldOut numFacesInCell,
|
|
|
|
FieldInPoint pointCoordinates);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _2(CellShape, _3);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
VTKM_CONT
|
2017-08-03 20:08:06 +00:00
|
|
|
NumExternalFacesPerStructuredCell(const vtkm::Vec<vtkm::Float64, 3>& min_point,
|
|
|
|
const vtkm::Vec<vtkm::Float64, 3>& max_point)
|
2017-07-19 19:35:31 +00:00
|
|
|
: MinPoint(min_point)
|
|
|
|
, MaxPoint(max_point)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_EXEC
|
2017-08-03 20:08:06 +00:00
|
|
|
inline vtkm::IdComponent CountExternalFacesOnDimension(vtkm::Float64 grid_min,
|
|
|
|
vtkm::Float64 grid_max,
|
|
|
|
vtkm::Float64 cell_min,
|
|
|
|
vtkm::Float64 cell_max) const
|
2017-07-19 19:35:31 +00:00
|
|
|
{
|
|
|
|
vtkm::IdComponent count = 0;
|
|
|
|
|
|
|
|
bool cell_min_at_grid_boundary = cell_min <= grid_min;
|
|
|
|
bool cell_max_at_grid_boundary = cell_max >= grid_max;
|
|
|
|
|
2017-08-03 17:59:53 +00:00
|
|
|
if (cell_min_at_grid_boundary && !cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
count++;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-08-03 17:59:53 +00:00
|
|
|
else if (!cell_min_at_grid_boundary && cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
count++;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-08-03 17:59:53 +00:00
|
|
|
else if (cell_min_at_grid_boundary && cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
count += 2;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename CellShapeTag, typename PointCoordVecType>
|
|
|
|
VTKM_EXEC vtkm::IdComponent operator()(CellShapeTag shape,
|
|
|
|
const PointCoordVecType& pointCoordinates) const
|
|
|
|
{
|
2017-09-21 14:33:17 +00:00
|
|
|
(void)shape; // C4100 false positive workaround
|
2017-07-19 19:35:31 +00:00
|
|
|
VTKM_ASSERT(shape.Id == CELL_SHAPE_HEXAHEDRON);
|
|
|
|
|
|
|
|
vtkm::IdComponent count = 0;
|
|
|
|
|
|
|
|
count += CountExternalFacesOnDimension(
|
|
|
|
MinPoint[0], MaxPoint[0], pointCoordinates[0][0], pointCoordinates[1][0]);
|
|
|
|
|
|
|
|
count += CountExternalFacesOnDimension(
|
|
|
|
MinPoint[1], MaxPoint[1], pointCoordinates[0][1], pointCoordinates[3][1]);
|
|
|
|
|
|
|
|
count += CountExternalFacesOnDimension(
|
|
|
|
MinPoint[2], MaxPoint[2], pointCoordinates[0][2], pointCoordinates[4][2]);
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-08-03 20:08:06 +00:00
|
|
|
vtkm::Vec<vtkm::Float64, 3> MinPoint;
|
|
|
|
vtkm::Vec<vtkm::Float64, 3> MaxPoint;
|
2017-07-19 19:35:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//Worklet that finds face connectivity for each structured cell
|
|
|
|
class BuildConnectivityStructured : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn inCellSet,
|
2017-07-19 19:35:31 +00:00
|
|
|
WholeCellSetIn<> inputCell,
|
2019-01-10 18:59:25 +00:00
|
|
|
FieldOut faceShapes,
|
|
|
|
FieldOut facePointCount,
|
|
|
|
FieldOut faceConnectivity,
|
|
|
|
FieldInPoint pointCoordinates);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(CellShape, VisitIndex, InputIndex, _2, _3, _4, _5, _6);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CountArrayType>
|
|
|
|
VTKM_CONT static ScatterType MakeScatter(const CountArrayType& countArray)
|
2017-07-19 19:35:31 +00:00
|
|
|
{
|
|
|
|
VTKM_IS_ARRAY_HANDLE(CountArrayType);
|
2018-08-30 15:53:18 +00:00
|
|
|
return ScatterType(countArray);
|
2017-07-19 19:35:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_CONT
|
2017-08-03 20:08:06 +00:00
|
|
|
BuildConnectivityStructured(const vtkm::Vec<vtkm::Float64, 3>& min_point,
|
Move Scatter from Worklet to Dispatcher
Previously, when a Worklet needed a scatter, the scatter object was
stored in the Worklet object. That was problematic because that means
the Scatter, which is a control object, was shoved into the execution
environment.
To prevent that, move the Scatter into the Dispatcher object. The
worklet still declares a ScatterType alias, but no longer has a
GetScatter method. Instead, the Dispatcher now takes a Scatter object in
its constructor. If using the default scatter (ScatterIdentity), the
default constructor is used. If using another type of Scatter that
requires data to set up its state, then the caller of the worklet needs
to provide that to the dispatcher. For convenience, worklets are
encouraged to have a MakeScatter method to help construct a proper
scatter object.
2018-04-27 04:43:51 +00:00
|
|
|
const vtkm::Vec<vtkm::Float64, 3>& max_point)
|
2017-07-19 19:35:31 +00:00
|
|
|
: MinPoint(min_point)
|
|
|
|
, MaxPoint(max_point)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
enum FaceType
|
|
|
|
{
|
|
|
|
FACE_GRID_MIN,
|
|
|
|
FACE_GRID_MAX,
|
|
|
|
FACE_GRID_MIN_AND_MAX,
|
|
|
|
FACE_NONE
|
|
|
|
};
|
|
|
|
|
|
|
|
VTKM_EXEC
|
2017-08-03 20:08:06 +00:00
|
|
|
inline bool FoundFaceOnDimension(vtkm::Float64 grid_min,
|
|
|
|
vtkm::Float64 grid_max,
|
|
|
|
vtkm::Float64 cell_min,
|
|
|
|
vtkm::Float64 cell_max,
|
2017-08-03 17:59:53 +00:00
|
|
|
vtkm::IdComponent& faceIndex,
|
2017-07-19 19:35:31 +00:00
|
|
|
vtkm::IdComponent& count,
|
|
|
|
vtkm::IdComponent dimensionFaceOffset,
|
|
|
|
vtkm::IdComponent visitIndex) const
|
|
|
|
{
|
|
|
|
bool cell_min_at_grid_boundary = cell_min <= grid_min;
|
|
|
|
bool cell_max_at_grid_boundary = cell_max >= grid_max;
|
|
|
|
|
|
|
|
FaceType Faces = FaceType::FACE_NONE;
|
|
|
|
|
2017-08-03 17:59:53 +00:00
|
|
|
if (cell_min_at_grid_boundary && !cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
Faces = FaceType::FACE_GRID_MIN;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-08-03 17:59:53 +00:00
|
|
|
else if (!cell_min_at_grid_boundary && cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
Faces = FaceType::FACE_GRID_MAX;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-08-03 17:59:53 +00:00
|
|
|
else if (cell_min_at_grid_boundary && cell_max_at_grid_boundary)
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
Faces = FaceType::FACE_GRID_MIN_AND_MAX;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
if (Faces == FaceType::FACE_NONE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Faces == FaceType::FACE_GRID_MIN)
|
|
|
|
{
|
|
|
|
if (visitIndex == count)
|
|
|
|
{
|
|
|
|
faceIndex = dimensionFaceOffset;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
count++;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-07-19 19:35:31 +00:00
|
|
|
}
|
|
|
|
else if (Faces == FaceType::FACE_GRID_MAX)
|
|
|
|
{
|
|
|
|
if (visitIndex == count)
|
|
|
|
{
|
|
|
|
faceIndex = dimensionFaceOffset + 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
2017-08-03 20:08:06 +00:00
|
|
|
{
|
2017-07-19 19:35:31 +00:00
|
|
|
count++;
|
2017-08-03 20:08:06 +00:00
|
|
|
}
|
2017-07-19 19:35:31 +00:00
|
|
|
}
|
|
|
|
else if (Faces == FaceType::FACE_GRID_MIN_AND_MAX)
|
|
|
|
{
|
|
|
|
if (visitIndex == count)
|
|
|
|
{
|
|
|
|
faceIndex = dimensionFaceOffset;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
if (visitIndex == count)
|
|
|
|
{
|
|
|
|
faceIndex = dimensionFaceOffset + 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename PointCoordVecType>
|
|
|
|
VTKM_EXEC inline vtkm::IdComponent FindFaceIndexForVisit(
|
|
|
|
vtkm::IdComponent visitIndex,
|
|
|
|
const PointCoordVecType& pointCoordinates) const
|
|
|
|
{
|
|
|
|
vtkm::IdComponent count = 0;
|
2017-08-03 17:59:53 +00:00
|
|
|
vtkm::IdComponent faceIndex = 0;
|
2017-07-19 19:35:31 +00:00
|
|
|
// Search X dimension
|
|
|
|
if (!FoundFaceOnDimension(MinPoint[0],
|
|
|
|
MaxPoint[0],
|
|
|
|
pointCoordinates[0][0],
|
|
|
|
pointCoordinates[1][0],
|
|
|
|
faceIndex,
|
|
|
|
count,
|
|
|
|
0,
|
|
|
|
visitIndex))
|
|
|
|
{
|
|
|
|
// Search Y dimension
|
|
|
|
if (!FoundFaceOnDimension(MinPoint[1],
|
|
|
|
MaxPoint[1],
|
|
|
|
pointCoordinates[0][1],
|
|
|
|
pointCoordinates[3][1],
|
|
|
|
faceIndex,
|
|
|
|
count,
|
|
|
|
2,
|
|
|
|
visitIndex))
|
|
|
|
{
|
|
|
|
// Search Z dimension
|
|
|
|
FoundFaceOnDimension(MinPoint[2],
|
|
|
|
MaxPoint[2],
|
|
|
|
pointCoordinates[0][2],
|
|
|
|
pointCoordinates[4][2],
|
|
|
|
faceIndex,
|
|
|
|
count,
|
|
|
|
4,
|
|
|
|
visitIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return faceIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename CellShapeTag,
|
|
|
|
typename CellSetType,
|
|
|
|
typename PointCoordVecType,
|
|
|
|
typename ConnectivityType>
|
|
|
|
VTKM_EXEC void operator()(CellShapeTag shape,
|
|
|
|
vtkm::IdComponent visitIndex,
|
|
|
|
vtkm::Id inputIndex,
|
|
|
|
const CellSetType& cellSet,
|
|
|
|
vtkm::UInt8& shapeOut,
|
|
|
|
vtkm::IdComponent& numFacePointsOut,
|
|
|
|
ConnectivityType& faceConnectivity,
|
|
|
|
const PointCoordVecType& pointCoordinates) const
|
|
|
|
{
|
|
|
|
VTKM_ASSERT(shape.Id == CELL_SHAPE_HEXAHEDRON);
|
|
|
|
|
2017-08-03 17:59:53 +00:00
|
|
|
vtkm::IdComponent faceIndex = FindFaceIndexForVisit(visitIndex, pointCoordinates);
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2018-02-21 19:51:15 +00:00
|
|
|
const vtkm::IdComponent numFacePoints =
|
|
|
|
vtkm::exec::CellFaceNumberOfPoints(faceIndex, shape, *this);
|
2017-08-03 17:59:53 +00:00
|
|
|
VTKM_ASSERT(numFacePoints == faceConnectivity.GetNumberOfComponents());
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(inputIndex);
|
|
|
|
|
|
|
|
shapeOut = vtkm::CELL_SHAPE_QUAD;
|
|
|
|
numFacePointsOut = 4;
|
|
|
|
|
|
|
|
for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++)
|
|
|
|
{
|
2018-02-21 19:51:15 +00:00
|
|
|
faceConnectivity[facePointIndex] =
|
2018-03-23 04:37:33 +00:00
|
|
|
inCellIndices[vtkm::exec::CellFaceLocalIndex(facePointIndex, faceIndex, shape, *this)];
|
2017-07-19 19:35:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-08-03 20:08:06 +00:00
|
|
|
vtkm::Vec<vtkm::Float64, 3> MinPoint;
|
|
|
|
vtkm::Vec<vtkm::Float64, 3> MaxPoint;
|
2017-07-19 19:35:31 +00:00
|
|
|
};
|
|
|
|
|
2015-08-14 19:47:25 +00:00
|
|
|
//Worklet that returns the number of faces for each cell/shape
|
2016-12-06 00:30:57 +00:00
|
|
|
class NumFacesPerCell : public vtkm::worklet::WorkletMapPointToCell
|
2015-08-14 19:47:25 +00:00
|
|
|
{
|
|
|
|
public:
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(CellSetIn inCellSet, FieldOut numFacesInCell);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _2(CellShape);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename CellShapeTag>
|
|
|
|
VTKM_EXEC vtkm::IdComponent operator()(CellShapeTag shape) const
|
2015-07-09 03:10:19 +00:00
|
|
|
{
|
2016-12-06 00:30:57 +00:00
|
|
|
return vtkm::exec::CellFaceNumberOfFaces(shape, *this);
|
2015-08-14 19:47:25 +00:00
|
|
|
}
|
|
|
|
};
|
2015-07-09 03:10:19 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
//Worklet that identifies a cell face by a hash value. Not necessarily completely unique.
|
2016-12-06 00:30:57 +00:00
|
|
|
class FaceHash : public vtkm::worklet::WorkletMapPointToCell
|
2015-08-14 19:47:25 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn cellset,
|
2019-01-10 18:59:25 +00:00
|
|
|
FieldOut faceHashes,
|
|
|
|
FieldOut originCells,
|
|
|
|
FieldOut originFaces);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(_2, _3, _4, CellShape, FromIndices, InputIndex, VisitIndex);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2016-12-06 00:30:57 +00:00
|
|
|
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename CellShapeTag, typename CellNodeVecType>
|
2017-08-24 18:11:45 +00:00
|
|
|
VTKM_EXEC void operator()(vtkm::HashType& faceHash,
|
2017-05-26 17:53:28 +00:00
|
|
|
vtkm::Id& cellIndex,
|
|
|
|
vtkm::IdComponent& faceIndex,
|
|
|
|
CellShapeTag shape,
|
|
|
|
const CellNodeVecType& cellNodeIds,
|
|
|
|
vtkm::Id inputIndex,
|
2017-05-18 14:29:41 +00:00
|
|
|
vtkm::IdComponent visitIndex) const
|
2015-08-14 19:47:25 +00:00
|
|
|
{
|
2017-08-29 18:26:29 +00:00
|
|
|
faceHash = vtkm::Hash(vtkm::exec::CellFaceCanonicalId(visitIndex, shape, cellNodeIds, *this));
|
2016-12-06 00:30:57 +00:00
|
|
|
|
|
|
|
cellIndex = inputIndex;
|
|
|
|
faceIndex = visitIndex;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
// Worklet that identifies the number of cells written out per face.
|
|
|
|
// Because there can be collisions in the face ids, this instance might
|
|
|
|
// represent multiple faces, which have to be checked. The resulting
|
|
|
|
// number is the total number of external faces.
|
2016-12-06 00:30:57 +00:00
|
|
|
class FaceCounts : public vtkm::worklet::WorkletReduceByKey
|
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(KeysIn keys,
|
2017-08-24 18:11:45 +00:00
|
|
|
WholeCellSetIn<> inputCells,
|
2019-01-10 18:59:25 +00:00
|
|
|
ValuesIn originCells,
|
|
|
|
ValuesIn originFaces,
|
|
|
|
ReducedValuesOut numOutputCells);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _5(_2, _3, _4);
|
2016-12-06 00:30:57 +00:00
|
|
|
using InputDomain = _1;
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
|
|
|
VTKM_EXEC vtkm::IdComponent operator()(const CellSetType& cellSet,
|
|
|
|
const OriginCellsType& originCells,
|
|
|
|
const OriginFacesType& originFaces) const
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::IdComponent numCellsOnHash = originCells.GetNumberOfComponents();
|
|
|
|
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numCellsOnHash);
|
|
|
|
|
|
|
|
// Start by assuming all faces are unique, then remove one for each
|
|
|
|
// face we find a duplicate for.
|
|
|
|
vtkm::IdComponent numExternalFaces = numCellsOnHash;
|
|
|
|
|
|
|
|
for (vtkm::IdComponent myIndex = 0;
|
|
|
|
myIndex < numCellsOnHash - 1; // Don't need to check last face
|
|
|
|
myIndex++)
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::Id3 myFace =
|
2017-08-29 18:26:29 +00:00
|
|
|
vtkm::exec::CellFaceCanonicalId(originFaces[myIndex],
|
2017-08-24 18:11:45 +00:00
|
|
|
cellSet.GetCellShape(originCells[myIndex]),
|
|
|
|
cellSet.GetIndices(originCells[myIndex]),
|
|
|
|
*this);
|
|
|
|
for (vtkm::IdComponent otherIndex = myIndex + 1; otherIndex < numCellsOnHash; otherIndex++)
|
|
|
|
{
|
|
|
|
vtkm::Id3 otherFace =
|
2017-08-29 18:26:29 +00:00
|
|
|
vtkm::exec::CellFaceCanonicalId(originFaces[otherIndex],
|
2017-08-24 18:11:45 +00:00
|
|
|
cellSet.GetCellShape(originCells[otherIndex]),
|
|
|
|
cellSet.GetIndices(originCells[otherIndex]),
|
|
|
|
*this);
|
|
|
|
if (myFace == otherFace)
|
|
|
|
{
|
|
|
|
// Faces are the same. Must be internal. Remove 2, one for each face. We don't have to
|
|
|
|
// worry about otherFace matching anything else because a proper topology will have at
|
|
|
|
// most 2 cells sharing a face, so there should be no more matches.
|
|
|
|
numExternalFaces -= 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-08-14 19:47:25 +00:00
|
|
|
}
|
2017-08-24 18:11:45 +00:00
|
|
|
|
|
|
|
return numExternalFaces;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Resolves duplicate hashes by finding a specified unique face for a given hash.
|
|
|
|
// Given a cell set (from a WholeCellSetIn) and the cell/face id pairs for each face
|
|
|
|
// associated with a given hash, returns the index of the cell/face provided of the
|
|
|
|
// visitIndex-th unique face. Basically, this method searches through all the cell/face
|
|
|
|
// pairs looking for unique sets and returns the one associated with visitIndex.
|
|
|
|
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
|
|
|
VTKM_EXEC static vtkm::IdComponent FindUniqueFace(const CellSetType& cellSet,
|
|
|
|
const OriginCellsType& originCells,
|
|
|
|
const OriginFacesType& originFaces,
|
|
|
|
vtkm::IdComponent visitIndex,
|
|
|
|
const vtkm::exec::FunctorBase* self)
|
|
|
|
{
|
|
|
|
vtkm::IdComponent numCellsOnHash = originCells.GetNumberOfComponents();
|
|
|
|
VTKM_ASSERT(originFaces.GetNumberOfComponents() == numCellsOnHash);
|
|
|
|
|
|
|
|
// Find the visitIndex-th unique face.
|
|
|
|
vtkm::IdComponent numFound = 0;
|
|
|
|
vtkm::IdComponent myIndex = 0;
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
VTKM_ASSERT(myIndex < numCellsOnHash);
|
2017-08-29 18:26:29 +00:00
|
|
|
vtkm::Id3 myFace = vtkm::exec::CellFaceCanonicalId(originFaces[myIndex],
|
2017-08-24 18:11:45 +00:00
|
|
|
cellSet.GetCellShape(originCells[myIndex]),
|
|
|
|
cellSet.GetIndices(originCells[myIndex]),
|
|
|
|
*self);
|
|
|
|
bool foundPair = false;
|
|
|
|
for (vtkm::IdComponent otherIndex = myIndex + 1; otherIndex < numCellsOnHash; otherIndex++)
|
2016-12-02 03:26:49 +00:00
|
|
|
{
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::Id3 otherFace =
|
2017-08-29 18:26:29 +00:00
|
|
|
vtkm::exec::CellFaceCanonicalId(originFaces[otherIndex],
|
2017-08-24 18:11:45 +00:00
|
|
|
cellSet.GetCellShape(originCells[otherIndex]),
|
|
|
|
cellSet.GetIndices(originCells[otherIndex]),
|
|
|
|
*self);
|
|
|
|
if (myFace == otherFace)
|
|
|
|
{
|
|
|
|
// Faces are the same. Must be internal.
|
|
|
|
foundPair = true;
|
|
|
|
break;
|
|
|
|
}
|
2016-12-06 00:30:57 +00:00
|
|
|
}
|
2017-08-24 18:11:45 +00:00
|
|
|
|
|
|
|
if (!foundPair)
|
|
|
|
{
|
|
|
|
if (numFound == visitIndex)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
numFound++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
myIndex++;
|
2016-12-06 00:30:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
return myIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
// Worklet that returns the number of points for each outputted face.
|
|
|
|
// Have to manage the case where multiple faces have the same hash.
|
2016-12-06 00:30:57 +00:00
|
|
|
class NumPointsPerFace : public vtkm::worklet::WorkletReduceByKey
|
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(KeysIn keys,
|
2017-05-26 17:53:28 +00:00
|
|
|
WholeCellSetIn<> inputCells,
|
2019-01-10 18:59:25 +00:00
|
|
|
ValuesIn originCells,
|
|
|
|
ValuesIn originFaces,
|
|
|
|
ReducedValuesOut numPointsInFace);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _5(_2, _3, _4, VisitIndex);
|
2016-12-06 00:30:57 +00:00
|
|
|
using InputDomain = _1;
|
|
|
|
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CountArrayType>
|
|
|
|
VTKM_CONT static ScatterType MakeScatter(const CountArrayType& countArray)
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
|
|
|
VTKM_IS_ARRAY_HANDLE(CountArrayType);
|
2018-08-30 15:53:18 +00:00
|
|
|
return ScatterType(countArray);
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename CellSetType, typename OriginCellsType, typename OriginFacesType>
|
|
|
|
VTKM_EXEC vtkm::IdComponent operator()(const CellSetType& cellSet,
|
|
|
|
const OriginCellsType& originCells,
|
2017-08-24 18:11:45 +00:00
|
|
|
const OriginFacesType& originFaces,
|
|
|
|
vtkm::IdComponent visitIndex) const
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::IdComponent myIndex =
|
|
|
|
ExternalFaces::FindUniqueFace(cellSet, originCells, originFaces, visitIndex, this);
|
|
|
|
|
2017-05-26 17:53:28 +00:00
|
|
|
return vtkm::exec::CellFaceNumberOfPoints(
|
2017-08-24 18:11:45 +00:00
|
|
|
originFaces[myIndex], cellSet.GetCellShape(originCells[myIndex]), *this);
|
2016-12-06 00:30:57 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Worklet that returns the shape and connectivity for each external face
|
|
|
|
class BuildConnectivity : public vtkm::worklet::WorkletReduceByKey
|
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(KeysIn keys,
|
2017-05-26 17:53:28 +00:00
|
|
|
WholeCellSetIn<> inputCells,
|
2019-01-10 18:59:25 +00:00
|
|
|
ValuesIn originCells,
|
|
|
|
ValuesIn originFaces,
|
|
|
|
ReducedValuesOut shapesOut,
|
|
|
|
ReducedValuesOut connectivityOut,
|
|
|
|
ReducedValuesOut cellIdMapOut);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(_2, _3, _4, VisitIndex, _5, _6, _7);
|
2016-12-06 00:30:57 +00:00
|
|
|
using InputDomain = _1;
|
|
|
|
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2017-05-26 17:53:28 +00:00
|
|
|
template <typename CellSetType,
|
|
|
|
typename OriginCellsType,
|
|
|
|
typename OriginFacesType,
|
2017-05-18 14:29:41 +00:00
|
|
|
typename ConnectivityType>
|
2017-05-26 17:53:28 +00:00
|
|
|
VTKM_EXEC void operator()(const CellSetType& cellSet,
|
|
|
|
const OriginCellsType& originCells,
|
|
|
|
const OriginFacesType& originFaces,
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::IdComponent visitIndex,
|
2017-05-26 17:53:28 +00:00
|
|
|
vtkm::UInt8& shapeOut,
|
2017-07-31 14:06:33 +00:00
|
|
|
ConnectivityType& connectivityOut,
|
|
|
|
vtkm::Id& cellIdMapOut) const
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
2018-02-21 19:51:15 +00:00
|
|
|
const vtkm::IdComponent myIndex =
|
2017-08-24 18:11:45 +00:00
|
|
|
ExternalFaces::FindUniqueFace(cellSet, originCells, originFaces, visitIndex, this);
|
2018-02-21 19:51:15 +00:00
|
|
|
const vtkm::IdComponent myFace = originFaces[myIndex];
|
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
typename CellSetType::CellShapeTag shapeIn = cellSet.GetCellShape(originCells[myIndex]);
|
2018-02-21 19:51:15 +00:00
|
|
|
shapeOut = vtkm::exec::CellFaceShape(myFace, shapeIn, *this);
|
2017-08-24 18:11:45 +00:00
|
|
|
cellIdMapOut = originCells[myIndex];
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2018-02-21 19:51:15 +00:00
|
|
|
const vtkm::IdComponent numFacePoints =
|
|
|
|
vtkm::exec::CellFaceNumberOfPoints(myFace, shapeIn, *this);
|
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
VTKM_ASSERT(numFacePoints == connectivityOut.GetNumberOfComponents());
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
typename CellSetType::IndicesType inCellIndices = cellSet.GetIndices(originCells[myIndex]);
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
for (vtkm::IdComponent facePointIndex = 0; facePointIndex < numFacePoints; facePointIndex++)
|
2016-12-06 00:30:57 +00:00
|
|
|
{
|
2018-02-21 19:51:15 +00:00
|
|
|
connectivityOut[facePointIndex] =
|
2018-03-23 04:37:33 +00:00
|
|
|
inCellIndices[vtkm::exec::CellFaceLocalIndex(facePointIndex, myFace, shapeIn, *this)];
|
2016-12-02 03:26:49 +00:00
|
|
|
}
|
2015-08-14 19:47:25 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
class IsPolyDataCell : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(CellSetIn inCellSet, FieldOut isPolyDataCell);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _2(CellShape);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
template <typename CellShapeTag>
|
|
|
|
VTKM_EXEC vtkm::IdComponent operator()(CellShapeTag shape) const
|
|
|
|
{
|
|
|
|
return !vtkm::exec::CellFaceNumberOfFaces(shape, *this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CountPolyDataCellPoints : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(CellSetIn inCellSet, FieldOut numPoints);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _2(PointCount);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
VTKM_EXEC vtkm::Id operator()(vtkm::Id count) const { return count; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class PassPolyDataCells : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using ScatterType = vtkm::worklet::ScatterCounting;
|
|
|
|
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn inputTopology,
|
2019-01-10 18:59:25 +00:00
|
|
|
FieldOut shapes,
|
|
|
|
FieldOut pointIndices,
|
|
|
|
FieldOut cellIdMapOut);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(CellShape, PointIndices, InputIndex, _2, _3, _4);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
template <typename CellShape, typename InPointIndexType, typename OutPointIndexType>
|
|
|
|
VTKM_EXEC void operator()(const CellShape& inShape,
|
|
|
|
const InPointIndexType& inPoints,
|
|
|
|
vtkm::Id inputIndex,
|
|
|
|
vtkm::UInt8& outShape,
|
|
|
|
OutPointIndexType& outPoints,
|
|
|
|
vtkm::Id& cellIdMapOut) const
|
|
|
|
{
|
|
|
|
cellIdMapOut = inputIndex;
|
|
|
|
outShape = inShape.Id;
|
|
|
|
|
|
|
|
vtkm::IdComponent numPoints = inPoints.GetNumberOfComponents();
|
|
|
|
VTKM_ASSERT(numPoints == outPoints.GetNumberOfComponents());
|
|
|
|
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; pointIndex++)
|
|
|
|
{
|
|
|
|
outPoints[pointIndex] = inPoints[pointIndex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct BiasFunctor
|
|
|
|
{
|
|
|
|
VTKM_EXEC_CONT
|
|
|
|
BiasFunctor(T bias = T(0))
|
|
|
|
: Bias(bias)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
|
|
|
T operator()(T x) const { return x + this->Bias; }
|
|
|
|
|
|
|
|
T Bias;
|
|
|
|
};
|
|
|
|
|
2015-08-14 19:47:25 +00:00
|
|
|
public:
|
2017-08-03 15:19:22 +00:00
|
|
|
VTKM_CONT
|
|
|
|
ExternalFaces()
|
|
|
|
: PassPolyData(true)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
void SetPassPolyData(bool flag) { this->PassPolyData = flag; }
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
VTKM_CONT
|
|
|
|
bool GetPassPolyData() const { return this->PassPolyData; }
|
|
|
|
|
2017-07-31 14:06:33 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename ValueType, typename StorageType>
|
2017-07-31 14:06:33 +00:00
|
|
|
vtkm::cont::ArrayHandle<ValueType> ProcessCellField(
|
2018-08-30 15:53:18 +00:00
|
|
|
const vtkm::cont::ArrayHandle<ValueType, StorageType>& in) const
|
2017-07-31 14:06:33 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
// Use a temporary permutation array to simplify the mapping:
|
|
|
|
auto tmp = vtkm::cont::make_ArrayHandlePermutation(this->CellIdMap, in);
|
|
|
|
|
|
|
|
// Copy into an array with default storage:
|
|
|
|
vtkm::cont::ArrayHandle<ValueType> result;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(tmp, result);
|
2017-07-31 14:06:33 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReleaseCellMapArrays() { this->CellIdMap.ReleaseResources(); }
|
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
/// \brief ExternalFaces: Extract Faces on outside of geometry for regular grids.
|
|
|
|
///
|
|
|
|
/// Faster Run() method for uniform and rectilinear grid types.
|
|
|
|
/// Uses grid extents to find cells on the boundaries of the grid.
|
2017-07-19 19:35:31 +00:00
|
|
|
template <typename ShapeStorage,
|
|
|
|
typename NumIndicesStorage,
|
|
|
|
typename ConnectivityStorage,
|
2018-08-30 15:53:18 +00:00
|
|
|
typename OffsetsStorage>
|
2017-07-19 19:35:31 +00:00
|
|
|
VTKM_CONT void Run(const vtkm::cont::CellSetStructured<3>& inCellSet,
|
|
|
|
const vtkm::cont::CoordinateSystem& coord,
|
|
|
|
vtkm::cont::CellSetExplicit<ShapeStorage,
|
|
|
|
NumIndicesStorage,
|
|
|
|
ConnectivityStorage,
|
2018-08-30 15:53:18 +00:00
|
|
|
OffsetsStorage>& outCellSet)
|
2017-07-19 19:35:31 +00:00
|
|
|
{
|
2017-08-03 20:08:06 +00:00
|
|
|
vtkm::Vec<vtkm::Float64, 3> MinPoint;
|
|
|
|
vtkm::Vec<vtkm::Float64, 3> MaxPoint;
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2017-12-12 19:26:23 +00:00
|
|
|
vtkm::Id3 PointDimensions = inCellSet.GetPointDimensions();
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2018-02-22 13:29:13 +00:00
|
|
|
using DefaultHandle = vtkm::cont::ArrayHandle<vtkm::FloatDefault>;
|
|
|
|
using CartesianArrayHandle =
|
|
|
|
vtkm::cont::ArrayHandleCartesianProduct<DefaultHandle, DefaultHandle, DefaultHandle>;
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2017-12-12 19:26:23 +00:00
|
|
|
auto coordData = coord.GetData();
|
2018-01-25 16:02:52 +00:00
|
|
|
if (coordData.IsType<CartesianArrayHandle>())
|
2017-07-19 19:35:31 +00:00
|
|
|
{
|
2017-12-12 19:26:23 +00:00
|
|
|
auto vertices = coordData.Cast<CartesianArrayHandle>();
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
MinPoint[0] =
|
2017-08-03 20:08:06 +00:00
|
|
|
static_cast<vtkm::Float64>(vertices.GetPortalConstControl().GetFirstPortal().Get(0));
|
2017-07-19 19:35:31 +00:00
|
|
|
MinPoint[1] =
|
2017-08-03 20:08:06 +00:00
|
|
|
static_cast<vtkm::Float64>(vertices.GetPortalConstControl().GetSecondPortal().Get(0));
|
2017-07-19 19:35:31 +00:00
|
|
|
MinPoint[2] =
|
2017-08-03 20:08:06 +00:00
|
|
|
static_cast<vtkm::Float64>(vertices.GetPortalConstControl().GetThirdPortal().Get(0));
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2017-08-03 20:08:06 +00:00
|
|
|
MaxPoint[0] = static_cast<vtkm::Float64>(
|
2017-07-19 19:35:31 +00:00
|
|
|
vertices.GetPortalConstControl().GetFirstPortal().Get(PointDimensions[0] - 1));
|
2017-08-03 20:08:06 +00:00
|
|
|
MaxPoint[1] = static_cast<vtkm::Float64>(
|
2017-07-19 19:35:31 +00:00
|
|
|
vertices.GetPortalConstControl().GetSecondPortal().Get(PointDimensions[1] - 1));
|
2017-08-03 20:08:06 +00:00
|
|
|
MaxPoint[2] = static_cast<vtkm::Float64>(
|
2017-07-19 19:35:31 +00:00
|
|
|
vertices.GetPortalConstControl().GetThirdPortal().Get(PointDimensions[2] - 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-12 19:26:23 +00:00
|
|
|
auto vertices = coordData.Cast<vtkm::cont::ArrayHandleUniformPointCoordinates>();
|
|
|
|
auto Coordinates = vertices.GetPortalConstControl();
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
MinPoint = Coordinates.GetOrigin();
|
2017-08-03 20:08:06 +00:00
|
|
|
vtkm::Vec<vtkm::Float64, 3> spacing = Coordinates.GetSpacing();
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2017-08-03 20:08:06 +00:00
|
|
|
vtkm::Vec<vtkm::Float64, 3> unitLength;
|
|
|
|
unitLength[0] = static_cast<vtkm::Float64>(PointDimensions[0] - 1);
|
|
|
|
unitLength[1] = static_cast<vtkm::Float64>(PointDimensions[1] - 1);
|
|
|
|
unitLength[2] = static_cast<vtkm::Float64>(PointDimensions[2] - 1);
|
2017-07-19 19:35:31 +00:00
|
|
|
MaxPoint = MinPoint + spacing * unitLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a worklet to count the number of external faces on each cell
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numExternalFaces;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<NumExternalFacesPerStructuredCell>
|
2017-07-19 19:35:31 +00:00
|
|
|
numExternalFacesDispatcher((NumExternalFacesPerStructuredCell(MinPoint, MaxPoint)));
|
|
|
|
|
2017-12-12 19:26:23 +00:00
|
|
|
numExternalFacesDispatcher.Invoke(inCellSet, numExternalFaces, coordData);
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::Id numberOfExternalFaces =
|
|
|
|
vtkm::cont::Algorithm::Reduce(numExternalFaces, 0, vtkm::Sum());
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
auto scatterCellToExternalFace = BuildConnectivityStructured::MakeScatter(numExternalFaces);
|
2017-07-19 19:35:31 +00:00
|
|
|
|
2017-07-31 14:06:33 +00:00
|
|
|
// Maps output cells to input cells. Store this for cell field mapping.
|
|
|
|
this->CellIdMap = scatterCellToExternalFace.GetOutputToInputMap();
|
|
|
|
|
2017-07-19 19:35:31 +00:00
|
|
|
numExternalFaces.ReleaseResources();
|
|
|
|
|
|
|
|
vtkm::Id connectivitySize = 4 * numberOfExternalFaces;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage> faceConnectivity;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage> faceShapes;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage> facePointCount;
|
|
|
|
// Must pre allocate because worklet invocation will not have enough
|
|
|
|
// information to.
|
|
|
|
faceConnectivity.Allocate(connectivitySize);
|
|
|
|
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<BuildConnectivityStructured>
|
Move Scatter from Worklet to Dispatcher
Previously, when a Worklet needed a scatter, the scatter object was
stored in the Worklet object. That was problematic because that means
the Scatter, which is a control object, was shoved into the execution
environment.
To prevent that, move the Scatter into the Dispatcher object. The
worklet still declares a ScatterType alias, but no longer has a
GetScatter method. Instead, the Dispatcher now takes a Scatter object in
its constructor. If using the default scatter (ScatterIdentity), the
default constructor is used. If using another type of Scatter that
requires data to set up its state, then the caller of the worklet needs
to provide that to the dispatcher. For convenience, worklets are
encouraged to have a MakeScatter method to help construct a proper
scatter object.
2018-04-27 04:43:51 +00:00
|
|
|
buildConnectivityStructuredDispatcher(BuildConnectivityStructured(MinPoint, MaxPoint),
|
|
|
|
scatterCellToExternalFace);
|
2017-07-19 19:35:31 +00:00
|
|
|
|
|
|
|
buildConnectivityStructuredDispatcher.Invoke(
|
|
|
|
inCellSet,
|
|
|
|
inCellSet,
|
|
|
|
faceShapes,
|
|
|
|
facePointCount,
|
|
|
|
vtkm::cont::make_ArrayHandleGroupVec<4>(faceConnectivity),
|
2017-12-12 19:26:23 +00:00
|
|
|
coordData);
|
2017-07-19 19:35:31 +00:00
|
|
|
outCellSet.Fill(inCellSet.GetNumberOfPoints(), faceShapes, facePointCount, faceConnectivity);
|
|
|
|
}
|
|
|
|
|
2015-08-14 19:47:25 +00:00
|
|
|
///////////////////////////////////////////////////
|
|
|
|
/// \brief ExternalFaces: Extract Faces on outside of geometry
|
2017-05-26 17:53:28 +00:00
|
|
|
template <typename InCellSetType,
|
|
|
|
typename ShapeStorage,
|
|
|
|
typename NumIndicesStorage,
|
|
|
|
typename ConnectivityStorage,
|
2018-08-30 15:53:18 +00:00
|
|
|
typename OffsetsStorage>
|
2017-05-18 14:29:41 +00:00
|
|
|
VTKM_CONT void Run(const InCellSetType& inCellSet,
|
2017-05-26 17:53:28 +00:00
|
|
|
vtkm::cont::CellSetExplicit<ShapeStorage,
|
|
|
|
NumIndicesStorage,
|
|
|
|
ConnectivityStorage,
|
2018-08-30 15:53:18 +00:00
|
|
|
OffsetsStorage>& outCellSet)
|
2015-08-14 19:47:25 +00:00
|
|
|
{
|
2017-08-24 18:11:45 +00:00
|
|
|
using PointCountArrayType = vtkm::cont::ArrayHandle<vtkm::IdComponent, NumIndicesStorage>;
|
|
|
|
using ShapeArrayType = vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeStorage>;
|
|
|
|
using OffsetsArrayType = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>;
|
|
|
|
using ConnectivityArrayType = vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityStorage>;
|
2017-08-03 15:19:22 +00:00
|
|
|
|
2015-08-14 19:47:25 +00:00
|
|
|
//Create a worklet to map the number of faces to each cell
|
2016-12-06 00:30:57 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> facesPerCell;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<NumFacesPerCell> numFacesDispatcher;
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
numFacesDispatcher.Invoke(inCellSet, facesPerCell);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::worklet::ScatterCounting scatterCellToFace(facesPerCell);
|
2015-08-14 19:47:25 +00:00
|
|
|
facesPerCell.ReleaseResources();
|
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
PointCountArrayType polyDataPointCount;
|
|
|
|
ShapeArrayType polyDataShapes;
|
|
|
|
OffsetsArrayType polyDataOffsets;
|
|
|
|
ConnectivityArrayType polyDataConnectivity;
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> polyDataCellIdMap;
|
2017-08-03 15:19:22 +00:00
|
|
|
vtkm::Id polyDataConnectivitySize = 0;
|
|
|
|
if (this->PassPolyData)
|
|
|
|
{
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> isPolyDataCell;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<IsPolyDataCell> isPolyDataCellDispatcher;
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
isPolyDataCellDispatcher.Invoke(inCellSet, isPolyDataCell);
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::worklet::ScatterCounting scatterPolyDataCells(isPolyDataCell);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
isPolyDataCell.ReleaseResources();
|
|
|
|
|
|
|
|
if (scatterPolyDataCells.GetOutputRange(inCellSet.GetNumberOfCells()) != 0)
|
|
|
|
{
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<CountPolyDataCellPoints>
|
Move Scatter from Worklet to Dispatcher
Previously, when a Worklet needed a scatter, the scatter object was
stored in the Worklet object. That was problematic because that means
the Scatter, which is a control object, was shoved into the execution
environment.
To prevent that, move the Scatter into the Dispatcher object. The
worklet still declares a ScatterType alias, but no longer has a
GetScatter method. Instead, the Dispatcher now takes a Scatter object in
its constructor. If using the default scatter (ScatterIdentity), the
default constructor is used. If using another type of Scatter that
requires data to set up its state, then the caller of the worklet needs
to provide that to the dispatcher. For convenience, worklets are
encouraged to have a MakeScatter method to help construct a proper
scatter object.
2018-04-27 04:43:51 +00:00
|
|
|
countPolyDataCellPointsDispatcher(scatterPolyDataCells);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
countPolyDataCellPointsDispatcher.Invoke(inCellSet, polyDataPointCount);
|
|
|
|
|
|
|
|
vtkm::cont::ConvertNumComponentsToOffsets(
|
|
|
|
polyDataPointCount, polyDataOffsets, polyDataConnectivitySize);
|
|
|
|
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<PassPolyDataCells> passPolyDataCellsDispatcher(
|
|
|
|
scatterPolyDataCells);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
polyDataConnectivity.Allocate(polyDataConnectivitySize);
|
|
|
|
|
|
|
|
passPolyDataCellsDispatcher.Invoke(
|
|
|
|
inCellSet,
|
|
|
|
polyDataShapes,
|
|
|
|
vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, polyDataOffsets),
|
|
|
|
polyDataCellIdMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
if (scatterCellToFace.GetOutputRange(inCellSet.GetNumberOfCells()) == 0)
|
|
|
|
{
|
2017-08-03 15:19:22 +00:00
|
|
|
if (!polyDataConnectivitySize)
|
|
|
|
{
|
|
|
|
// Data has no faces. Output is empty.
|
|
|
|
outCellSet.PrepareToAddCells(0, 0);
|
|
|
|
outCellSet.CompleteAddingCells(inCellSet.GetNumberOfPoints());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Pass only input poly data to output
|
|
|
|
outCellSet.Fill(inCellSet.GetNumberOfPoints(),
|
|
|
|
polyDataShapes,
|
|
|
|
polyDataPointCount,
|
|
|
|
polyDataConnectivity,
|
|
|
|
polyDataOffsets);
|
|
|
|
this->CellIdMap = polyDataCellIdMap;
|
|
|
|
return;
|
|
|
|
}
|
2016-12-06 00:30:57 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::HashType> faceHashes;
|
2016-12-06 00:30:57 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> originCells;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> originFaces;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<FaceHash> faceHashDispatcher(scatterCellToFace);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
faceHashDispatcher.Invoke(inCellSet, faceHashes, originCells, originFaces);
|
2017-08-24 18:11:45 +00:00
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::worklet::Keys<vtkm::HashType> faceKeys(faceHashes);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> faceOutputCount;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherReduceByKey<FaceCounts> faceCountDispatcher;
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
faceCountDispatcher.Invoke(faceKeys, inCellSet, originCells, originFaces, faceOutputCount);
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
auto scatterCullInternalFaces = NumPointsPerFace::MakeScatter(faceOutputCount);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
PointCountArrayType facePointCount;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherReduceByKey<NumPointsPerFace> pointsPerFaceDispatcher(
|
2017-05-18 14:29:41 +00:00
|
|
|
scatterCullInternalFaces);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
pointsPerFaceDispatcher.Invoke(faceKeys, inCellSet, originCells, originFaces, facePointCount);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
ShapeArrayType faceShapes;
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
OffsetsArrayType faceOffsets;
|
2016-12-06 00:30:57 +00:00
|
|
|
vtkm::Id connectivitySize;
|
2017-05-18 14:29:41 +00:00
|
|
|
vtkm::cont::ConvertNumComponentsToOffsets(facePointCount, faceOffsets, connectivitySize);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
ConnectivityArrayType faceConnectivity;
|
2016-12-06 00:30:57 +00:00
|
|
|
// Must pre allocate because worklet invocation will not have enough
|
|
|
|
// information to.
|
|
|
|
faceConnectivity.Allocate(connectivitySize);
|
|
|
|
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherReduceByKey<BuildConnectivity> buildConnectivityDispatcher(
|
|
|
|
scatterCullInternalFaces);
|
2016-12-06 00:30:57 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> faceToCellIdMap;
|
2017-08-03 15:19:22 +00:00
|
|
|
|
2016-12-06 00:30:57 +00:00
|
|
|
buildConnectivityDispatcher.Invoke(
|
2017-05-26 17:53:28 +00:00
|
|
|
faceKeys,
|
|
|
|
inCellSet,
|
|
|
|
originCells,
|
|
|
|
originFaces,
|
|
|
|
faceShapes,
|
2017-07-31 14:06:33 +00:00
|
|
|
vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsets),
|
2017-08-03 15:19:22 +00:00
|
|
|
faceToCellIdMap);
|
2015-08-14 19:47:25 +00:00
|
|
|
|
2017-08-03 15:19:22 +00:00
|
|
|
if (!polyDataConnectivitySize)
|
|
|
|
{
|
|
|
|
outCellSet.Fill(
|
|
|
|
inCellSet.GetNumberOfPoints(), faceShapes, facePointCount, faceConnectivity, faceOffsets);
|
|
|
|
this->CellIdMap = faceToCellIdMap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Join poly data to face data output
|
|
|
|
vtkm::cont::ArrayHandleConcatenate<ShapeArrayType, ShapeArrayType> faceShapesArray(
|
|
|
|
faceShapes, polyDataShapes);
|
|
|
|
ShapeArrayType joinedShapesArray;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(faceShapesArray, joinedShapesArray);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
vtkm::cont::ArrayHandleConcatenate<PointCountArrayType, PointCountArrayType> pointCountArray(
|
|
|
|
facePointCount, polyDataPointCount);
|
|
|
|
PointCountArrayType joinedPointCountArray;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(pointCountArray, joinedPointCountArray);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
vtkm::cont::ArrayHandleConcatenate<ConnectivityArrayType, ConnectivityArrayType>
|
|
|
|
connectivityArray(faceConnectivity, polyDataConnectivity);
|
|
|
|
ConnectivityArrayType joinedConnectivity;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(connectivityArray, joinedConnectivity);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
// Adjust poly data offsets array with face connectivity size before join
|
2018-02-22 13:29:13 +00:00
|
|
|
using TransformBiasArrayType =
|
|
|
|
vtkm::cont::ArrayHandleTransform<OffsetsArrayType, BiasFunctor<vtkm::Id>>;
|
2017-08-03 15:19:22 +00:00
|
|
|
TransformBiasArrayType adjustedPolyDataOffsets =
|
|
|
|
vtkm::cont::make_ArrayHandleTransform<OffsetsArrayType>(
|
|
|
|
polyDataOffsets, BiasFunctor<vtkm::Id>(faceConnectivity.GetNumberOfValues()));
|
|
|
|
vtkm::cont::ArrayHandleConcatenate<OffsetsArrayType, TransformBiasArrayType> offsetsArray(
|
|
|
|
faceOffsets, adjustedPolyDataOffsets);
|
|
|
|
OffsetsArrayType joinedOffsets;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(offsetsArray, joinedOffsets);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
vtkm::cont::ArrayHandleConcatenate<vtkm::cont::ArrayHandle<vtkm::Id>,
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id>>
|
|
|
|
cellIdMapArray(faceToCellIdMap, polyDataCellIdMap);
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> joinedCellIdMap;
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(cellIdMapArray, joinedCellIdMap);
|
2017-08-03 15:19:22 +00:00
|
|
|
|
|
|
|
outCellSet.Fill(inCellSet.GetNumberOfPoints(),
|
|
|
|
joinedShapesArray,
|
|
|
|
joinedPointCountArray,
|
|
|
|
joinedConnectivity,
|
|
|
|
joinedOffsets);
|
|
|
|
this->CellIdMap = joinedCellIdMap;
|
|
|
|
}
|
2015-08-14 19:47:25 +00:00
|
|
|
}
|
2015-07-09 03:10:19 +00:00
|
|
|
|
2017-08-24 18:11:45 +00:00
|
|
|
private:
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> CellIdMap;
|
|
|
|
bool PassPolyData;
|
|
|
|
|
2015-07-09 03:10:19 +00:00
|
|
|
}; //struct ExternalFaces
|
2017-05-18 14:29:41 +00:00
|
|
|
}
|
|
|
|
} //namespace vtkm::worklet
|
2015-07-09 03:10:19 +00:00
|
|
|
|
|
|
|
#endif //vtk_m_worklet_ExternalFaces_h
|