// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-FileCopyrightText: Copyright (c) Kitware, Inc. // SPDX-FileCopyrightText: Copyright 2019 Sandia Corporation. // SPDX-FileCopyrightText: Copyright 2019 UT-Battelle, LLC. // SPDX-FileCopyrightText: Copyright 2019 Los Alamos National Security. // SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Sandia-LANL-USGov #ifndef vtkmDataArray_hxx #define vtkmDataArray_hxx #include "vtkObjectFactory.h" #include "vtkmDataArrayUtilities.h" #include #include #include #include #include #include #include #include #include #ifndef vtkmDataArray_h #error "vtkmDataArray.hxx should only be included from vtkmDataArray.h." #include // For IDEs #endif namespace fromvtkm { VTK_ABI_NAMESPACE_BEGIN //----------------------------------------------------------------------------- struct NotMaskValue { viskores::UInt8 MaskValue; VISKORES_EXEC_CONT viskores::UInt8 operator()(viskores::UInt8 value) const { return static_cast(value != this->MaskValue); } }; //----------------------------------------------------------------------------- template class ArrayHandleHelperBase { public: using ValueType = T; ArrayHandleHelperBase(const viskores::cont::UnknownArrayHandle& vtkmArray) : VtkmArray(vtkmArray) { assert(vtkmArray.IsBaseComponentType()); } virtual ~ArrayHandleHelperBase() = default; enum class HelperType { Unknown, Read, Write }; virtual HelperType GetHelperType() const = 0; viskores::IdComponent GetNumberOfComponents() const { return this->VtkmArray.GetNumberOfComponentsFlat(); } void Reallocate(const vtkmDataArray* self, viskores::Id numberOfTuples) { this->VtkmArray.Allocate(numberOfTuples, viskores::CopyFlag::On); this->ResetHelper(self); } bool ComputeScalarRange(const vtkmDataArray* self, double* ranges, const unsigned char* ghosts, viskores::UInt8 ghostValueToSkip, bool finitesOnly); bool ComputeVectorRange(const vtkmDataArray* self, double range[2], const unsigned char* ghosts, viskores::UInt8 ghostValueToSkip, bool finitesOnly); viskores::cont::UnknownArrayHandle GetArrayHandle() const { return this->VtkmArray; } virtual void GetTuple( const vtkmDataArray* self, viskores::Id valIdx, ValueType* values) const = 0; virtual void SetTuple( const vtkmDataArray* self, viskores::Id valIdx, const ValueType* values) = 0; virtual ValueType GetComponent( const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx) const = 0; virtual void SetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const ValueType& value) = 0; protected: viskores::cont::UnknownArrayHandle VtkmArray; private: // Some operations might invalidate portals and other information pulled from the ArrayHandle, // so reset the helper registered with the vtkmDataArray so that they get re-pulled if necessary. void ResetHelper(const vtkmDataArray* self); }; template class ArrayHandleHelperUnknown : public ArrayHandleHelperBase { public: ArrayHandleHelperUnknown(const viskores::cont::UnknownArrayHandle& array) : ArrayHandleHelperBase(array) { } using typename ArrayHandleHelperBase::HelperType; HelperType GetHelperType() const override { return HelperType::Unknown; } void GetTuple(const vtkmDataArray* self, viskores::Id valIdx, T* values) const override; void SetTuple(const vtkmDataArray* self, viskores::Id valIdx, const T* values) override; T GetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx) const override; void SetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) override; private: ArrayHandleHelperBase* SwapReadHelper(const vtkmDataArray* self) const; ArrayHandleHelperBase* SwapWriteHelper(const vtkmDataArray* self) const; }; template std::unique_ptr> MakeArrayHandleHelperUnknown( const viskores::cont::UnknownArrayHandle& array) { return std::unique_ptr>{ new ArrayHandleHelperUnknown(array) }; } template class ArrayHandleHelperWrite : public ArrayHandleHelperBase< typename viskores::VecTraits::BaseComponentType> { using T = typename viskores::VecTraits::BaseComponentType; public: ArrayHandleHelperWrite(const viskores::cont::UnknownArrayHandle& array); using typename ArrayHandleHelperBase::HelperType; HelperType GetHelperType() const override { return HelperType::Write; } void GetTuple(const vtkmDataArray* self, viskores::Id valIdx, T* values) const override; void SetTuple(const vtkmDataArray* self, viskores::Id valIdx, const T* values) override; T GetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx) const override; void SetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) override; private: ArrayHandleType TypedArray; typename ArrayHandleType::WritePortalType WritePortal; }; template std::unique_ptr::BaseComponentType>> MakeArrayHandleHelperWrite(const ArrayHandleType& array) { return std::unique_ptr::BaseComponentType>>{ new ArrayHandleHelperWrite(array) }; } template class ArrayHandleHelperRead : public ArrayHandleHelperBase< typename viskores::VecTraits::BaseComponentType> { using T = typename viskores::VecTraits::BaseComponentType; public: ArrayHandleHelperRead(const viskores::cont::UnknownArrayHandle& array); using typename ArrayHandleHelperBase::HelperType; HelperType GetHelperType() const override { return HelperType::Read; } void GetTuple(const vtkmDataArray* self, viskores::Id valIdx, T* values) const override; void SetTuple(const vtkmDataArray* self, viskores::Id valIdx, const T* values) override; T GetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx) const override; void SetComponent(const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) override; private: ArrayHandleType TypedArray; typename ArrayHandleType::ReadPortalType ReadPortal; }; template std::unique_ptr::BaseComponentType>> MakeArrayHandleHelperRead(const ArrayHandleType& array) { return std::unique_ptr::BaseComponentType>>{ new ArrayHandleHelperRead(array) }; } //----------------------------------------------------------------------------- template bool ArrayHandleHelperBase::ComputeScalarRange(const vtkmDataArray* self, double* ranges, const unsigned char* ghosts, viskores::UInt8 ghostValueToSkip, bool finitesOnly) { if (this->VtkmArray.GetNumberOfValues() < 1) { for (int i = 0; i < this->GetNumberOfComponents(); ++i) { ranges[(2 * i) + 0] = VTK_DOUBLE_MAX; ranges[(2 * i) + 1] = VTK_DOUBLE_MIN; } return false; } viskores::cont::ArrayHandle ghostArray; if (ghosts) { ghostArray = viskores::cont::make_ArrayHandle( ghosts, this->VtkmArray.GetNumberOfValues(), viskores::CopyFlag::Off); if (ghostValueToSkip != 0) { auto transform = viskores::cont::make_ArrayHandleTransform(ghostArray, NotMaskValue{ ghostValueToSkip }); viskores::cont::ArrayHandle newGhostArray; viskores::cont::ArrayCopy(transform, newGhostArray); ghostArray = newGhostArray; } } viskores::cont::ArrayHandle rangeArray = viskores::cont::ArrayRangeCompute(this->VtkmArray, ghostArray, finitesOnly); auto rangePortal = rangeArray.ReadPortal(); for (viskores::IdComponent index = 0; index < rangePortal.GetNumberOfValues(); ++index) { viskores::Range r = rangePortal.Get(index); ranges[(2 * index) + 0] = r.Min; ranges[(2 * index) + 1] = r.Max; } this->ResetHelper(self); return true; } template bool ArrayHandleHelperBase::ComputeVectorRange(const vtkmDataArray* self, double range[2], const unsigned char* ghosts, viskores::UInt8 ghostValueToSkip, bool finitesOnly) { if (this->VtkmArray.GetNumberOfValues() < 1) { range[0] = VTK_DOUBLE_MAX; range[1] = VTK_DOUBLE_MIN; return false; } viskores::cont::ArrayHandle ghostArray; if (ghosts) { ghostArray = viskores::cont::make_ArrayHandle( ghosts, this->VtkmArray.GetNumberOfValues(), viskores::CopyFlag::Off); if (ghostValueToSkip != 0) { auto transform = viskores::cont::make_ArrayHandleTransform(ghostArray, NotMaskValue{ ghostValueToSkip }); viskores::cont::ArrayHandle newGhostArray; viskores::cont::ArrayCopy(transform, newGhostArray); ghostArray = newGhostArray; } } viskores::Range r = viskores::cont::ArrayRangeComputeMagnitude(this->VtkmArray, ghostArray, finitesOnly); range[0] = r.Min; range[1] = r.Max; this->ResetHelper(self); return true; } template void ArrayHandleHelperBase::ResetHelper(const vtkmDataArray* self) { auto newHelper = MakeArrayHandleHelperUnknown(this->VtkmArray); self->Helper.swap(newHelper); } //----------------------------------------------------------------------------- template void ArrayHandleHelperUnknown::GetTuple( const vtkmDataArray* self, viskores::Id valIdx, T* values) const { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for reading if (self->Helper->GetHelperType() != HelperType::Read && self->Helper->GetHelperType() != HelperType::Write) { this->SwapReadHelper(self); } self->Helper->GetTuple(self, valIdx, values); } template void ArrayHandleHelperUnknown::SetTuple( const vtkmDataArray* self, viskores::Id valIdx, const T* values) { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for writing if (self->Helper->GetHelperType() != HelperType::Write) { this->SwapWriteHelper(self); } self->Helper->SetTuple(self, valIdx, values); } template T ArrayHandleHelperUnknown::GetComponent( const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx) const { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for reading if (self->Helper->GetHelperType() != HelperType::Read && self->Helper->GetHelperType() != HelperType::Write) { this->SwapReadHelper(self); } return self->Helper->GetComponent(self, valIdx, compIdx); } template void ArrayHandleHelperUnknown::SetComponent( const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for writing if (self->Helper->GetHelperType() != HelperType::Write) { this->SwapWriteHelper(self); } self->Helper->SetComponent(self, valIdx, compIdx, value); } template ArrayHandleHelperBase* ArrayHandleHelperUnknown::SwapReadHelper( const vtkmDataArray* self) const { std::unique_ptr> newHelper; if (this->VtkmArray.template CanConvert>()) { newHelper = MakeArrayHandleHelperRead( this->VtkmArray.template AsArrayHandle>()); } else if (this->VtkmArray.template CanConvert>()) { newHelper = MakeArrayHandleHelperRead( this->VtkmArray.template AsArrayHandle>()); } else if (this->VtkmArray.template CanConvert>()) { newHelper = MakeArrayHandleHelperRead( this->VtkmArray.template AsArrayHandle>()); } else { if constexpr (std::is_same_v) { if (this->VtkmArray.template CanConvert()) { newHelper = MakeArrayHandleHelperRead( this->VtkmArray.template AsArrayHandle()); } else { newHelper = MakeArrayHandleHelperRead(this->VtkmArray.template ExtractArrayFromComponents()); } } else { newHelper = MakeArrayHandleHelperRead(this->VtkmArray.template ExtractArrayFromComponents()); } } self->Helper.swap(newHelper); return self->Helper.get(); } template ArrayHandleHelperBase* ArrayHandleHelperUnknown::SwapWriteHelper( const vtkmDataArray* self) const { std::unique_ptr> newHelper; if (this->VtkmArray.template CanConvert>()) { newHelper = MakeArrayHandleHelperWrite( this->VtkmArray.template AsArrayHandle>()); } else { newHelper = MakeArrayHandleHelperWrite(this->VtkmArray.template ExtractArrayFromComponents()); } self->Helper.swap(newHelper); return self->Helper.get(); } //----------------------------------------------------------------------------- template ArrayHandleHelperWrite::ArrayHandleHelperWrite( const viskores::cont::UnknownArrayHandle& array) : ArrayHandleHelperBase(array) , TypedArray(array.AsArrayHandle()) , WritePortal(TypedArray.WritePortal()) { } template void ArrayHandleHelperWrite::GetTuple( const vtkmDataArray*, viskores::Id valIdx, T* values) const { auto tuple = this->WritePortal.Get(valIdx); using VTraits = viskores::VecTraits; for (viskores::IdComponent cIndex = 0; cIndex < VTraits::GetNumberOfComponents(tuple); ++cIndex) { values[cIndex] = VTraits::GetComponent(tuple, cIndex); } } namespace detail { template void SetTupleImpl(const ArrayPortal& portal, viskores::Id valIdx, const T* values, std::true_type) { // It's a little weird to get a value to set it, but these arrays with variable length Vecs // actually return a reference back to the array, so you are actually just setting values // into the array. auto tuple = portal.Get(valIdx); using VTraits = viskores::VecTraits; for (viskores::IdComponent cIndex = 0; cIndex < VTraits::GetNumberOfComponents(tuple); ++cIndex) { VTraits::SetComponent(tuple, cIndex, values[cIndex]); } portal.Set(valIdx, tuple); } template void SetTupleImpl(const ArrayPortal&, viskores::Id, const T*, std::false_type) { assert(0 && "Attempted to write to read-only Viskores array."); } } // namespace detail template void ArrayHandleHelperWrite::SetTuple( const vtkmDataArray* vtkNotUsed(self), viskores::Id valIdx, const T* values) { detail::SetTupleImpl(this->WritePortal, valIdx, values, viskores::internal::PortalSupportsSetsWritePortal)>{}); } template auto ArrayHandleHelperWrite::GetComponent(const vtkmDataArray* vtkNotUsed(self), viskores::Id valIdx, viskores::IdComponent compIdx) const -> T { auto tuple = this->WritePortal.Get(valIdx); using VTraits = viskores::VecTraits; return VTraits::GetComponent(tuple, compIdx); } namespace detail { template void SetComponentImpl(const ArrayPortal& portal, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value, std::true_type) { // It's a little weird to get a value to set it, but these arrays with variable length Vecs // actually return a reference back to the array, so you are actually just setting values // into the array. auto tuple = portal.Get(valIdx); using VTraits = viskores::VecTraits; VTraits::SetComponent(tuple, compIdx, value); portal.Set(valIdx, tuple); } template void SetComponentImpl( const ArrayPortal&, viskores::Id, viskores::IdComponent, const T&, std::false_type) { assert(0 && "Attempted to write to read-only Viskores array."); } } // namespace detail template void ArrayHandleHelperWrite::SetComponent(const vtkmDataArray* vtkNotUsed(self), viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) { detail::SetComponentImpl(this->WritePortal, valIdx, compIdx, value, viskores::internal::PortalSupportsSetsWritePortal)>{}); } //----------------------------------------------------------------------------- // The write helper does all that the read helper does and more. However, we have a separate // read helper because the construction of the write helper will delete any data on the // device, so we have a read subset that allows leaving the data on the device. template ArrayHandleHelperRead::ArrayHandleHelperRead( const viskores::cont::UnknownArrayHandle& array) : ArrayHandleHelperBase(array) , TypedArray(array.AsArrayHandle()) , ReadPortal(TypedArray.ReadPortal()) { } template void ArrayHandleHelperRead::GetTuple( const vtkmDataArray*, viskores::Id valIdx, T* values) const { auto tuple = this->ReadPortal.Get(valIdx); using VTraits = viskores::VecTraits; for (viskores::IdComponent cIndex = 0; cIndex < VTraits::GetNumberOfComponents(tuple); ++cIndex) { values[cIndex] = VTraits::GetComponent(tuple, cIndex); } } template void ArrayHandleHelperRead::SetTuple( const vtkmDataArray* self, viskores::Id valIdx, const T* values) { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for writing if (self->Helper->GetHelperType() != HelperType::Write) { auto helper = MakeArrayHandleHelperWrite(this->TypedArray); self->Helper.swap(helper); } self->Helper->SetTuple(self, valIdx, values); } template auto ArrayHandleHelperRead::GetComponent(const vtkmDataArray* vtkNotUsed(self), viskores::Id valIdx, viskores::IdComponent compIdx) const -> T { auto tuple = this->ReadPortal.Get(valIdx); using VTraits = viskores::VecTraits; return VTraits::GetComponent(tuple, compIdx); } template void ArrayHandleHelperRead::SetComponent( const vtkmDataArray* self, viskores::Id valIdx, viskores::IdComponent compIdx, const T& value) { std::lock_guard lock(self->Mutex); // Check if we already have a suitable helper for writing if (self->Helper->GetHelperType() != HelperType::Write) { auto helper = MakeArrayHandleHelperWrite(this->TypedArray); self->Helper.swap(helper); } self->Helper->SetComponent(self, valIdx, compIdx, value); } VTK_ABI_NAMESPACE_END } // fromvtkm VTK_ABI_NAMESPACE_BEGIN //============================================================================= template vtkmDataArray::vtkmDataArray() = default; template vtkmDataArray::~vtkmDataArray() = default; template vtkmDataArray* vtkmDataArray::New() { VTK_STANDARD_NEW_BODY(vtkmDataArray); } template void vtkmDataArray::SetVtkmArrayHandle(const viskores::cont::UnknownArrayHandle& ah) { this->Helper = fromvtkm::MakeArrayHandleHelperUnknown(ah); this->SetNumberOfComponents(this->Helper->GetNumberOfComponents()); this->Size = ah.GetNumberOfValues() * this->GetNumberOfComponents(); this->MaxId = this->Size - 1; } template viskores::cont::UnknownArrayHandle vtkmDataArray::GetVtkmUnknownArrayHandle() const { if (this->Helper) { return this->Helper->GetArrayHandle(); } return {}; } //----------------------------------------------------------------------------- template void* vtkmDataArray::GetVoidPointer(vtkIdType valueIdx) { viskores::cont::ArrayHandleRuntimeVec array{ this->GetNumberOfComponents() }; if (this->GetVtkmUnknownArrayHandle().template CanConvert()) { this->GetVtkmUnknownArrayHandle().AsArrayHandle(array); } else { // Data does not appear to be in a basic layout. Copy array. viskores::cont::ArrayCopy(this->GetVtkmUnknownArrayHandle(), array); this->SetVtkmArrayHandle(array); } // Get the write pointer to the data (since there is no way to know whether // this array will be written to). T* pointer = array.GetComponentsArray().GetWritePointer(); return &(pointer[valueIdx]); } //----------------------------------------------------------------------------- template void* vtkmDataArray::GetDeviceVoidPointer(vtkIdType valueIdx) { viskores::cont::ArrayHandleRuntimeVec array{ this->GetNumberOfComponents() }; if (this->GetVtkmUnknownArrayHandle().template CanConvert()) { this->GetVtkmUnknownArrayHandle().AsArrayHandle(array); } else { // Data does not appear to be in a basic layout. Copy array. viskores::cont::ArrayCopy(this->GetVtkmUnknownArrayHandle(), array); this->SetVtkmArrayHandle(array); } // Get the write pointer to the data (since there is no way to know whether // this array will be written to). auto& tracker = viskores::cont::GetRuntimeDeviceTracker(); viskores::cont::Token token; if (tracker.CanRunOn(viskores::cont::DeviceAdapterTagCuda{})) { T* pointer = array.GetComponentsArray().GetWritePointer(viskores::cont::DeviceAdapterTagCuda{}); return &(pointer[valueIdx]); } if (tracker.CanRunOn(viskores::cont::DeviceAdapterTagKokkos{})) { T* pointer = array.GetComponentsArray().GetWritePointer(viskores::cont::DeviceAdapterTagKokkos{}); return &(pointer[valueIdx]); } return nullptr; } template void* vtkmDataArray::WriteVoidPointer(vtkIdType valueIdx, vtkIdType numValues) { vtkIdType numTuples = (numValues + this->NumberOfComponents - 1) / this->NumberOfComponents; this->ReallocateTuples(numTuples); return this->GetVoidPointer(valueIdx); } //----------------------------------------------------------------------------- template auto vtkmDataArray::GetValue(vtkIdType valueIdx) const -> ValueType { assert(this->Helper); auto idx = valueIdx / this->GetNumberOfComponents(); auto comp = valueIdx % this->GetNumberOfComponents(); return this->Helper->GetComponent(this, idx, comp); } template void vtkmDataArray::SetValue(vtkIdType valueIdx, ValueType value) { assert(this->Helper); auto idx = valueIdx / this->GetNumberOfComponents(); auto comp = valueIdx % this->GetNumberOfComponents(); try { this->Helper->SetComponent(this, idx, comp, value); } catch (viskores::cont::Error) { vtkErrorMacro(<< "Underlying ArrayHandle (" << this->Helper->GetArrayHandle().GetArrayTypeName() << ") does not support writes through vtkmDataArray"); } } template void vtkmDataArray::GetTypedTuple(vtkIdType tupleIdx, ValueType* tuple) const { assert(this->Helper); this->Helper->GetTuple(this, tupleIdx, tuple); } template void vtkmDataArray::SetTypedTuple(vtkIdType tupleIdx, const ValueType* tuple) { assert(this->Helper); try { this->Helper->SetTuple(this, tupleIdx, tuple); } catch (viskores::cont::Error) { vtkErrorMacro(<< "Underlying ArrayHandle (" << this->Helper->GetArrayHandle().GetArrayTypeName() << ") is read-only"); } } template auto vtkmDataArray::GetTypedComponent(vtkIdType tupleIdx, int compIdx) const -> ValueType { assert(this->Helper); return this->Helper->GetComponent(this, tupleIdx, compIdx); } template void vtkmDataArray::SetTypedComponent(vtkIdType tupleIdx, int compIdx, ValueType value) { assert(this->Helper); try { this->Helper->SetComponent(this, tupleIdx, compIdx, value); } catch (viskores::cont::Error) { vtkErrorMacro(<< "Underlying ArrayHandle (" << this->Helper->GetArrayHandle().GetArrayTypeName() << ") is read-only"); } } //----------------------------------------------------------------------------- template bool vtkmDataArray::ComputeScalarRange( double* ranges, const unsigned char* ghosts, unsigned char ghostsToSkip) { if (this->Helper) { return this->Helper->ComputeScalarRange(this, ranges, ghosts, ghostsToSkip, false); } return false; } template bool vtkmDataArray::ComputeVectorRange( double range[2], const unsigned char* ghosts, unsigned char ghostsToSkip) { if (this->Helper) { return this->Helper->ComputeVectorRange(this, range, ghosts, ghostsToSkip, false); } return false; } template bool vtkmDataArray::ComputeFiniteScalarRange( double* ranges, const unsigned char* ghosts, unsigned char ghostsToSkip) { if (this->Helper) { return this->Helper->ComputeScalarRange(this, ranges, ghosts, ghostsToSkip, true); } return false; } template bool vtkmDataArray::ComputeFiniteVectorRange( double range[2], const unsigned char* ghosts, unsigned char ghostsToSkip) { if (this->Helper) { return this->Helper->ComputeVectorRange(this, range, ghosts, ghostsToSkip, true); } return false; } //----------------------------------------------------------------------------- template bool vtkmDataArray::AllocateTuples(vtkIdType numberOfTuples) { viskores::cont::ArrayHandleRuntimeVec arrayHandle(this->NumberOfComponents); arrayHandle.Allocate(numberOfTuples); // Reset helper since any held portals have been invalidated. this->Helper = fromvtkm::MakeArrayHandleHelperUnknown(arrayHandle); // Size and MaxId are updated by the caller return true; } //----------------------------------------------------------------------------- template bool vtkmDataArray::ReallocateTuples(vtkIdType numberOfTuples) { if (this->Helper) { // Size and MaxId are updated by the caller try { this->Helper->Reallocate(this, numberOfTuples); return true; } catch (viskores::cont::Error) { vtkErrorMacro(<< "Underlying ArrayHandle (" << this->Helper->GetArrayHandle().GetArrayTypeName() << ") does not support reallocation through vtkmDataArray"); return false; } } return this->AllocateTuples(numberOfTuples); } //----------------------------------------------------------------------------- template vtkDataArray::MemorySpace vtkmDataArray::GetMemorySpace() { auto pointer = this->GetDeviceVoidPointer(0); if (pointer) { if (vtkmDataArrayUtilities::IsCudaDevicePointer(pointer)) { return vtkDataArray::MemorySpace::CudaDeviceMemory; } if (vtkmDataArrayUtilities::IsHipDevicePointer(pointer)) { return vtkDataArray::MemorySpace::HipDeviceMemory; } } return vtkDataArray::MemorySpace::HostMemory; } VTK_ABI_NAMESPACE_END #endif // vtkmDataArray_hxx