mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add ability to get an array from a Field for a particular type
This is done through a new version of ApplyPolicy. This version takes a type of the array as its first template argument, which must be specified. This requires having a list of potential storage to try. It will use that to construct an ArrayHandleMultiplexer containing all potential types. This list of storages comes from the policy. A StorageList item was added to the policy. Types are automatically converted. So if you ask for a vtkm::Float64 and field contains a vtkm::Float32, it will the array wrapped in an ArrayHandleCast to give the expected type.
This commit is contained in:
parent
2b6e6da6ca
commit
3039a18baf
44
docs/changelog/apply-policy-with-single-type.md
Normal file
44
docs/changelog/apply-policy-with-single-type.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Add ability to get an array from a Field for a particular type
|
||||
|
||||
Previously, whenever you got an array from a `Field` object from a call to
|
||||
an `ApplyPolicy`, you would get back a `VariantArrayHandle` that allows you
|
||||
to cast to multiple types. To use that, you then have to cast it to
|
||||
multiple different types and multiple different storage.
|
||||
|
||||
Often, this is what you want. If you are operating on a field, then you
|
||||
want to cast to the native type. But there are also cases where you know a
|
||||
specific type you want. For example, if you are operating on two fields, it
|
||||
makes sense to find the exact type for the first field and then cast the
|
||||
second field to that type if necessary rather than pointlessly unroll
|
||||
templates for the cross of every possible combination. Also, we are not
|
||||
unrolling for different storage types or attempting to create a virtual
|
||||
array. Instead, we are using an `ArrayHandleMultiplexer` so that you only
|
||||
have to compile for this array once.
|
||||
|
||||
This is done through a new version of `ApplyPolicy`. This version takes a
|
||||
type of the array as its first template argument, which must be specified.
|
||||
|
||||
This requires having a list of potential storage to try. It will use that
|
||||
to construct an `ArrayHandleMultiplexer` containing all potential types.
|
||||
This list of storages comes from the policy. A `StorageList` item was added
|
||||
to the policy.
|
||||
|
||||
Types are automatically converted. So if you ask for a `vtkm::Float64` and
|
||||
field contains a `vtkm::Float32`, it will the array wrapped in an
|
||||
`ArrayHandleCast` to give the expected type.
|
||||
|
||||
Here is an example where you are doing an operation on a field and
|
||||
coordinate system. The superclass finds the correct type of the field. Your
|
||||
result is just going to follow the type of the field.
|
||||
|
||||
``` cpp
|
||||
template <typename T, typename StorageType, typename DerivedPolicy>
|
||||
inline VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(
|
||||
const vtkm::cont::DataSet& inDataSet,
|
||||
const vtkm::cont::ArrayHandle<T, StorageType>& field,
|
||||
const vtkm::filter::FieldMetadata& fieldMetadata,
|
||||
vtkm::filter::PolicyBase<DerivedPolicy> policy)
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coords = inDataSet.GetCoordianteSystem();
|
||||
auto coordsArray = vtkm::filter::ApplyPolicy<T>(coords, policy);
|
||||
```
|
@ -103,13 +103,10 @@ struct ListTagEmpty : detail::ListRoot
|
||||
|
||||
/// A tag that is a construction of two other tags joined together. This struct
|
||||
/// can be subclassed and still behave like a list tag.
|
||||
template <typename ListTag1, typename ListTag2>
|
||||
template <typename... ListTags>
|
||||
struct ListTagJoin : detail::ListRoot
|
||||
{
|
||||
VTKM_IS_LIST_TAG(ListTag1);
|
||||
VTKM_IS_LIST_TAG(ListTag2);
|
||||
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTag1>,
|
||||
internal::ListTagAsBrigandList<ListTag2>>::type;
|
||||
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTags>...>::type;
|
||||
};
|
||||
|
||||
|
||||
|
@ -526,6 +526,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Converts a \c vtkm::ListTag to an \c ArrayHandleMultiplexer
|
||||
///
|
||||
/// The argument of this template must be a vtkm::ListTag and furthermore all the types in
|
||||
/// the list tag must be some type of \c ArrayHandle. The templated type gets aliased to
|
||||
/// an \c ArrayHandleMultiplexer that can store any of these ArrayHandle types.
|
||||
///
|
||||
template <typename ListTag>
|
||||
using ArrayHandleMultiplexerFromListTag = vtkm::ListTagApply<ListTag, ArrayHandleMultiplexer>;
|
||||
|
||||
} // namespace cont
|
||||
|
||||
} // namespace vtkm
|
||||
|
@ -32,12 +32,201 @@ template <typename Derived>
|
||||
struct PolicyBase
|
||||
{
|
||||
using FieldTypeList = VTKM_DEFAULT_TYPE_LIST_TAG;
|
||||
using StorageList = vtkm::ListTagJoin<
|
||||
VTKM_DEFAULT_STORAGE_LIST_TAG,
|
||||
vtkm::ListTagBase<
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32>>::StorageTag,
|
||||
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<vtkm::Float64>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Float64>>::StorageTag>>;
|
||||
|
||||
using StructuredCellSetList = vtkm::cont::CellSetListTagStructured;
|
||||
using UnstructuredCellSetList = vtkm::cont::CellSetListTagUnstructured;
|
||||
using AllCellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG;
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Given a base type, forms a list of all types with the same Vec structure but with the
|
||||
// base component replaced with each of the basic C types.
|
||||
template <typename BaseType>
|
||||
struct AllCastingTypes
|
||||
{
|
||||
using VTraits = vtkm::VecTraits<BaseType>;
|
||||
|
||||
using type =
|
||||
vtkm::ListTagBase<typename VTraits::template ReplaceBaseComponentType<vtkm::Int8>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::UInt8>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::Int16>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::UInt8>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::Int32>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::UInt32>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::Int64>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::UInt64>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::Float32>,
|
||||
typename VTraits::template ReplaceBaseComponentType<vtkm::Float64>>;
|
||||
};
|
||||
|
||||
template <typename TargetT, typename SourceT, typename Storage, bool Valid>
|
||||
struct CastArrayIfValid;
|
||||
|
||||
template <typename TargetT, typename SourceT, typename Storage>
|
||||
struct CastArrayIfValid<TargetT, SourceT, Storage, true>
|
||||
{
|
||||
using type = vtkm::cont::ArrayHandleCast<TargetT, vtkm::cont::ArrayHandle<SourceT, Storage>>;
|
||||
};
|
||||
|
||||
template <typename TargetT, typename SourceT, typename Storage>
|
||||
struct CastArrayIfValid<TargetT, SourceT, Storage, false>
|
||||
{
|
||||
using type = vtkm::cont::ArrayHandleDiscard<TargetT>;
|
||||
};
|
||||
|
||||
// Provides a transform template that builds a cast from an array of some source type to a
|
||||
// cast array to a specific target type.
|
||||
template <typename TargetT, typename Storage>
|
||||
struct CastArrayTransform
|
||||
{
|
||||
template <typename SourceT>
|
||||
using Transform = typename CastArrayIfValid<
|
||||
TargetT,
|
||||
SourceT,
|
||||
Storage,
|
||||
vtkm::cont::internal::IsValidArrayHandle<SourceT, Storage>::value>::type;
|
||||
};
|
||||
|
||||
template <typename TargetT, typename Storage, bool Valid>
|
||||
struct AllCastArraysForStorageImpl;
|
||||
|
||||
template <typename TargetT, typename Storage>
|
||||
struct AllCastArraysForStorageImpl<TargetT, Storage, true>
|
||||
{
|
||||
using SourceTypes = typename AllCastingTypes<TargetT>::type;
|
||||
using type = vtkm::ListTagJoin<
|
||||
vtkm::ListTagBase<vtkm::cont::ArrayHandle<TargetT, Storage>>,
|
||||
vtkm::ListTagTransform<SourceTypes, CastArrayTransform<TargetT, Storage>::template Transform>>;
|
||||
};
|
||||
|
||||
template <typename TargetT, typename Storage>
|
||||
struct AllCastArraysForStorageImpl<TargetT, Storage, false>
|
||||
{
|
||||
using SourceTypes = typename AllCastingTypes<TargetT>::type;
|
||||
using type =
|
||||
vtkm::ListTagTransform<SourceTypes, CastArrayTransform<TargetT, Storage>::template Transform>;
|
||||
};
|
||||
|
||||
// Special cases for known storage with limited type support.
|
||||
template <>
|
||||
struct AllCastArraysForStorageImpl<vtkm::Vec3f,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
true>
|
||||
{
|
||||
using type = vtkm::ListTagBase<vtkm::cont::ArrayHandleUniformPointCoordinates>;
|
||||
};
|
||||
template <typename T>
|
||||
struct AllCastArraysForStorageImpl<vtkm::Vec<T, 3>,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
false>
|
||||
{
|
||||
using type = vtkm::ListTagBase<vtkm::cont::ArrayHandleCast<
|
||||
vtkm::Vec<T, 3>,
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec3f,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag>>>;
|
||||
};
|
||||
template <typename TargetT>
|
||||
struct AllCastArraysForStorageImpl<TargetT,
|
||||
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
|
||||
false>
|
||||
{
|
||||
using type = vtkm::ListTagEmpty;
|
||||
};
|
||||
|
||||
template <typename T, typename S1, typename S2, typename S3>
|
||||
struct AllCastArraysForStorageImpl<
|
||||
vtkm::Vec<T, 3>,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<vtkm::cont::ArrayHandle<T, S1>,
|
||||
vtkm::cont::ArrayHandle<T, S2>,
|
||||
vtkm::cont::ArrayHandle<T, S3>>,
|
||||
true>
|
||||
{
|
||||
using type =
|
||||
vtkm::ListTagBase<vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<T, S1>,
|
||||
vtkm::cont::ArrayHandle<T, S2>,
|
||||
vtkm::cont::ArrayHandle<T, S3>>>;
|
||||
};
|
||||
template <typename TargetT, typename SourceT, typename S1, typename S2, typename S3>
|
||||
struct AllCastArraysForStorageImpl<
|
||||
vtkm::Vec<TargetT, 3>,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<vtkm::cont::ArrayHandle<SourceT, S1>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S2>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S3>>,
|
||||
false>
|
||||
{
|
||||
using type = vtkm::ListTagBase<vtkm::cont::ArrayHandleCast<
|
||||
vtkm::Vec<TargetT, 3>,
|
||||
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<SourceT, S1>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S2>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S3>>>>;
|
||||
};
|
||||
template <typename TargetT, typename SourceT, typename S1, typename S2, typename S3>
|
||||
struct AllCastArraysForStorageImpl<
|
||||
TargetT,
|
||||
vtkm::cont::internal::StorageTagCartesianProduct<vtkm::cont::ArrayHandle<SourceT, S1>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S2>,
|
||||
vtkm::cont::ArrayHandle<SourceT, S3>>,
|
||||
false>
|
||||
{
|
||||
using type = vtkm::ListTagEmpty;
|
||||
};
|
||||
|
||||
// Given a target type and storage of an array handle, provides a list this array handle plus all
|
||||
// array handles that can be cast to the target type wrapped in an ArrayHandleCast that does so.
|
||||
template <typename TargetT, typename Storage>
|
||||
struct AllCastArraysForStorage
|
||||
{
|
||||
using SourceTypes = typename AllCastingTypes<TargetT>::type;
|
||||
using type = typename AllCastArraysForStorageImpl<
|
||||
TargetT,
|
||||
Storage,
|
||||
vtkm::cont::internal::IsValidArrayHandle<TargetT, Storage>::value>::type;
|
||||
};
|
||||
|
||||
// Provides a transform template that converts a storage type to a list of all arrays that come
|
||||
// from that storage type and can be cast to a target type (wrapped in an ArrayHandleCast as
|
||||
// appropriate).
|
||||
template <typename TargetT>
|
||||
struct AllCastArraysTransform
|
||||
{
|
||||
template <typename Storage>
|
||||
using Transform = typename AllCastArraysForStorage<TargetT, Storage>::type;
|
||||
};
|
||||
|
||||
// Given a target type and a list of storage types, provides a joined list of all possible arrays
|
||||
// of any of these storage cast to the target type.
|
||||
template <typename TargetT, typename StorageList>
|
||||
struct AllCastArraysForStorageList
|
||||
{
|
||||
VTKM_IS_LIST_TAG(StorageList);
|
||||
using listOfLists =
|
||||
vtkm::ListTagTransform<StorageList, AllCastArraysTransform<TargetT>::template Transform>;
|
||||
using type = vtkm::ListTagApply<listOfLists, vtkm::ListTagJoin>;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
template <typename TargetT, typename StorageList>
|
||||
using ArrayHandleMultiplexerForStorageList = vtkm::cont::ArrayHandleMultiplexerFromListTag<
|
||||
typename detail::AllCastArraysForStorageList<TargetT, StorageList>::type>;
|
||||
|
||||
} // namespace internal
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename DerivedPolicy>
|
||||
VTKM_CONT vtkm::cont::VariantArrayHandleBase<typename DerivedPolicy::FieldTypeList> ApplyPolicy(
|
||||
@ -48,6 +237,16 @@ VTKM_CONT vtkm::cont::VariantArrayHandleBase<typename DerivedPolicy::FieldTypeLi
|
||||
return field.GetData().ResetTypes(TypeList());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, typename DerivedPolicy>
|
||||
VTKM_CONT internal::ArrayHandleMultiplexerForStorageList<T, typename DerivedPolicy::StorageList>
|
||||
ApplyPolicy(const vtkm::cont::Field& field, const vtkm::filter::PolicyBase<DerivedPolicy>&)
|
||||
{
|
||||
using ArrayHandleMultiplexerType =
|
||||
internal::ArrayHandleMultiplexerForStorageList<T, typename DerivedPolicy::StorageList>;
|
||||
return field.GetData().AsMultiplexer<ArrayHandleMultiplexerType>();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename DerivedPolicy, typename FilterType>
|
||||
VTKM_CONT vtkm::cont::VariantArrayHandleBase<typename vtkm::filter::DeduceFilterFieldTypes<
|
||||
|
@ -44,10 +44,10 @@ struct UniversalTag
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename ListTag1, typename ListTag2>
|
||||
template <typename... ListTags>
|
||||
struct ListJoin
|
||||
{
|
||||
using type = brigand::append<ListTag1, ListTag2>;
|
||||
using type = brigand::append<ListTags...>;
|
||||
};
|
||||
|
||||
template <typename ListTag>
|
||||
|
Loading…
Reference in New Issue
Block a user