mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
Handle any Vec size in VTKDataSetReader
The legacy VTK file reader previously only supported a specific set of Vec lengths (i.e., 1, 2, 3, 4, 6, and 9). This is because a basic array handle has to have the vec length compiled in. However, the new `ArrayHandleRuntimeVec` feature is capable of reading in any vec-length and can be leveraged to read in arbitrarily sized vectors in field arrays.
This commit is contained in:
parent
2cc2205218
commit
bb9e7a0d6f
7
docs/changelog/read-any-vec-size.md
Normal file
7
docs/changelog/read-any-vec-size.md
Normal file
@ -0,0 +1,7 @@
|
||||
# VTKDataSetReader handles any Vec size.
|
||||
|
||||
The legacy VTK file reader previously only supported a specific set of Vec
|
||||
lengths (i.e., 1, 2, 3, 4, 6, and 9). This is because a basic array handle
|
||||
has to have the vec length compiled in. However, the new
|
||||
`ArrayHandleRuntimeVec` feature is capable of reading in any vec-length and
|
||||
can be leveraged to read in arbitrarily sized vectors in field arrays.
|
@ -372,10 +372,13 @@ public:
|
||||
///@}
|
||||
};
|
||||
|
||||
/// \c make_ArrayHandleRuntimeVec is convenience function to generate an
|
||||
/// ArrayHandleRuntimeVec. It takes in an ArrayHandle of values and an
|
||||
/// array handle of offsets and returns an array handle with consecutive
|
||||
/// entries grouped in a Vec.
|
||||
/// `make_ArrayHandleRuntimeVec` is convenience function to generate an
|
||||
/// `ArrayHandleRuntimeVec`. It takes the number of components stored in
|
||||
/// each value's `Vec`, which must be specified on the construction of
|
||||
/// the `ArrayHandleRuntimeVec`. If not specified, the number of components
|
||||
/// is set to 1. `make_ArrayHandleRuntimeVec` can also optionally take an
|
||||
/// existing array of components, which will be grouped into `Vec` values
|
||||
/// based on the specified number of components.
|
||||
///
|
||||
template <typename T>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(
|
||||
@ -402,6 +405,62 @@ VTKM_CONT auto make_ArrayHandleRuntimeVec(
|
||||
return make_ArrayHandleRuntimeVec(1, componentsArray);
|
||||
}
|
||||
|
||||
/// A convenience function for creating an `ArrayHandleRuntimeVec` from a standard C array.
|
||||
///
|
||||
template <typename T>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
|
||||
const T* array,
|
||||
vtkm::Id numberOfValues,
|
||||
vtkm::CopyFlag copy)
|
||||
{
|
||||
return make_ArrayHandleRuntimeVec(numComponents,
|
||||
vtkm::cont::make_ArrayHandle(array, numberOfValues, copy));
|
||||
}
|
||||
|
||||
/// A convenience function to move a user-allocated array into an `ArrayHandleRuntimeVec`.
|
||||
/// The provided array pointer will be reset to `nullptr`.
|
||||
/// If the array was not allocated with the `new[]` operator, then deleter and reallocater
|
||||
/// functions must be provided.
|
||||
///
|
||||
template <typename T>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVecMove(
|
||||
vtkm::IdComponent numComponents,
|
||||
T*& array,
|
||||
vtkm::Id numberOfValues,
|
||||
vtkm::cont::internal::BufferInfo::Deleter deleter = internal::SimpleArrayDeleter<T>,
|
||||
vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::SimpleArrayReallocater<T>)
|
||||
{
|
||||
return make_ArrayHandleRuntimeVec(
|
||||
numComponents, vtkm::cont::make_ArrayHandleMove(array, numberOfValues, deleter, reallocater));
|
||||
}
|
||||
|
||||
/// A convenience function for creating an `ArrayHandleRuntimeVec` from an `std::vector`.
|
||||
///
|
||||
template <typename T, typename Allocator>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
|
||||
const std::vector<T, Allocator>& array,
|
||||
vtkm::CopyFlag copy)
|
||||
{
|
||||
return make_ArrayHandleRuntimeVec(numComponents, vtkm::cont::make_ArrayHandle(array, copy));
|
||||
}
|
||||
|
||||
/// Move an `std::vector` into an `ArrayHandleRuntimeVec`.
|
||||
///
|
||||
template <typename T, typename Allocator>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVecMove(vtkm::IdComponent numComponents,
|
||||
std::vector<T, Allocator>&& array)
|
||||
{
|
||||
return make_ArrayHandleRuntimeVec(numComponents, make_ArrayHandleMove(std::move(array)));
|
||||
}
|
||||
|
||||
template <typename T, typename Allocator>
|
||||
VTKM_CONT auto make_ArrayHandleRuntimeVec(vtkm::IdComponent numComponents,
|
||||
std::vector<T, Allocator>&& array,
|
||||
vtkm::CopyFlag vtkmNotUsed(copy))
|
||||
{
|
||||
return make_ArrayHandleRuntimeVecMove(numComponents, std::move(array));
|
||||
}
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleOffsetsToNumComponents.h>
|
||||
#include <vtkm/cont/ArrayHandleRuntimeVec.h>
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||
@ -35,162 +36,6 @@ inline void PrintVTKDataFileSummary(const vtkm::io::internal::VTKDataSetFile& df
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Since Fields and DataSets store data in the default UnknownArrayHandle, convert
|
||||
// the data to the closest type supported by default. The following will
|
||||
// need to be updated if UnknownArrayHandle or TypeListCommon changes.
|
||||
template <typename T>
|
||||
struct ClosestCommonType
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ClosestFloat
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::UnknownArrayHandle CreateUnknownArrayHandle(const std::vector<T>& vec)
|
||||
{
|
||||
switch (vtkm::VecTraits<T>::NUM_COMPONENTS)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
using CommonType = typename ClosestCommonType<T>::Type;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<T>::Name()
|
||||
<< " is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<CommonType>::Name() << ".");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
portal.Set(i, static_cast<CommonType>(vec[static_cast<std::size_t>(i)]));
|
||||
}
|
||||
|
||||
return vtkm::cont::UnknownArrayHandle(output);
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
case 9:
|
||||
{
|
||||
constexpr auto numComps = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
|
||||
using InComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||
using OutComponentType = typename ClosestFloat<InComponentType>::Type;
|
||||
using CommonType = vtkm::Vec<OutComponentType, numComps>;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<InComponentType>::Name() << "["
|
||||
<< vtkm::VecTraits<T>::GetNumberOfComponents(T()) << "] "
|
||||
<< "is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<OutComponentType>::Name() << "["
|
||||
<< numComps << "].");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
CommonType outval = CommonType();
|
||||
for (vtkm::IdComponent j = 0; j < numComps; ++j)
|
||||
{
|
||||
outval[j] = static_cast<OutComponentType>(
|
||||
vtkm::VecTraits<T>::GetComponent(vec[static_cast<std::size_t>(i)], j));
|
||||
}
|
||||
portal.Set(i, outval);
|
||||
}
|
||||
|
||||
return vtkm::cont::UnknownArrayHandle(output);
|
||||
}
|
||||
default:
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Only 1, 2, 3, or 9 components supported. Skipping.");
|
||||
return vtkm::cont::UnknownArrayHandle(vtkm::cont::ArrayHandle<vtkm::Float32>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
@ -676,27 +521,23 @@ void VTKDataSetReaderBase::ReadGlobalOrPedigreeIds(vtkm::cont::Field::Associatio
|
||||
class VTKDataSetReaderBase::SkipArrayVariant
|
||||
{
|
||||
public:
|
||||
SkipArrayVariant(VTKDataSetReaderBase* reader, std::size_t numElements)
|
||||
SkipArrayVariant(VTKDataSetReaderBase* reader,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents)
|
||||
: Reader(reader)
|
||||
, NumElements(numElements)
|
||||
, TotalSize(numElements * static_cast<std::size_t>(numComponents))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements, T());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements * static_cast<std::size_t>(numComponents), T());
|
||||
this->Reader->SkipArray(this->TotalSize, T());
|
||||
}
|
||||
|
||||
protected:
|
||||
VTKDataSetReaderBase* Reader;
|
||||
std::size_t NumElements;
|
||||
std::size_t TotalSize;
|
||||
};
|
||||
|
||||
class VTKDataSetReaderBase::ReadArrayVariant : public SkipArrayVariant
|
||||
@ -705,9 +546,11 @@ public:
|
||||
ReadArrayVariant(VTKDataSetReaderBase* reader,
|
||||
vtkm::cont::Field::Association association,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents,
|
||||
vtkm::cont::UnknownArrayHandle& data)
|
||||
: SkipArrayVariant(reader, numElements)
|
||||
: SkipArrayVariant(reader, numElements, numComponents)
|
||||
, Association(association)
|
||||
, NumComponents(numComponents)
|
||||
, Data(&data)
|
||||
{
|
||||
}
|
||||
@ -715,12 +558,13 @@ public:
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
std::vector<T> buffer(this->NumElements);
|
||||
std::vector<T> buffer(this->TotalSize);
|
||||
this->Reader->ReadArray(buffer);
|
||||
if ((this->Association != vtkm::cont::Field::Association::Cells) ||
|
||||
(this->Reader->GetCellsPermutation().GetNumberOfValues() < 1))
|
||||
{
|
||||
*this->Data = CreateUnknownArrayHandle(buffer);
|
||||
*this->Data =
|
||||
vtkm::cont::make_ArrayHandleRuntimeVecMove(this->NumComponents, std::move(buffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -734,20 +578,14 @@ public:
|
||||
std::size_t inIndex = static_cast<std::size_t>(permutation.Get(outIndex));
|
||||
permutedBuffer[static_cast<std::size_t>(outIndex)] = buffer[inIndex];
|
||||
}
|
||||
*this->Data = CreateUnknownArrayHandle(permutedBuffer);
|
||||
*this->Data =
|
||||
vtkm::cont::make_ArrayHandleRuntimeVecMove(this->NumComponents, std::move(permutedBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for " << numComponents << " components not implemented. Skipping.");
|
||||
SkipArrayVariant::operator()(numComponents, T());
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::cont::Field::Association Association;
|
||||
vtkm::IdComponent NumComponents;
|
||||
vtkm::cont::UnknownArrayHandle* Data;
|
||||
};
|
||||
|
||||
@ -764,8 +602,8 @@ void VTKDataSetReaderBase::DoSkipArrayVariant(std::string dataType,
|
||||
else
|
||||
{
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, SkipArrayVariant(this, numElements));
|
||||
vtkm::io::internal::SelectTypeAndCall(typeId,
|
||||
SkipArrayVariant(this, numElements, numComponents));
|
||||
}
|
||||
}
|
||||
|
||||
@ -791,7 +629,7 @@ vtkm::cont::UnknownArrayHandle VTKDataSetReaderBase::DoReadArrayVariant(
|
||||
{
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, ReadArrayVariant(this, association, numElements, data));
|
||||
typeId, ReadArrayVariant(this, association, numElements, numComponents, data));
|
||||
}
|
||||
|
||||
return data;
|
||||
|
@ -170,73 +170,45 @@ struct DataTypeName<vtkm::Float64>
|
||||
static const char* Name() { return "double"; }
|
||||
};
|
||||
|
||||
template <typename T, typename Functor>
|
||||
inline void SelectVecTypeAndCall(T, vtkm::IdComponent numComponents, const Functor& functor)
|
||||
{
|
||||
switch (numComponents)
|
||||
{
|
||||
case 1:
|
||||
functor(T());
|
||||
break;
|
||||
case 2:
|
||||
functor(vtkm::Vec<T, 2>());
|
||||
break;
|
||||
case 3:
|
||||
functor(vtkm::Vec<T, 3>());
|
||||
break;
|
||||
case 4:
|
||||
functor(vtkm::Vec<T, 4>());
|
||||
break;
|
||||
case 9:
|
||||
functor(vtkm::Vec<T, 9>());
|
||||
break;
|
||||
default:
|
||||
functor(numComponents, T());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
inline void SelectTypeAndCall(DataType dtype,
|
||||
vtkm::IdComponent numComponents,
|
||||
const Functor& functor)
|
||||
inline void SelectTypeAndCall(DataType dtype, Functor&& functor)
|
||||
{
|
||||
switch (dtype)
|
||||
{
|
||||
case DTYPE_BIT:
|
||||
SelectVecTypeAndCall(DummyBitType(), numComponents, functor);
|
||||
functor(DummyBitType());
|
||||
break;
|
||||
case DTYPE_UNSIGNED_CHAR:
|
||||
SelectVecTypeAndCall(vtkm::UInt8(), numComponents, functor);
|
||||
functor(vtkm::UInt8());
|
||||
break;
|
||||
case DTYPE_CHAR:
|
||||
SelectVecTypeAndCall(vtkm::Int8(), numComponents, functor);
|
||||
functor(vtkm::Int8());
|
||||
break;
|
||||
case DTYPE_UNSIGNED_SHORT:
|
||||
SelectVecTypeAndCall(vtkm::UInt16(), numComponents, functor);
|
||||
functor(vtkm::UInt16());
|
||||
break;
|
||||
case DTYPE_SHORT:
|
||||
SelectVecTypeAndCall(vtkm::Int16(), numComponents, functor);
|
||||
functor(vtkm::Int16());
|
||||
break;
|
||||
case DTYPE_UNSIGNED_INT:
|
||||
SelectVecTypeAndCall(vtkm::UInt32(), numComponents, functor);
|
||||
functor(vtkm::UInt32());
|
||||
break;
|
||||
case DTYPE_INT:
|
||||
SelectVecTypeAndCall(vtkm::Int32(), numComponents, functor);
|
||||
functor(vtkm::Int32());
|
||||
break;
|
||||
case DTYPE_UNSIGNED_LONG:
|
||||
case DTYPE_UNSIGNED_LONG_LONG:
|
||||
SelectVecTypeAndCall(vtkm::UInt64(), numComponents, functor);
|
||||
functor(vtkm::UInt64());
|
||||
break;
|
||||
case DTYPE_LONG:
|
||||
case DTYPE_LONG_LONG:
|
||||
SelectVecTypeAndCall(vtkm::Int64(), numComponents, functor);
|
||||
functor(vtkm::Int64());
|
||||
break;
|
||||
case DTYPE_FLOAT:
|
||||
SelectVecTypeAndCall(vtkm::Float32(), numComponents, functor);
|
||||
functor(vtkm::Float32());
|
||||
break;
|
||||
case DTYPE_DOUBLE:
|
||||
SelectVecTypeAndCall(vtkm::Float64(), numComponents, functor);
|
||||
functor(vtkm::Float64());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <vtkm/cont/ArrayHandleSOA.h>
|
||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||
#include <vtkm/io/VTKDataSetReader.h>
|
||||
#include <vtkm/io/VTKDataSetWriter.h>
|
||||
|
||||
@ -122,7 +123,7 @@ void CheckWrittenReadData(const vtkm::cont::DataSet& originalData,
|
||||
VTKM_TEST_ASSERT(fileData.HasField(originalField.GetName(), originalField.GetAssociation()));
|
||||
vtkm::cont::Field fileField =
|
||||
fileData.GetField(originalField.GetName(), originalField.GetAssociation());
|
||||
vtkm::cont::CastAndCall(originalField, CheckSameField{}, fileField);
|
||||
VTKM_TEST_ASSERT(test_equal_ArrayHandles(originalField.GetData(), fileField.GetData()));
|
||||
}
|
||||
|
||||
VTKM_TEST_ASSERT(fileData.GetNumberOfCoordinateSystems() > 0);
|
||||
@ -261,12 +262,31 @@ void TestVTKCompoundWrite()
|
||||
std::remove("chirp.vtk");
|
||||
}
|
||||
|
||||
void TestVTKOddVecSizes()
|
||||
{
|
||||
vtkm::cont::DataSetBuilderUniform dsb;
|
||||
vtkm::cont::DataSet dataSet = dsb.Create({ 2, 2, 2 });
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 5>> vec5Array;
|
||||
vec5Array.Allocate(dataSet.GetNumberOfPoints());
|
||||
SetPortal(vec5Array.WritePortal());
|
||||
dataSet.AddPointField("vec5", vec5Array);
|
||||
|
||||
vtkm::cont::ArrayHandleSOA<vtkm::Vec<vtkm::FloatDefault, 13>> vec13Array;
|
||||
vec13Array.Allocate(dataSet.GetNumberOfPoints());
|
||||
SetPortal(vec13Array.WritePortal());
|
||||
dataSet.AddPointField("vec13", vec13Array);
|
||||
|
||||
TestVTKWriteTestData("OddVecSizes", dataSet);
|
||||
}
|
||||
|
||||
void TestVTKWrite()
|
||||
{
|
||||
TestVTKExplicitWrite();
|
||||
TestVTKUniformWrite();
|
||||
TestVTKRectilinearWrite();
|
||||
TestVTKCompoundWrite();
|
||||
TestVTKOddVecSizes();
|
||||
}
|
||||
|
||||
} //Anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user