Use a worklet to permute fields rather than ArrayHandlePermutation
According to talks with Rob Maynard, using a worklet should be (counterintuitively) faster than using ArrayHandlePermutation with ArrayCopy. This change also gives an opportunity to handle invalid indices, which may be intentionally set when no mapping is available for that value. For this case, MapFieldPermutation now takes an invalidValue argument to set such values.
This commit is contained in:
parent
4a5dbb65db
commit
98f20ec269
@ -11,16 +11,75 @@
|
||||
#include <vtkm/filter/MapFieldPermutation.h>
|
||||
|
||||
#include <vtkm/TypeList.h>
|
||||
#include <vtkm/TypeTraits.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <vtkm/filter/PolicyDefault.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
|
||||
{
|
||||
T InvalidValue;
|
||||
|
||||
explicit MapPermutationWorklet(T invalidValue)
|
||||
: InvalidValue(invalidValue)
|
||||
{
|
||||
}
|
||||
|
||||
using ControlSignature = void(FieldIn permutationIndex, WholeArrayIn input, FieldOut output);
|
||||
|
||||
template <typename InputPortalType>
|
||||
VTKM_EXEC void operator()(vtkm::Id permutationIndex, InputPortalType inputPortal, T& output) const
|
||||
{
|
||||
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
|
||||
{
|
||||
output = inputPortal.Get(permutationIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
output = this->InvalidValue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// For simplicity, the invalid value is specified as a single type (vtkm::Float64), and this is
|
||||
// often a non-finite value, which is not well represented by integer types. This function does its
|
||||
// best to find a reasonable cast for the value.
|
||||
template <typename T>
|
||||
T CastInvalidValue(vtkm::Float64 invalidValue)
|
||||
{
|
||||
using ComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
|
||||
|
||||
if (std::is_same<vtkm::TypeTraitsIntegerTag, typename vtkm::TypeTraits<T>::NumericTag>::value)
|
||||
{
|
||||
// Casting to integer types
|
||||
if (vtkm::IsFinite(invalidValue))
|
||||
{
|
||||
return T(static_cast<ComponentType>(invalidValue));
|
||||
}
|
||||
else if (vtkm::IsInf(invalidValue) && (invalidValue > 0))
|
||||
{
|
||||
return T(std::numeric_limits<ComponentType>::max());
|
||||
}
|
||||
else
|
||||
{
|
||||
return T(std::numeric_limits<ComponentType>::min());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not an integer type. Assume can be directly cast
|
||||
return T(static_cast<ComponentType>(invalidValue));
|
||||
}
|
||||
}
|
||||
|
||||
struct DoMapFieldPermutation
|
||||
{
|
||||
bool CalledMap = false;
|
||||
@ -28,11 +87,13 @@ struct DoMapFieldPermutation
|
||||
template <typename T, typename S>
|
||||
void operator()(const vtkm::cont::ArrayHandle<T, S>& inputArray,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
||||
vtkm::cont::VariantArrayHandle& output)
|
||||
vtkm::cont::VariantArrayHandle& output,
|
||||
vtkm::Float64 invalidValue)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<T> outputArray;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandlePermutation(permutation, inputArray),
|
||||
outputArray);
|
||||
MapPermutationWorklet<T> worklet(CastInvalidValue<T>(invalidValue));
|
||||
vtkm::cont::Invoker invoke;
|
||||
invoke(worklet, permutation, inputArray, outputArray);
|
||||
output = vtkm::cont::VariantArrayHandle(outputArray);
|
||||
this->CalledMap = true;
|
||||
}
|
||||
@ -42,12 +103,13 @@ struct DoMapFieldPermutation
|
||||
|
||||
bool vtkm::filter::MapFieldPermutation(const vtkm::cont::Field& inputField,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
||||
vtkm::cont::Field& outputField)
|
||||
vtkm::cont::Field& outputField,
|
||||
vtkm::Float64 invalidValue)
|
||||
{
|
||||
vtkm::cont::VariantArrayHandle outputArray;
|
||||
DoMapFieldPermutation functor;
|
||||
inputField.GetData().ResetTypes<vtkm::TypeListAll>().CastAndCall(
|
||||
vtkm::filter::PolicyDefault::StorageList{}, functor, permutation, outputArray);
|
||||
vtkm::filter::PolicyDefault::StorageList{}, functor, permutation, outputArray, invalidValue);
|
||||
if (functor.CalledMap)
|
||||
{
|
||||
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
|
||||
@ -61,10 +123,12 @@ bool vtkm::filter::MapFieldPermutation(const vtkm::cont::Field& inputField,
|
||||
|
||||
bool vtkm::filter::MapFieldPermutation(const vtkm::cont::Field& inputField,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
||||
vtkm::cont::DataSet& outputData)
|
||||
vtkm::cont::DataSet& outputData,
|
||||
vtkm::Float64 invalidValue)
|
||||
{
|
||||
vtkm::cont::Field outputField;
|
||||
bool success = vtkm::filter::MapFieldPermutation(inputField, permutation, outputField);
|
||||
bool success =
|
||||
vtkm::filter::MapFieldPermutation(inputField, permutation, outputField, invalidValue);
|
||||
if (success)
|
||||
{
|
||||
outputData.AddField(outputField);
|
||||
|
@ -39,10 +39,15 @@ namespace filter
|
||||
/// `true`, then the results in `outputField` are valid. If it is `false`, then `outputField`
|
||||
/// should not be used.
|
||||
///
|
||||
/// If an invalid index is given in the permutation array (i.e. less than 0 or greater than the
|
||||
/// size of the array), then the resulting outputField will be given `invalidValue` (converted as
|
||||
/// best as possible to the correct data type).
|
||||
///
|
||||
VTKM_FILTER_EXPORT VTKM_CONT bool MapFieldPermutation(
|
||||
const vtkm::cont::Field& inputField,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
||||
vtkm::cont::Field& outputField);
|
||||
vtkm::cont::Field& outputField,
|
||||
vtkm::Float64 invalidValue = vtkm::Nan<vtkm::Float64>());
|
||||
|
||||
/// \brief Maps a field by permuting it by a given index array.
|
||||
///
|
||||
@ -62,10 +67,15 @@ VTKM_FILTER_EXPORT VTKM_CONT bool MapFieldPermutation(
|
||||
/// `true`, then `outputData` has the permuted field. If it is `false`, then the field is not
|
||||
/// placed in `outputData`.
|
||||
///
|
||||
/// If an invalid index is given in the permutation array (i.e. less than 0 or greater than the
|
||||
/// size of the array), then the resulting outputField will be given `invalidValue` (converted as
|
||||
/// best as possible to the correct data type).
|
||||
///
|
||||
VTKM_FILTER_EXPORT VTKM_CONT bool MapFieldPermutation(
|
||||
const vtkm::cont::Field& inputField,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
|
||||
vtkm::cont::DataSet& outputData);
|
||||
vtkm::cont::DataSet& outputData,
|
||||
vtkm::Float64 invalidValue = vtkm::Nan<vtkm::Float64>());
|
||||
}
|
||||
} // namespace vtkm::filter
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user