From ac024587a6734e58b47f69f15d19885c7dae3cbb Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 13 Dec 2021 14:04:43 -0700 Subject: [PATCH 1/5] Add UncertainCellSet This is a replacement for DynamicCellSet that requires less templating. --- docs/changelog/unknowncellset.md | 21 ++ vtkm/cont/CMakeLists.txt | 3 + vtkm/cont/UncertainCellSet.h | 206 +++++++++++++ vtkm/cont/UnknownArrayHandle.h | 2 +- vtkm/cont/UnknownCellSet.cxx | 114 +++++++ vtkm/cont/UnknownCellSet.h | 301 +++++++++++++++++++ vtkm/cont/testing/CMakeLists.txt | 1 + vtkm/cont/testing/UnitTestUnknownCellSet.cxx | 175 +++++++++++ 8 files changed, 822 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/unknowncellset.md create mode 100644 vtkm/cont/UncertainCellSet.h create mode 100644 vtkm/cont/UnknownCellSet.cxx create mode 100644 vtkm/cont/UnknownCellSet.h create mode 100644 vtkm/cont/testing/UnitTestUnknownCellSet.cxx diff --git a/docs/changelog/unknowncellset.md b/docs/changelog/unknowncellset.md new file mode 100644 index 000000000..3c8cf4b57 --- /dev/null +++ b/docs/changelog/unknowncellset.md @@ -0,0 +1,21 @@ +# UnknownCellSet + +The `DynamicCellSet` class has been replaced with `UnknownCellSet`. +Likewise, the `DynamicCellSetBase` class (a templated version of +`DynamicCellSet`) has been replaced with `UncertainCellSet`. + +These changes principally follow the changes to the `UnknownArrayHandle` +management class. The `ArrayHandle` version of a polymorphic manager has +gone through several refinements from `DynamicArrayHandle` to +`VariantArrayHandle` to its current form as `UnknownArrayHandle`. +Throughout these improvements for `ArrayHandle`, the equivalent classes for +`CellSet` have lagged behind. The `CellSet` version is decidedly simpler +because `CellSet` itself is polymorphic, but there were definitely +improvements to be had. + +The biggest improvement was to remove the templating from the basic unknown +cell set. The old `DynamicArrayHandle` was actually a type alias for +`DynamicArrayHandleBase`. As +`VTKM_DEFAULT_CELL_SET_LIST` tends to be pretty long, `DynamicArrayHandle` +was actually a really long type. In contrast, `UnknownArrayHandle` is its +own untemplated class and will show up in linker symbols as such. diff --git a/vtkm/cont/CMakeLists.txt b/vtkm/cont/CMakeLists.txt index c59ca8f59..4002e9a75 100644 --- a/vtkm/cont/CMakeLists.txt +++ b/vtkm/cont/CMakeLists.txt @@ -122,7 +122,9 @@ set(headers TryExecute.h SerializableTypeString.h UncertainArrayHandle.h + UncertainCellSet.h UnknownArrayHandle.h + UnknownCellSet.h VariantArrayHandle.h ) @@ -157,6 +159,7 @@ set(sources Storage.cxx Token.cxx TryExecute.cxx + UnknownCellSet.cxx ) # This list of sources has code that uses devices and so might need to be diff --git a/vtkm/cont/UncertainCellSet.h b/vtkm/cont/UncertainCellSet.h new file mode 100644 index 000000000..3ab9f02a7 --- /dev/null +++ b/vtkm/cont/UncertainCellSet.h @@ -0,0 +1,206 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// 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_cont_UncertainCellSet_h +#define vtk_m_cont_UncertainCellSet_h + +#include + +namespace vtkm +{ +namespace cont +{ + +/// \brief A `CellSet` of an uncertain type. +/// +/// `UncertainCellSet` holds a `CellSet` object using runtime polymorphism to +/// manage different types. It behaves like its superclass, `UnknownCellSet`, +/// except that it also contains a template parameter that provides a +/// `vtkm::List` of potential cell set types. +/// +/// These potental types come into play when the `CastAndCall` method is called +/// (or the `UncertainCellSet` is used in the `vtkm::cont::CastAndCall` function). +/// In this case, the `CastAndCall` will search for `CellSet`s of types that match +/// this list. +/// +/// Both `UncertainCellSet` and `UnknownCellSet` have a method named +/// `ResetCellSetList` that redefines the list of potential cell sets by returning +/// a new `UncertainCellSet` containing the same `CellSet` but with the new cell +/// set type list. +/// +template +class VTKM_ALWAYS_EXPORT UncertainCellSet : public vtkm::cont::UnknownCellSet +{ + VTKM_IS_LIST(CellSetList); + + VTKM_STATIC_ASSERT_MSG((!std::is_same::value), + "Cannot use vtkm::ListUniversal with UncertainCellSet."); + + using Superclass = UnknownCellSet; + using Thisclass = UncertainCellSet; + +public: + VTKM_CONT UncertainCellSet() = default; + + template + explicit VTKM_CONT UncertainCellSet(const CellSetType& cellSet) + : Superclass(cellSet) + { + } + + explicit VTKM_CONT UncertainCellSet(const vtkm::cont::UnknownCellSet& src) + : Superclass(src) + { + } + + UncertainCellSet(const Thisclass&) = default; + + template + explicit VTKM_CONT UncertainCellSet(const UncertainCellSet& src) + : Superclass(src) + { + } + + /// \brief Create a new cell set of the same type as this. + /// + /// This method creates a new array that is the same type as this one and + /// returns a new `UncertainCellSet` for it. + /// + VTKM_CONT Thisclass NewInstance() const { return Thisclass(this->Superclass::NewInstance()); } + + /// \brief Call a functor using the underlying array type. + /// + /// `CastAndCall` attempts to cast the held array to a specific value type, + /// and then calls the given functor with the cast array. + /// + template + VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const + { + this->CastAndCallForTypes(std::forward(functor), + std::forward(args)...); + } +}; + +// Defined here to avoid circular dependencies between UnknownArrayHandle and UncertainArrayHandle. +template +VTKM_CONT vtkm::cont::UncertainCellSet UnknownCellSet::ResetCellSetList( + NewCellSetList) const +{ + return vtkm::cont::UncertainCellSet(*this); +} +template +VTKM_CONT vtkm::cont::UncertainCellSet UnknownCellSet::ResetCellSetList() const +{ + return vtkm::cont::UncertainCellSet(*this); +} + +namespace internal +{ + +template +struct DynamicTransformTraits> +{ + using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; +}; + +} // namespace internal + +} // namespace vtkm::cont +} // namespace vtkm + +//============================================================================= +// Specializations of serialization related classes +/// @cond SERIALIZATION + +namespace vtkm +{ +namespace cont +{ + +template +struct SerializableTypeString> +{ + static VTKM_CONT std::string Get() + { + return SerializableTypeString::Get(); + } +}; +} +} // namespace vtkm::cont + +namespace mangled_diy_namespace +{ + +namespace internal +{ + +struct UncertainCellSetSerializeFunctor +{ + template + void operator()(const CellSetType& cs, BinaryBuffer& bb) const + { + vtkmdiy::save(bb, vtkm::cont::SerializableTypeString::Get()); + vtkmdiy::save(bb, cs); + } +}; + +struct UncertainCellSetDeserializeFunctor +{ + template + void operator()(CellSetType, + vtkm::cont::UnknownCellSet& unknownArray, + const std::string& typeString, + bool& success, + BinaryBuffer& bb) const + { + if (!success && (typeString == vtkm::cont::SerializableTypeString::Get())) + { + CellSetType knownArray; + vtkmdiy::load(bb, knownArray); + unknownArray = knownArray; + success = true; + } + } +}; + +} // internal + +template +struct Serialization> +{ + using Type = vtkm::cont::UncertainCellSet; + +public: + static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj) + { + obj.CastAndCall(internal::UncertainCellSetSerializeFunctor{}, bb); + } + + static VTKM_CONT void load(BinaryBuffer& bb, Type& obj) + { + std::string typeString; + vtkmdiy::load(bb, typeString); + + bool success = false; + vtkm::ListForEach( + internal::UncertainCellSetDeserializeFunctor{}, CellSetList{}, obj, typeString, success, bb); + + if (!success) + { + throw vtkm::cont::ErrorBadType( + "Error deserializing Unknown/UncertainCellSet. Message TypeString: " + typeString); + } + } +}; + +} // namespace mangled_diy_namespace + +/// @endcond SERIALIZATION + +#endif //vtk_m_cont_UncertainCellSet_h diff --git a/vtkm/cont/UnknownArrayHandle.h b/vtkm/cont/UnknownArrayHandle.h index b68d67445..4b3bd1a0c 100644 --- a/vtkm/cont/UnknownArrayHandle.h +++ b/vtkm/cont/UnknownArrayHandle.h @@ -600,7 +600,7 @@ public: ///@{ /// Returns this array cast appropriately and stored in the given `ArrayHandle` type. /// Throws an `ErrorBadType` if the stored array cannot be stored in the given array type. - /// Use the `IsType` method to determine if the array can be returned with the given type. + /// Use the `CanConvert` method to determine if the array can be returned with the given type. /// template VTKM_CONT void AsArrayHandle(vtkm::cont::ArrayHandle& array) const diff --git a/vtkm/cont/UnknownCellSet.cxx b/vtkm/cont/UnknownCellSet.cxx new file mode 100644 index 000000000..4a2c70928 --- /dev/null +++ b/vtkm/cont/UnknownCellSet.cxx @@ -0,0 +1,114 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// 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. +//============================================================================ + +#include + +#include + +#include + +namespace +{ + +// Could potentially precompile more cell sets to serialze if that is useful. +using UnknownSerializationCellSets = VTKM_DEFAULT_CELL_SET_LIST; + +} + +namespace vtkm +{ +namespace cont +{ + +vtkm::cont::UnknownCellSet UnknownCellSet::NewInstance() const +{ + UnknownCellSet newCellSet; + if (this->Container) + { + newCellSet.Container = this->Container->NewInstance(); + } + return newCellSet; +} + +std::string UnknownCellSet::GetCellSetName() const +{ + if (this->Container) + { + return vtkm::cont::TypeToString(typeid(this->Container.get())); + } + else + { + return ""; + } +} + +void UnknownCellSet::PrintSummary(std::ostream& os) const +{ + if (this->Container) + { + this->Container->PrintSummary(os); + } + else + { + os << " UnknownCellSet = nullptr\n"; + } +} + +namespace internal +{ + +void ThrowCastAndCallException(const vtkm::cont::UnknownCellSet& ref, const std::type_info& type) +{ + std::ostringstream out; + out << "Could not find appropriate cast for array in CastAndCall.\n" + "CellSet: "; + ref.PrintSummary(out); + out << "TypeList: " << vtkm::cont::TypeToString(type) << "\n"; + throw vtkm::cont::ErrorBadType(out.str()); +} + +} // namespace internal + +} // namespace vtkm::cont +} // namespace vtkm + +//============================================================================= +// Specializations of serialization related classes + +namespace vtkm +{ +namespace cont +{ + +std::string SerializableTypeString::Get() +{ + return "UnknownCS"; +} +} +} // namespace vtkm::cont + +namespace mangled_diy_namespace +{ + +void Serialization::save(BinaryBuffer& bb, + const vtkm::cont::UnknownCellSet& obj) +{ + vtkmdiy::save(bb, obj.ResetCellSetList()); +} + +void Serialization::load(BinaryBuffer& bb, + vtkm::cont::UnknownCellSet& obj) +{ + vtkm::cont::UncertainCellSet uncertainCellSet; + vtkmdiy::load(bb, uncertainCellSet); + obj = uncertainCellSet; +} + +} // namespace mangled_diy_namespace diff --git a/vtkm/cont/UnknownCellSet.h b/vtkm/cont/UnknownCellSet.h new file mode 100644 index 000000000..850eec4f6 --- /dev/null +++ b/vtkm/cont/UnknownCellSet.h @@ -0,0 +1,301 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// 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_cont_UnknownCellSet_h +#define vtk_m_cont_UnknownCellSet_h + +#include +#include +#include + +#include + +#include + +namespace vtkm +{ +namespace cont +{ + +// Forward declaration. Include UncertainCellSet.h if using this. +template +class UncertainCellSet; + +/// \brief A CellSet of an unknown type. +/// +/// `UnknownCellSet` holds a `CellSet` object using runtime polymorphism to manage +/// the dynamic type rather than compile-time templates. This adds a programming +/// convenience that helps avoid a proliferation of templates. +/// +/// To interface between the runtime polymorphism and the templated algorithms +/// in VTK-m, `UnknownCellSet` contains a method named `CastAndCallForTypes` that +/// determines the correct type from some known list of types. This mechanism is +/// used internally by VTK-m's worklet invocation mechanism to determine the type +/// when running algorithms. +/// +/// If the `UnknownCellSet` is used in a context where the possible cell set types +/// can be whittled down to a finite list, you can specify lists of cell set types +/// using the `ResetCellSetList` method. This will convert this object to an +/// `UncertainCellSet` of the given types. In cases where a finite set of types +/// are needed but there is no subset, `VTKM_DEFAULT_CELL_SET_LIST` +/// +class VTKM_CONT_EXPORT UnknownCellSet +{ + std::shared_ptr Container; + +public: + VTKM_CONT UnknownCellSet() = default; + UnknownCellSet(const UnknownCellSet&) = default; + + template + VTKM_CONT UnknownCellSet(const CellSetType& cellSet) + { + VTKM_IS_CELL_SET(CellSetType); + this->Container = std::shared_ptr(new CellSetType(cellSet)); + } + + /// \brief Returns whether a cell set is stored in this `UnknownCellSet`. + /// + /// If the `UnknownCellSet` is constructed without a `CellSet`, it will not + /// have an underlying type, and therefore the operations will be invalid. + /// + VTKM_CONT bool IsValid() const { return static_cast(this->Container); } + + /// \brief Returns a pointer to the `CellSet` base class. + /// + VTKM_CONT vtkm::cont::CellSet* GetCellSetBase() { return this->Container.get(); } + VTKM_CONT const vtkm::cont::CellSet* GetCellSetBase() const { return this->Container.get(); } + + /// \brief Create a new cell set of the same type as this cell set. + /// + /// This method creates a new cell set that is the same type as this one + /// and returns a new `UnknownCellSet` for it. This method is convenient + /// when creating output cell sets that should be the same type as the + /// input cell set. + /// + VTKM_CONT UnknownCellSet NewInstance() const; + + /// \brief Returns the name of the cell set type stored in the array. + /// + /// Returns an empty string if no cell set is stored. + /// + VTKM_CONT std::string GetCellSetName() const; + + /// \brief Returns true if this cell set matches the `CellSetType` template argument. + /// + template + VTKM_CONT bool IsType() const + { + return (dynamic_cast(this->Container.get()) != nullptr); + } + + VTKM_CONT vtkm::Id GetNumberOfCells() const + { + return this->Container ? this->Container->GetNumberOfCells() : 0; + } + VTKM_CONT vtkm::Id GetNumberOfFaces() const + { + return this->Container ? this->Container->GetNumberOfFaces() : 0; + } + VTKM_CONT vtkm::Id GetNumberOfEdges() const + { + return this->Container ? this->Container->GetNumberOfEdges() : 0; + } + VTKM_CONT vtkm::Id GetNumberOfPoints() const + { + return this->Container ? this->Container->GetNumberOfPoints() : 0; + } + + VTKM_CONT vtkm::UInt8 GetCellShape(vtkm::Id id) const + { + return this->GetCellSetBase()->GetCellShape(id); + } + VTKM_CONT vtkm::IdComponent GetNumberOfPointsInCell(vtkm::Id id) const + { + return this->GetCellSetBase()->GetNumberOfPointsInCell(id); + } + VTKM_CONT void GetCellPointIds(vtkm::Id id, vtkm::Id* ptids) const + { + return this->GetCellSetBase()->GetCellPointIds(id, ptids); + } + + VTKM_CONT void DeepCopyFrom(const CellSet* src) { this->GetCellSetBase()->DeepCopy(src); } + + VTKM_CONT void PrintSummary(std::ostream& os) const; + + VTKM_CONT void ReleaseResourcesExecution() + { + if (this->Container) + { + this->Container->ReleaseResourcesExecution(); + } + } + + /// \brief Returns true if this cell set can be retrieved as the given type. + /// + /// This method will return true if calling `AsCellSet` of the given type will + /// succeed. This result is similar to `IsType`, and if `IsType` returns true, + /// then this will return true. However, this method will also return true for + /// other types where automatic conversions are made. + /// + template + VTKM_CONT bool CanConvert() const + { + // TODO: Currently, these are the same. But in the future we expect to support + // special CellSet types that can convert back and forth such as multiplexed + // cell sets or a cell set that can hold structured grids of any dimension. + return this->IsType(); + } + + ///@{ + /// \brief Get the cell set as a known type. + /// + /// Returns this cell set cast appropriately and stored in the given `CellSet` + /// type. Throws an `ErrorBadType` if the stored cell set cannot be stored in + /// the given cell set type. Use the `CanConvert` method to determine if the + /// cell set can be returned with the given type. + /// + template + VTKM_CONT void AsCellSet(CellSetType& cellSet) const + { + VTKM_IS_CELL_SET(CellSetType); + if (!this->IsType()) + { + VTKM_LOG_CAST_FAIL(*this, decltype(cellSet)); + throwFailedDynamicCast(this->GetCellSetName(), vtkm::cont::TypeToString(cellSet)); + } + + cellSet = *reinterpret_cast(this->Container.get()); + } + + template + VTKM_CONT CellSetType AsCellSet() const + { + CellSetType cellSet; + this->AsCellSet(cellSet); + return cellSet; + } + ///@} + + /// \brief Assigns potential cell set types. + /// + /// Calling this method will return an `UncertainCellSet` with the provided + /// cell set list. The returned object will hold the same `CellSet`, but + /// `CastAndCall`'s on the returned object will be constrained to the given + /// types. + /// + // Defined in UncertainCellSet.h + template + VTKM_CONT vtkm::cont::UncertainCellSet ResetCellSetList(CellSetList) const; + template + VTKM_CONT vtkm::cont::UncertainCellSet ResetCellSetList() const; + + /// \brief Call a functor using the underlying cell set type. + /// + /// `CastAndCallForTypes` attemts to cast the held cell set to a specific type + /// and then calls the given functor with the cast cell set. You must specify + /// the `CellSetList` (in a `vtkm::List`) as a template argument. + /// + /// After the functor argument, you may add any number of arguments that will + /// be passed to the functor after the converted cell set. + /// + template + VTKM_CONT void CastAndCallForTypes(Functor&& functor, Args&&... args) const; +}; + +namespace internal +{ + +VTKM_CONT_EXPORT void ThrowCastAndCallException(const vtkm::cont::UnknownCellSet&, + const std::type_info&); + +template <> +struct DynamicTransformTraits +{ + using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; +}; + +} // namespace internal + +template +VTKM_CONT void UnknownCellSet::CastAndCallForTypes(Functor&& functor, Args&&... args) const +{ + VTKM_IS_LIST(CellSetList); + bool called = false; + vtkm::ListForEach( + [&](auto cellSet) { + if (!called && this->CanConvert()) + { + called = true; + this->AsCellSet(cellSet); + VTKM_LOG_CAST_SUCC(*this, cellSet); + + // If you get a compile error here, it means that you have called CastAndCall for a + // vtkm::cont::UnknownCellSet and the arguments of the functor do not match those + // being passed. This is often because it is calling the functor with a CellSet + // type that was not expected. Either add overloads to the functor to accept all + // possible array types or constrain the types tried for the CastAndCall. + functor(cellSet, args...); + } + }, + CellSetList{}); + + if (!called) + { + VTKM_LOG_CAST_FAIL(*this, CellSetList); + internal::ThrowCastAndCallException(*this, typeid(CellSetList)); + } +} + +/// A specialization of `CastAndCall` for `UnknownCellSet`. +/// Since we have no hints on the types, use `VTKM_DEFAULT_CELL_SET_LIST`. +template +void CastAndCall(const vtkm::cont::UnknownCellSet& cellSet, Functor&& f, Args&&... args) +{ + cellSet.CastAndCallForTypes(std::forward(f), + std::forward(args)...); +} + + +} // namespace vtkm::cont +} // namespace vtkm + +//============================================================================= +// Specializations of serialization related classes +/// @cond SERIALIZATION + +namespace vtkm +{ +namespace cont +{ + +template <> +struct VTKM_CONT_EXPORT SerializableTypeString +{ + static VTKM_CONT std::string Get(); +}; +} +} // namespace vtkm::cont + +namespace mangled_diy_namespace +{ + +template <> +struct VTKM_CONT_EXPORT Serialization +{ +public: + static VTKM_CONT void save(BinaryBuffer& bb, const vtkm::cont::UnknownCellSet& obj); + static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::UnknownCellSet& obj); +}; + +} // namespace mangled_diy_namespace + +/// @endcond SERIALIZATION + +#endif //vtk_m_cont_UnknownCellSet_h diff --git a/vtkm/cont/testing/CMakeLists.txt b/vtkm/cont/testing/CMakeLists.txt index 7c97e0e17..d892cf8fd 100644 --- a/vtkm/cont/testing/CMakeLists.txt +++ b/vtkm/cont/testing/CMakeLists.txt @@ -94,6 +94,7 @@ set(unit_tests UnitTestToken.cxx UnitTestTryExecute.cxx UnitTestUnknownArrayHandle.cxx + UnitTestUnknownCellSet.cxx UnitTestVariantArrayHandle.cxx ) diff --git a/vtkm/cont/testing/UnitTestUnknownCellSet.cxx b/vtkm/cont/testing/UnitTestUnknownCellSet.cxx new file mode 100644 index 000000000..398661e9e --- /dev/null +++ b/vtkm/cont/testing/UnitTestUnknownCellSet.cxx @@ -0,0 +1,175 @@ +//============================================================================ +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// 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. +//============================================================================ + +#include + +#include + +#include + +namespace +{ + +using NonDefaultCellSetList = + vtkm::List, + vtkm::cont::CellSetExplicit::StorageTag>>; + +template +struct CheckFunctor +{ + void operator()(const ExpectedCellType&, bool& called) const { called = true; } + + template + void operator()(const UnexpectedType&, bool& called) const + { + VTKM_TEST_FAIL("CastAndCall functor called with wrong type."); + called = false; + } +}; + +class DummyCellSet : public vtkm::cont::CellSet +{ +}; + +void CheckEmptyUnknownCellSet() +{ + vtkm::cont::UnknownCellSet empty; + + VTKM_TEST_ASSERT(empty.GetNumberOfCells() == 0, "UnknownCellSet should have no cells"); + VTKM_TEST_ASSERT(empty.GetNumberOfFaces() == 0, "UnknownCellSet should have no faces"); + VTKM_TEST_ASSERT(empty.GetNumberOfEdges() == 0, "UnknownCellSet should have no edges"); + VTKM_TEST_ASSERT(empty.GetNumberOfPoints() == 0, "UnknownCellSet should have no points"); + + empty.PrintSummary(std::cout); + + using CellSet2D = vtkm::cont::CellSetStructured<2>; + using CellSet3D = vtkm::cont::CellSetStructured<3>; + VTKM_TEST_ASSERT(!empty.IsType(), "UnknownCellSet reports wrong type."); + VTKM_TEST_ASSERT(!empty.IsType(), "UnknownCellSet reports wrong type."); + VTKM_TEST_ASSERT(!empty.IsType(), "UnknownCellSet reports wrong type."); + + VTKM_TEST_ASSERT(!empty.CanConvert(), "UnknownCellSet reports wrong type."); + VTKM_TEST_ASSERT(!empty.CanConvert(), "UnknownCellSet reports wrong type."); + VTKM_TEST_ASSERT(!empty.CanConvert(), "UnknownCellSet reports wrong type."); + + bool gotException = false; + try + { + CellSet2D instance = empty.AsCellSet(); + } + catch (vtkm::cont::ErrorBadType&) + { + gotException = true; + } + VTKM_TEST_ASSERT(gotException, "Empty UnknownCellSet should have thrown on casting"); + + auto empty2 = empty.NewInstance(); + VTKM_TEST_ASSERT(empty.GetCellSetBase() == nullptr, "UnknownCellSet should contain a nullptr"); + VTKM_TEST_ASSERT(empty2.GetCellSetBase() == nullptr, "UnknownCellSet should contain a nullptr"); +} + +template +void CheckUnknownCellSet(vtkm::cont::UnknownCellSet unknownCellSet) +{ + VTKM_TEST_ASSERT(unknownCellSet.CanConvert()); + VTKM_TEST_ASSERT(!unknownCellSet.CanConvert()); + + unknownCellSet.AsCellSet(); + + bool called = false; + unknownCellSet.CastAndCallForTypes(CheckFunctor(), called); + VTKM_TEST_ASSERT( + called, "The functor was never called (and apparently a bad value exception not thrown)."); + + if (vtkm::ListHas::value) + { + called = false; + CastAndCall(unknownCellSet, CheckFunctor(), called); + VTKM_TEST_ASSERT( + called, "The functor was never called (and apparently a bad value exception not thrown)."); + } + + vtkm::cont::UncertainCellSet uncertainCellSet(unknownCellSet); + + called = false; + uncertainCellSet.CastAndCall(CheckFunctor(), called); + VTKM_TEST_ASSERT( + called, "The functor was never called (and apparently a bad value exception not thrown)."); + + called = false; + CastAndCall(uncertainCellSet, CheckFunctor(), called); + VTKM_TEST_ASSERT( + called, "The functor was never called (and apparently a bad value exception not thrown)."); +} + +template +void TryNewInstance(vtkm::cont::UnknownCellSet& originalCellSet) +{ + vtkm::cont::UnknownCellSet newCellSet = originalCellSet.NewInstance(); + + VTKM_TEST_ASSERT(newCellSet.IsType(), "New cell set wrong type."); + + VTKM_TEST_ASSERT(originalCellSet.GetCellSetBase() != newCellSet.GetCellSetBase(), + "NewInstance did not make a copy."); +} + +template +void TryCellSet(vtkm::cont::UnknownCellSet& unknownCellSet) +{ + CheckUnknownCellSet(unknownCellSet); + + CheckUnknownCellSet>(unknownCellSet); + + TryNewInstance(unknownCellSet); +} + +template +void TryDefaultCellSet(CellSetType cellSet) +{ + vtkm::cont::UnknownCellSet unknownCellSet(cellSet); + + TryCellSet(unknownCellSet); +} + +template +void TryNonDefaultCellSet(CellSetType cellSet) +{ + vtkm::cont::UnknownCellSet unknownCellSet(cellSet); + + TryCellSet(unknownCellSet); +} + +void TestDynamicCellSet() +{ + std::cout << "Try default types with default type lists." << std::endl; + std::cout << "*** 2D Structured Grid ******************" << std::endl; + TryDefaultCellSet(vtkm::cont::CellSetStructured<2>()); + std::cout << "*** 3D Structured Grid ******************" << std::endl; + TryDefaultCellSet(vtkm::cont::CellSetStructured<3>()); + std::cout << "*** Explicit Grid ***********************" << std::endl; + TryDefaultCellSet(vtkm::cont::CellSetExplicit<>()); + + std::cout << std::endl << "Try non-default types." << std::endl; + std::cout << "*** 1D Structured Grid ******************" << std::endl; + TryNonDefaultCellSet(vtkm::cont::CellSetStructured<1>()); + std::cout << "*** Explicit Grid Constant Shape ********" << std::endl; + TryNonDefaultCellSet( + vtkm::cont::CellSetExplicit::StorageTag>()); + + std::cout << std::endl << "Try empty DynamicCellSet." << std::endl; + CheckEmptyUnknownCellSet(); +} + +} // anonymous namespace + +int UnitTestUnknownCellSet(int argc, char* argv[]) +{ + return vtkm::cont::testing::Testing::Run(TestDynamicCellSet, argc, argv); +} -- GitLab From 6da5aa4564027c0a2af9ce65cfee09fad42f6b6f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 14 Dec 2021 10:40:58 -0700 Subject: [PATCH 2/5] Replace DynamicCellSet implementation with UnknownCellSet Soon, the `DynamicCellSet` interface will be deprecated so that code can move to `UnknownCellSet`. --- vtkm/cont/DynamicCellSet.h | 247 +----------------- vtkm/cont/UncertainCellSet.h | 2 +- vtkm/cont/UnknownCellSet.h | 94 ++++++- .../testing/UnitTestExternalFacesFilter.cxx | 2 +- .../testing/UnitTestSplitSharpEdgesFilter.cxx | 2 +- 5 files changed, 103 insertions(+), 244 deletions(-) diff --git a/vtkm/cont/DynamicCellSet.h b/vtkm/cont/DynamicCellSet.h index a672bcf19..e5906b005 100644 --- a/vtkm/cont/DynamicCellSet.h +++ b/vtkm/cont/DynamicCellSet.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace vtkm { @@ -52,248 +53,30 @@ namespace cont /// with the default cell set list. /// template -class VTKM_ALWAYS_EXPORT DynamicCellSetBase +class VTKM_ALWAYS_EXPORT DynamicCellSetBase : public vtkm::cont::UncertainCellSet { - VTKM_IS_LIST(CellSetList); + using Superclass = vtkm::cont::UncertainCellSet; public: - VTKM_CONT - DynamicCellSetBase() = default; + using Superclass::Superclass; - template - VTKM_CONT DynamicCellSetBase(const CellSetType& cellSet) - : CellSet(std::make_shared(cellSet)) - { - VTKM_IS_CELL_SET(CellSetType); - } - - template - VTKM_CONT explicit DynamicCellSetBase(const DynamicCellSetBase& src) - : CellSet(src.CellSet) - { - } - - VTKM_CONT explicit DynamicCellSetBase(const std::shared_ptr& cs) - : CellSet(cs) - { - } - - /// Returns true if this cell set is of the provided type. - /// - template - VTKM_CONT bool IsType() const - { - return (dynamic_cast(this->CellSet.get()) != nullptr); - } - - /// Returns true if this cell set is the same (or equivalent) type as the - /// object provided. - /// - template - VTKM_CONT bool IsSameType(const CellSetType&) const - { - return this->IsType(); - } - - /// Returns this cell set cast to the given \c CellSet type. Throws \c - /// ErrorBadType if the cast does not work. Use \c IsType to check if - /// the cast can happen. - /// - template - VTKM_CONT CellSetType& Cast() const + VTKM_CONT DynamicCellSetBase NewInstance() const { - auto cellSetPointer = dynamic_cast(this->CellSet.get()); - if (cellSetPointer == nullptr) - { - VTKM_LOG_CAST_FAIL(*this, CellSetType); - throw vtkm::cont::ErrorBadType("Bad cast of dynamic cell set."); - } - VTKM_LOG_CAST_SUCC(*this, *cellSetPointer); - return *cellSetPointer; + return DynamicCellSetBase(this->Superclass::NewInstance()); } - /// Given a reference to a concrete \c CellSet object, attempt to downcast - /// the contain cell set to the provided type and copy into the given \c - /// CellSet object. Throws \c ErrorBadType if the cast does not work. - /// Use \c IsType to check if the cast can happen. - /// - /// Note that this is a shallow copy. Any data in associated arrays are not - /// copied. - /// - template - VTKM_CONT void CopyTo(CellSetType& cellSet) const - { - cellSet = this->Cast(); - } - - /// Changes the cell set types to try casting to when resolving this dynamic - /// cell set, which is specified with a list tag like those in - /// CellSetList.h. Since C++ does not allow you to actually change the - /// template arguments, this method returns a new dynamic cell setobject. - /// This method is particularly useful to narrow down (or expand) the types - /// when using a cell set of particular constraints. - /// template - VTKM_CONT DynamicCellSetBase ResetCellSetList( - NewCellSetList = NewCellSetList()) const - { - VTKM_IS_LIST(NewCellSetList); - return DynamicCellSetBase(*this); - } - - /// Attempts to cast the held cell set to a specific concrete type, then call - /// the given functor with the cast cell set. The cell sets tried in the cast - /// are those in the \c CellSetList template argument of the \c - /// DynamicCellSetBase class (or \c VTKM_DEFAULT_CELL_SET_LIST for \c - /// DynamicCellSet). You can use \c ResetCellSetList to get different - /// behavior from \c CastAndCall. - /// - template - VTKM_CONT void CastAndCall(Functor&& f, Args&&...) const; - - /// \brief Create a new cell set of the same type as this cell set. - /// - /// This method creates a new cell set that is the same type as this one and - /// returns a new dynamic cell set for it. This method is convenient when - /// creating output data sets that should be the same type as some input cell - /// set. - /// - VTKM_CONT - DynamicCellSetBase NewInstance() const - { - DynamicCellSetBase newCellSet; - if (this->CellSet) - { - newCellSet.CellSet = this->CellSet->NewInstance(); - } - return newCellSet; - } - - VTKM_CONT - vtkm::cont::CellSet* GetCellSetBase() { return this->CellSet.get(); } - - VTKM_CONT - const vtkm::cont::CellSet* GetCellSetBase() const { return this->CellSet.get(); } - - VTKM_CONT - vtkm::Id GetNumberOfCells() const + VTKM_CONT vtkm::cont::DynamicCellSetBase ResetCellSetList(NewCellSetList) const { - return this->CellSet ? this->CellSet->GetNumberOfCells() : 0; + return vtkm::cont::DynamicCellSetBase(*this); } - - VTKM_CONT - vtkm::Id GetNumberOfFaces() const - { - return this->CellSet ? this->CellSet->GetNumberOfFaces() : 0; - } - - VTKM_CONT - vtkm::Id GetNumberOfEdges() const - { - return this->CellSet ? this->CellSet->GetNumberOfEdges() : 0; - } - - VTKM_CONT - vtkm::Id GetNumberOfPoints() const - { - return this->CellSet ? this->CellSet->GetNumberOfPoints() : 0; - } - - VTKM_CONT - void ReleaseResourcesExecution() - { - if (this->CellSet) - { - this->CellSet->ReleaseResourcesExecution(); - } - } - - VTKM_CONT - void PrintSummary(std::ostream& stream) const - { - if (this->CellSet) - { - this->CellSet->PrintSummary(stream); - } - else - { - stream << " DynamicCellSet = nullptr" << std::endl; - } - } - -private: - std::shared_ptr CellSet; - - template - friend class DynamicCellSetBase; -}; - -//============================================================================= -// Free function casting helpers - -/// Returns true if \c dynamicCellSet matches the type of CellSetType. -/// -template -VTKM_CONT inline bool IsType(const vtkm::cont::DynamicCellSetBase& dynamicCellSet) -{ - return dynamicCellSet.template IsType(); -} - -/// Returns \c dynamicCellSet cast to the given \c CellSet type. Throws \c -/// ErrorBadType if the cast does not work. Use \c IsType -/// to check if the cast can happen. -/// -template -VTKM_CONT inline CellSetType Cast(const vtkm::cont::DynamicCellSetBase& dynamicCellSet) -{ - return dynamicCellSet.template Cast(); -} - -namespace detail -{ - -struct DynamicCellSetTry -{ - DynamicCellSetTry(const vtkm::cont::CellSet* const cellSetBase) - : CellSetBase(cellSetBase) - { - } - - template - void operator()(CellSetType, Functor&& f, bool& called, Args&&... args) const + template + VTKM_CONT vtkm::cont::DynamicCellSetBase ResetCellSetList() const { - if (!called) - { - auto* cellset = dynamic_cast(this->CellSetBase); - if (cellset) - { - VTKM_LOG_CAST_SUCC(*this->CellSetBase, *cellset); - f(*cellset, std::forward(args)...); - called = true; - } - } + return vtkm::cont::DynamicCellSetBase(*this); } - - const vtkm::cont::CellSet* const CellSetBase; }; -} // namespace detail - -template -template -VTKM_CONT void DynamicCellSetBase::CastAndCall(Functor&& f, Args&&... args) const -{ - bool called = false; - detail::DynamicCellSetTry tryCellSet(this->CellSet.get()); - vtkm::ListForEach( - tryCellSet, CellSetList{}, std::forward(f), called, std::forward(args)...); - if (!called) - { - VTKM_LOG_CAST_FAIL(*this, CellSetList); - throw vtkm::cont::ErrorBadValue("Could not find appropriate cast for cell set."); - } -} - using DynamicCellSet = DynamicCellSetBase; namespace internal @@ -317,13 +100,7 @@ namespace internal template struct DynamicCellSetCheck { - using type = std::false_type; -}; - -template -struct DynamicCellSetCheck> -{ - using type = std::true_type; + using type = vtkm::cont::internal::UnknownCellSetCheck; }; #define VTKM_IS_DYNAMIC_CELL_SET(T) \ diff --git a/vtkm/cont/UncertainCellSet.h b/vtkm/cont/UncertainCellSet.h index 3ab9f02a7..af58b3230 100644 --- a/vtkm/cont/UncertainCellSet.h +++ b/vtkm/cont/UncertainCellSet.h @@ -49,7 +49,7 @@ public: VTKM_CONT UncertainCellSet() = default; template - explicit VTKM_CONT UncertainCellSet(const CellSetType& cellSet) + VTKM_CONT UncertainCellSet(const CellSetType& cellSet) : Superclass(cellSet) { } diff --git a/vtkm/cont/UnknownCellSet.h b/vtkm/cont/UnknownCellSet.h index 850eec4f6..05336cc82 100644 --- a/vtkm/cont/UnknownCellSet.h +++ b/vtkm/cont/UnknownCellSet.h @@ -49,6 +49,20 @@ class VTKM_CONT_EXPORT UnknownCellSet { std::shared_ptr Container; + void InitializeKnownOrUnknownCellSet(const UnknownCellSet& cellSet, + std::true_type vtkmNotUsed(isUnknownCellSet)) + { + *this = cellSet; + } + + template + void InitializeKnownOrUnknownCellSet(const CellSetType& cellSet, + std::false_type vtkmNotUsed(isUnknownCellSet)) + { + VTKM_IS_CELL_SET(CellSetType); + this->Container = std::shared_ptr(new CellSetType(cellSet)); + } + public: VTKM_CONT UnknownCellSet() = default; UnknownCellSet(const UnknownCellSet&) = default; @@ -56,8 +70,8 @@ public: template VTKM_CONT UnknownCellSet(const CellSetType& cellSet) { - VTKM_IS_CELL_SET(CellSetType); - this->Container = std::shared_ptr(new CellSetType(cellSet)); + this->InitializeKnownOrUnknownCellSet( + cellSet, typename std::is_base_of::type{}); } /// \brief Returns whether a cell set is stored in this `UnknownCellSet`. @@ -165,13 +179,14 @@ public: VTKM_CONT void AsCellSet(CellSetType& cellSet) const { VTKM_IS_CELL_SET(CellSetType); - if (!this->IsType()) + CellSetType* cellSetPointer = dynamic_cast(this->Container.get()); + if (cellSetPointer == nullptr) { - VTKM_LOG_CAST_FAIL(*this, decltype(cellSet)); + VTKM_LOG_CAST_FAIL(*this, CellSetType); throwFailedDynamicCast(this->GetCellSetName(), vtkm::cont::TypeToString(cellSet)); } - - cellSet = *reinterpret_cast(this->Container.get()); + VTKM_LOG_CAST_SUCC(*this, *cellSetPointer); + cellSet = *cellSetPointer; } template @@ -207,8 +222,58 @@ public: /// template VTKM_CONT void CastAndCallForTypes(Functor&& functor, Args&&... args) const; + + // Support for (soon to be) deprecated DynamicCellSet + // TODO: Deprecate these methods + + template + VTKM_CONT bool IsSameType(const CellSetType&) const + { + return this->IsType(); + } + + template + VTKM_CONT CellSetType Cast() const + { + return this->AsCellSet(); + } + + template + VTKM_CONT void CopyTo(CellSetType& cellSet) const + { + return this->AsCellSet(cellSet); + } + + // template + // VTKM_CONT void CastAndCall(Functor&& f, Args&&... args) const + // { + // this->CastAndCallForTypes( + // std::forward(f), std::forward(args)...); + // } }; +//============================================================================= +// Free function casting helpers +// (Not sure if these should be deprecated.) + +/// Returns true if `unknownCellSet` matches the type of `CellSetType`. +/// +template +VTKM_CONT inline bool IsType(const vtkm::cont::UnknownCellSet& unknownCellSet) +{ + return unknownCellSet.IsType(); +} + +/// Returns `unknownCellSet` cast to the given `CellSet` type. Throws +/// `ErrorBadType` if the cast does not work. Use `IsType` +/// to check if the cast can happen. +/// +template +VTKM_CONT inline CellSetType Cast(const vtkm::cont::UnknownCellSet& unknownCellSet) +{ + return unknownCellSet.Cast(); +} + namespace internal { @@ -262,6 +327,23 @@ void CastAndCall(const vtkm::cont::UnknownCellSet& cellSet, Functor&& f, Args&&. std::forward(args)...); } +namespace internal +{ + +/// Checks to see if the given object is an unknown (or uncertain) cell set. It +/// resolves to either `std::true_type` or `std::false_type`. +/// +template +using UnknownCellSetCheck = typename std::is_base_of::type; + +#define VTKM_IS_UNKNOWN_CELL_SET(T) \ + VTKM_STATIC_ASSERT(::vtkm::cont::internal::UnknownCellSetCheck::value) + +#define VTKM_IS_KNOWN_OR_UNKNOWN_CELL_SET(T) \ + VTKM_STATIC_ASSERT(::vtkm::cont::internal::CellSetCheck::type::value || \ + ::vtkm::cont::internal::UnknownCellSetCheck::value) + +} // namespace internal } // namespace vtkm::cont } // namespace vtkm diff --git a/vtkm/filter/testing/UnitTestExternalFacesFilter.cxx b/vtkm/filter/testing/UnitTestExternalFacesFilter.cxx index 3ec3ce773..7fbebb545 100644 --- a/vtkm/filter/testing/UnitTestExternalFacesFilter.cxx +++ b/vtkm/filter/testing/UnitTestExternalFacesFilter.cxx @@ -63,7 +63,7 @@ void TestExternalFacesExplicitGrid(const vtkm::cont::DataSet& ds, vtkm::cont::DataSet resultds = externalFaces.Execute(ds); // verify cellset - vtkm::cont::CellSetExplicit<>& new_cellSet = + vtkm::cont::CellSetExplicit<> new_cellSet = resultds.GetCellSet().Cast>(); const vtkm::Id numOutputExtFaces = new_cellSet.GetNumberOfCells(); VTKM_TEST_ASSERT(numOutputExtFaces == numExpectedExtFaces, "Number of External Faces mismatch"); diff --git a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx index d7cdd2c78..32d81032b 100644 --- a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx +++ b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx @@ -165,7 +165,7 @@ void TestSplitSharpEdgesFilterNoSplit(vtkm::cont::DataSet& simpleCubeWithSN, vtkm::cont::DataSet result = splitSharpEdgesFilter.Execute(simpleCubeWithSN); auto newCoords = result.GetCoordinateSystem().GetDataAsMultiplexer(); - vtkm::cont::CellSetExplicit<>& newCellset = + vtkm::cont::CellSetExplicit<> newCellset = result.GetCellSet().Cast>(); auto newCoordsP = newCoords.ReadPortal(); vtkm::cont::ArrayHandle newPointvarField; -- GitLab From 4cb392ca24bef6fe3ed72e6c7274044b330b2bc9 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Tue, 14 Dec 2021 13:15:20 -0700 Subject: [PATCH 3/5] Make DynamicCellSet directly an UnknownCellSet Before it was a DynamicCellSetBase. This change causes some calls to templated DynamicCellSetBase arguments to fail to resolve, but there were only 4 in the code base. In exchange, DynamicCellSet requires a lot less characters in its symbol. --- vtkm/cont/CellLocatorChooser.h | 11 +++--- vtkm/cont/DynamicCellSet.h | 39 +++++++++++++++++++- vtkm/cont/UnknownCellSet.h | 12 +++--- vtkm/cont/testing/UnitTestDynamicCellSet.cxx | 10 ++++- vtkm/filter/Contour.hxx | 3 +- vtkm/worklet/Clip.h | 17 ++++----- 6 files changed, 66 insertions(+), 26 deletions(-) diff --git a/vtkm/cont/CellLocatorChooser.h b/vtkm/cont/CellLocatorChooser.h index 91759b800..51ee2aca2 100644 --- a/vtkm/cont/CellLocatorChooser.h +++ b/vtkm/cont/CellLocatorChooser.h @@ -126,12 +126,11 @@ struct CastAndCallCellLocatorChooserFunctor /// /// Any additional args are passed to the functor. /// -template -VTKM_CONT void CastAndCallCellLocatorChooser( - const vtkm::cont::DynamicCellSetBase& cellSet, - const vtkm::cont::CoordinateSystem& coordinateSystem, - Functor&& functor, - Args&&... args) +template +VTKM_CONT void CastAndCallCellLocatorChooser(const CellSetType& cellSet, + const vtkm::cont::CoordinateSystem& coordinateSystem, + Functor&& functor, + Args&&... args) { vtkm::cont::CastAndCall(cellSet, detail::CastAndCallCellLocatorChooserFunctor{}, diff --git a/vtkm/cont/DynamicCellSet.h b/vtkm/cont/DynamicCellSet.h index e5906b005..1dba9f03d 100644 --- a/vtkm/cont/DynamicCellSet.h +++ b/vtkm/cont/DynamicCellSet.h @@ -77,7 +77,38 @@ public: } }; -using DynamicCellSet = DynamicCellSetBase; +struct VTKM_ALWAYS_EXPORT DynamicCellSet : public vtkm::cont::UnknownCellSet +{ + using UnknownCellSet::UnknownCellSet; + + DynamicCellSet() = default; + + DynamicCellSet(const vtkm::cont::UnknownCellSet& src) + : UnknownCellSet(src) + { + } + + operator vtkm::cont::DynamicCellSetBase() const + { + return vtkm::cont::DynamicCellSetBase{ *this }; + } + + VTKM_CONT vtkm::cont::DynamicCellSet NewInstance() const + { + return vtkm::cont::DynamicCellSet(this->UnknownCellSet::NewInstance()); + } + + template + VTKM_CONT vtkm::cont::DynamicCellSetBase ResetCellSetList(NewCellSetList) const + { + return vtkm::cont::DynamicCellSetBase(*this); + } + template + VTKM_CONT vtkm::cont::DynamicCellSetBase ResetCellSetList() const + { + return vtkm::cont::DynamicCellSetBase(*this); + } +}; namespace internal { @@ -88,6 +119,12 @@ struct DynamicTransformTraits> using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; }; +template <> +struct DynamicTransformTraits +{ + using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; +}; + } // namespace internal namespace internal diff --git a/vtkm/cont/UnknownCellSet.h b/vtkm/cont/UnknownCellSet.h index 05336cc82..02007299a 100644 --- a/vtkm/cont/UnknownCellSet.h +++ b/vtkm/cont/UnknownCellSet.h @@ -244,12 +244,12 @@ public: return this->AsCellSet(cellSet); } - // template - // VTKM_CONT void CastAndCall(Functor&& f, Args&&... args) const - // { - // this->CastAndCallForTypes( - // std::forward(f), std::forward(args)...); - // } + template + VTKM_CONT void CastAndCall(Functor&& f, Args&&... args) const + { + this->CastAndCallForTypes(std::forward(f), + std::forward(args)...); + } }; //============================================================================= diff --git a/vtkm/cont/testing/UnitTestDynamicCellSet.cxx b/vtkm/cont/testing/UnitTestDynamicCellSet.cxx index 74f1320ec..8371c6029 100644 --- a/vtkm/cont/testing/UnitTestDynamicCellSet.cxx +++ b/vtkm/cont/testing/UnitTestDynamicCellSet.cxx @@ -100,7 +100,7 @@ void CheckDynamicCellSet(const CellSetType& cellSet, } template -void TryNewInstance(CellSetType, vtkm::cont::DynamicCellSetBase& originalCellSet) +void TryNewInstance(CellSetType, vtkm::cont::DynamicCellSetBase originalCellSet) { vtkm::cont::DynamicCellSetBase newCellSet = originalCellSet.NewInstance(); @@ -111,7 +111,7 @@ void TryNewInstance(CellSetType, vtkm::cont::DynamicCellSetBase& or } template -void TryCellSet(CellSetType cellSet, vtkm::cont::DynamicCellSetBase& dynamicCellSet) +void TryCellSet(CellSetType cellSet, vtkm::cont::DynamicCellSetBase dynamicCellSet) { CheckDynamicCellSet(cellSet, dynamicCellSet); @@ -120,6 +120,12 @@ void TryCellSet(CellSetType cellSet, vtkm::cont::DynamicCellSetBase TryNewInstance(cellSet, dynamicCellSet); } +template +void TryCellSet(CellSetType cellSet, vtkm::cont::DynamicCellSet dynamicCellSet) +{ + TryCellSet(cellSet, dynamicCellSet.ResetCellSetList()); +} + template void TryDefaultCellSet(CellSetType cellSet) { diff --git a/vtkm/filter/Contour.hxx b/vtkm/filter/Contour.hxx index b08aa3f22..1f70795b8 100644 --- a/vtkm/filter/Contour.hxx +++ b/vtkm/filter/Contour.hxx @@ -26,8 +26,7 @@ namespace filter namespace { -template -inline bool IsCellSetStructured(const vtkm::cont::DynamicCellSetBase& cellset) +inline bool IsCellSetStructured(const vtkm::cont::UnknownCellSet& cellset) { if (cellset.template IsType>() || cellset.template IsType>() || diff --git a/vtkm/worklet/Clip.h b/vtkm/worklet/Clip.h index ab86f8af4..13f32940f 100644 --- a/vtkm/worklet/Clip.h +++ b/vtkm/worklet/Clip.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -584,8 +583,8 @@ public: { } - template - vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase& cellSet, + template + vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet, const ScalarsArrayHandle& scalars, vtkm::Float64 value, bool invert) @@ -697,13 +696,13 @@ public: return output; } - template + template class ClipWithImplicitFunction { public: VTKM_CONT ClipWithImplicitFunction(Clip* clipper, - const DynamicCellSet& cellSet, + const CellSetType& cellSet, const ImplicitFunction& function, const bool invert, vtkm::cont::CellSetExplicit<>* result) @@ -730,21 +729,21 @@ public: private: Clip* Clipper; - const DynamicCellSet* CellSet; + const CellSetType* CellSet; ImplicitFunction Function; bool Invert; vtkm::cont::CellSetExplicit<>* Result; }; - template - vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase& cellSet, + template + vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet, const ImplicitFunction& clipFunction, const vtkm::cont::CoordinateSystem& coords, const bool invert) { vtkm::cont::CellSetExplicit<> output; - ClipWithImplicitFunction, ImplicitFunction> clip( + ClipWithImplicitFunction clip( this, cellSet, clipFunction, invert, &output); CastAndCall(coords, clip); -- GitLab From 030ac1fff41d19fd16929c0f46cdb0b9a1a80bbd Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 16 Dec 2021 08:20:42 -0700 Subject: [PATCH 4/5] Fix some copy/paste errors with comments and variable names --- vtkm/cont/UncertainCellSet.h | 18 +++++++++--------- vtkm/cont/UnknownCellSet.cxx | 2 +- vtkm/cont/UnknownCellSet.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/vtkm/cont/UncertainCellSet.h b/vtkm/cont/UncertainCellSet.h index af58b3230..ec9f97d95 100644 --- a/vtkm/cont/UncertainCellSet.h +++ b/vtkm/cont/UncertainCellSet.h @@ -69,15 +69,15 @@ public: /// \brief Create a new cell set of the same type as this. /// - /// This method creates a new array that is the same type as this one and + /// This method creates a new cell set that is the same type as this one and /// returns a new `UncertainCellSet` for it. /// VTKM_CONT Thisclass NewInstance() const { return Thisclass(this->Superclass::NewInstance()); } - /// \brief Call a functor using the underlying array type. + /// \brief Call a functor using the underlying cell set type. /// - /// `CastAndCall` attempts to cast the held array to a specific value type, - /// and then calls the given functor with the cast array. + /// `CastAndCall` attempts to cast the held cell set to a specific type, + /// and then calls the given functor with the cast cell set. /// template VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const @@ -87,7 +87,7 @@ public: } }; -// Defined here to avoid circular dependencies between UnknownArrayHandle and UncertainArrayHandle. +// Defined here to avoid circular dependencies between UnknownCellSet and UncertainCellSet. template VTKM_CONT vtkm::cont::UncertainCellSet UnknownCellSet::ResetCellSetList( NewCellSetList) const @@ -154,16 +154,16 @@ struct UncertainCellSetDeserializeFunctor { template void operator()(CellSetType, - vtkm::cont::UnknownCellSet& unknownArray, + vtkm::cont::UnknownCellSet& unknownCellSet, const std::string& typeString, bool& success, BinaryBuffer& bb) const { if (!success && (typeString == vtkm::cont::SerializableTypeString::Get())) { - CellSetType knownArray; - vtkmdiy::load(bb, knownArray); - unknownArray = knownArray; + CellSetType knownCellSet; + vtkmdiy::load(bb, knownCellSet); + unknownCellSet = knownCellSet; success = true; } } diff --git a/vtkm/cont/UnknownCellSet.cxx b/vtkm/cont/UnknownCellSet.cxx index 4a2c70928..c331eb5cc 100644 --- a/vtkm/cont/UnknownCellSet.cxx +++ b/vtkm/cont/UnknownCellSet.cxx @@ -67,7 +67,7 @@ namespace internal void ThrowCastAndCallException(const vtkm::cont::UnknownCellSet& ref, const std::type_info& type) { std::ostringstream out; - out << "Could not find appropriate cast for array in CastAndCall.\n" + out << "Could not find appropriate cast for cell set in CastAndCall.\n" "CellSet: "; ref.PrintSummary(out); out << "TypeList: " << vtkm::cont::TypeToString(type) << "\n"; diff --git a/vtkm/cont/UnknownCellSet.h b/vtkm/cont/UnknownCellSet.h index 02007299a..14414be99 100644 --- a/vtkm/cont/UnknownCellSet.h +++ b/vtkm/cont/UnknownCellSet.h @@ -95,7 +95,7 @@ public: /// VTKM_CONT UnknownCellSet NewInstance() const; - /// \brief Returns the name of the cell set type stored in the array. + /// \brief Returns the name of the cell set type stored in this class. /// /// Returns an empty string if no cell set is stored. /// @@ -305,7 +305,7 @@ VTKM_CONT void UnknownCellSet::CastAndCallForTypes(Functor&& functor, Args&&... // vtkm::cont::UnknownCellSet and the arguments of the functor do not match those // being passed. This is often because it is calling the functor with a CellSet // type that was not expected. Either add overloads to the functor to accept all - // possible array types or constrain the types tried for the CastAndCall. + // possible cell set types or constrain the types tried for the CastAndCall. functor(cellSet, args...); } }, -- GitLab From 1dc3d145a59f289e4a3b2589bc07e89098ad0b80 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 16 Dec 2021 08:48:04 -0700 Subject: [PATCH 5/5] Allow `UnknownCellSet::Cast` return a reference The replacement method, `AsCellSet`, will not support returning a reference. However, we can continue to allow the deprecated method to return the reference and correct that later when we move from the deprecated method. --- vtkm/cont/UnknownCellSet.h | 12 ++++++++++-- .../filter/testing/UnitTestSplitSharpEdgesFilter.cxx | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/vtkm/cont/UnknownCellSet.h b/vtkm/cont/UnknownCellSet.h index 14414be99..46b25e4d2 100644 --- a/vtkm/cont/UnknownCellSet.h +++ b/vtkm/cont/UnknownCellSet.h @@ -233,9 +233,17 @@ public: } template - VTKM_CONT CellSetType Cast() const + VTKM_CONT CellSetType& Cast() const { - return this->AsCellSet(); + VTKM_IS_CELL_SET(CellSetType); + CellSetType* cellSetPointer = dynamic_cast(this->Container.get()); + if (cellSetPointer == nullptr) + { + VTKM_LOG_CAST_FAIL(*this, CellSetType); + throwFailedDynamicCast(this->GetCellSetName(), vtkm::cont::TypeToString()); + } + VTKM_LOG_CAST_SUCC(*this, *cellSetPointer); + return *cellSetPointer; } template diff --git a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx index 32d81032b..d7cdd2c78 100644 --- a/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx +++ b/vtkm/filter/testing/UnitTestSplitSharpEdgesFilter.cxx @@ -165,7 +165,7 @@ void TestSplitSharpEdgesFilterNoSplit(vtkm::cont::DataSet& simpleCubeWithSN, vtkm::cont::DataSet result = splitSharpEdgesFilter.Execute(simpleCubeWithSN); auto newCoords = result.GetCoordinateSystem().GetDataAsMultiplexer(); - vtkm::cont::CellSetExplicit<> newCellset = + vtkm::cont::CellSetExplicit<>& newCellset = result.GetCellSet().Cast>(); auto newCoordsP = newCoords.ReadPortal(); vtkm::cont::ArrayHandle newPointvarField; -- GitLab