2017-05-31 19:03:03 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2017-05-31 19:03:03 +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_gradient_PointGradient_h
|
|
|
|
#define vtk_m_worklet_gradient_PointGradient_h
|
|
|
|
|
|
|
|
#include <vtkm/exec/CellDerivative.h>
|
|
|
|
#include <vtkm/exec/ParametricCoordinates.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapTopology.h>
|
|
|
|
|
2020-04-14 15:00:46 +00:00
|
|
|
#include <utility>
|
2017-05-31 19:03:03 +00:00
|
|
|
#include <vtkm/worklet/gradient/GradientOutput.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace worklet
|
|
|
|
{
|
|
|
|
namespace gradient
|
|
|
|
{
|
|
|
|
|
2019-07-30 16:53:51 +00:00
|
|
|
struct PointGradient : public vtkm::worklet::WorkletVisitPointsWithCells
|
2017-05-31 19:03:03 +00:00
|
|
|
{
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn,
|
2019-07-30 16:53:51 +00:00
|
|
|
WholeCellSetIn<Cell, Point>,
|
2019-01-10 18:59:25 +00:00
|
|
|
WholeArrayIn pointCoordinates,
|
|
|
|
WholeArrayIn inputField,
|
2017-05-31 19:03:03 +00:00
|
|
|
GradientOutputs outputFields);
|
|
|
|
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(CellCount, CellIndices, WorkIndex, _2, _3, _4, _5);
|
2018-02-22 13:29:13 +00:00
|
|
|
using InputDomain = _1;
|
2017-05-31 19:03:03 +00:00
|
|
|
|
|
|
|
template <typename FromIndexType,
|
|
|
|
typename CellSetInType,
|
|
|
|
typename WholeCoordinatesIn,
|
|
|
|
typename WholeFieldIn,
|
|
|
|
typename GradientOutType>
|
|
|
|
VTKM_EXEC void operator()(const vtkm::IdComponent& numCells,
|
|
|
|
const FromIndexType& cellIds,
|
|
|
|
const vtkm::Id& pointId,
|
|
|
|
const CellSetInType& geometry,
|
|
|
|
const WholeCoordinatesIn& pointCoordinates,
|
|
|
|
const WholeFieldIn& inputField,
|
|
|
|
GradientOutType& outputGradient) const
|
|
|
|
{
|
2020-05-12 17:45:43 +00:00
|
|
|
// Use optimized ThreadIndicesTopologyMap
|
|
|
|
using CellThreadIndices =
|
|
|
|
vtkm::exec::arg::ThreadIndicesTopologyMap<CellSetInType,
|
|
|
|
vtkm::exec::arg::DefaultScatterAndMaskTag>;
|
2020-04-14 15:00:46 +00:00
|
|
|
|
2017-05-31 19:03:03 +00:00
|
|
|
using ValueType = typename WholeFieldIn::ValueType;
|
|
|
|
using CellShapeTag = typename CellSetInType::CellShapeTag;
|
|
|
|
|
|
|
|
vtkm::Vec<ValueType, 3> gradient(ValueType(0.0));
|
|
|
|
for (vtkm::IdComponent i = 0; i < numCells; ++i)
|
|
|
|
{
|
|
|
|
const vtkm::Id cellId = cellIds[i];
|
2019-01-21 02:14:55 +00:00
|
|
|
CellThreadIndices cellIndices(cellId, cellId, 0, cellId, geometry);
|
2017-05-31 19:03:03 +00:00
|
|
|
|
|
|
|
const CellShapeTag cellShape = cellIndices.GetCellShape();
|
|
|
|
|
|
|
|
// compute the parametric coordinates for the current point
|
|
|
|
const auto wCoords = this->GetValues(cellIndices, pointCoordinates);
|
|
|
|
const auto field = this->GetValues(cellIndices, inputField);
|
|
|
|
|
|
|
|
const vtkm::IdComponent pointIndexForCell = this->GetPointIndexForCell(cellIndices, pointId);
|
|
|
|
|
|
|
|
this->ComputeGradient(cellShape, pointIndexForCell, wCoords, field, gradient);
|
|
|
|
}
|
|
|
|
|
2017-08-04 16:43:26 +00:00
|
|
|
if (numCells != 0)
|
|
|
|
{
|
2019-09-09 19:01:03 +00:00
|
|
|
using BaseGradientType = typename vtkm::VecTraits<ValueType>::BaseComponentType;
|
2017-08-04 16:43:26 +00:00
|
|
|
const BaseGradientType invNumCells =
|
|
|
|
static_cast<BaseGradientType>(1.) / static_cast<BaseGradientType>(numCells);
|
2017-05-31 19:03:03 +00:00
|
|
|
|
2017-08-04 16:43:26 +00:00
|
|
|
gradient[0] = gradient[0] * invNumCells;
|
|
|
|
gradient[1] = gradient[1] * invNumCells;
|
|
|
|
gradient[2] = gradient[2] * invNumCells;
|
|
|
|
}
|
2017-05-31 19:03:03 +00:00
|
|
|
outputGradient = gradient;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename CellShapeTag,
|
|
|
|
typename PointCoordVecType,
|
|
|
|
typename FieldInVecType,
|
|
|
|
typename OutValueType>
|
|
|
|
inline VTKM_EXEC void ComputeGradient(CellShapeTag cellShape,
|
|
|
|
const vtkm::IdComponent& pointIndexForCell,
|
|
|
|
const PointCoordVecType& wCoords,
|
|
|
|
const FieldInVecType& field,
|
|
|
|
vtkm::Vec<OutValueType, 3>& gradient) const
|
|
|
|
{
|
2019-07-31 16:20:38 +00:00
|
|
|
vtkm::Vec3f pCoords;
|
2017-05-31 19:03:03 +00:00
|
|
|
vtkm::exec::ParametricCoordinatesPoint(
|
2020-03-12 23:38:27 +00:00
|
|
|
wCoords.GetNumberOfComponents(), pointIndexForCell, cellShape, pCoords);
|
2017-05-31 19:03:03 +00:00
|
|
|
|
|
|
|
//we need to add this to a return value
|
2020-03-12 23:38:27 +00:00
|
|
|
vtkm::Vec<OutValueType, 3> pointGradient;
|
|
|
|
auto status = vtkm::exec::CellDerivative(field, wCoords, pCoords, cellShape, pointGradient);
|
|
|
|
if (status == vtkm::ErrorCode::Success)
|
|
|
|
{
|
|
|
|
gradient += pointGradient;
|
|
|
|
}
|
2017-05-31 19:03:03 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 15:00:46 +00:00
|
|
|
template <typename ThreadIndicesType>
|
|
|
|
VTKM_EXEC vtkm::IdComponent GetPointIndexForCell(const ThreadIndicesType& indices,
|
|
|
|
vtkm::Id pointId) const
|
2017-05-31 19:03:03 +00:00
|
|
|
{
|
|
|
|
vtkm::IdComponent result = 0;
|
2019-07-30 16:53:51 +00:00
|
|
|
const auto& topo = indices.GetIndicesIncident();
|
2017-05-31 19:03:03 +00:00
|
|
|
for (vtkm::IdComponent i = 0; i < topo.GetNumberOfComponents(); ++i)
|
|
|
|
{
|
|
|
|
if (topo[i] == pointId)
|
|
|
|
{
|
|
|
|
result = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//This is fairly complex so that we can trigger code to extract
|
|
|
|
//VecRectilinearPointCoordinates when using structured connectivity, and
|
|
|
|
//uniform point coordinates.
|
|
|
|
//c++14 would make the return type simply auto
|
2020-04-14 15:00:46 +00:00
|
|
|
template <typename ThreadIndicesType, typename WholeFieldIn>
|
|
|
|
VTKM_EXEC auto GetValues(const ThreadIndicesType& indices, const WholeFieldIn& in) const
|
|
|
|
-> decltype(std::declval<vtkm::exec::arg::Fetch<vtkm::exec::arg::FetchTagArrayTopologyMapIn,
|
|
|
|
vtkm::exec::arg::AspectTagDefault,
|
|
|
|
typename WholeFieldIn::PortalType>>()
|
|
|
|
.Load(indices, in.GetPortal()))
|
2017-05-31 19:03:03 +00:00
|
|
|
{
|
|
|
|
//the current problem is that when the topology is structured
|
|
|
|
//we are passing in an vtkm::Id when it wants a Id2 or an Id3 that
|
|
|
|
//represents the flat index of the topology
|
|
|
|
using ExecObjectType = typename WholeFieldIn::PortalType;
|
|
|
|
using Fetch = vtkm::exec::arg::Fetch<vtkm::exec::arg::FetchTagArrayTopologyMapIn,
|
|
|
|
vtkm::exec::arg::AspectTagDefault,
|
|
|
|
ExecObjectType>;
|
|
|
|
Fetch fetch;
|
|
|
|
return fetch.Load(indices, in.GetPortal());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|