//============================================================================ // 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_Field_h #define vtk_m_cont_Field_h #include #include #include #include #include #include namespace vtkm { namespace cont { /// A \c Field encapsulates an array on some piece of the mesh, such as /// the points, a cell set, a point logical dimension, or the whole mesh. /// class VTKM_CONT_EXPORT Field { public: /// @brief Identifies what elements of a data set a field is associated with. /// /// The `Association` enum is used by `vtkm::cont::Field` to specify on what /// topological elements each item in the field is associated with. enum struct Association { // Documentation is below (for better layout in generated documents). Any, WholeDataSet, Points, Cells, Partitions, Global, }; /// @var Association Any /// @brief Any field regardless of the association. /// /// This is used when choosing a `vtkm::cont::Field` that could be of any /// association. It is often used as the default if no association is given. /// @var Association WholeDataSet /// @brief A "global" field that applies to the entirety of a `vtkm::cont::DataSet`. /// /// Fields of this association often contain summary or annotation information. /// An example of a whole data set field could be the region that the mesh covers. /// @var Association Points /// @brief A field that applies to points. /// /// There is a separate field value attached to each point. Point fields usually represent /// samples of continuous data that can be reinterpolated through cells. Physical properties /// such as temperature, pressure, density, velocity, etc. are usually best represented in /// point fields. Data that deals with the points of the topology, such as displacement /// vectors, are also appropriate for point data. /// @var Association Cells /// @brief A field that applies to cells. /// /// There is a separate field value attached to each cell in a cell set. Cell fields /// usually represent values from an integration over the finite cells of the mesh. /// Integrated values like mass or volume are best represented in cell fields. Statistics /// about each cell like strain or cell quality are also appropriate for cell data. /// @var Association Partitions /// @brief A field that applies to partitions. /// /// This type of field is attached to a `vtkm::cont::PartitionedDataSet`. There is a /// separate field value attached to each partition. Identification or information /// about the arrangement of partitions such as hierarchy levels are usually best /// represented in partition fields. /// @var Association Global /// @brief A field that applies to all partitions. /// /// This type of field is attached to a `vtkm::cont::PartitionedDataSet`. It contains /// values that are "global" across all partitions and data therin. VTKM_CONT Field() = default; VTKM_CONT Field(std::string name, Association association, const vtkm::cont::UnknownArrayHandle& data); template VTKM_CONT Field(std::string name, Association association, const vtkm::cont::ArrayHandle& data) : Field(name, association, vtkm::cont::UnknownArrayHandle{ data }) { } Field(const vtkm::cont::Field& src); Field(vtkm::cont::Field&& src) noexcept; VTKM_CONT virtual ~Field(); VTKM_CONT Field& operator=(const vtkm::cont::Field& src); VTKM_CONT Field& operator=(vtkm::cont::Field&& src) noexcept; VTKM_CONT bool IsCellField() const { return this->FieldAssociation == Association::Cells; } VTKM_CONT bool IsPointField() const { return this->FieldAssociation == Association::Points; } VTKM_CONT bool IsWholeDataSetField() const { return this->FieldAssociation == Association::WholeDataSet; } VTKM_CONT bool IsPartitionsField() const { return this->FieldAssociation == Association::Partitions; } VTKM_CONT bool IsGlobalField() const { return this->FieldAssociation == Association::Global; } /// Returns true if the array of the field has a value type that matches something in /// `VTKM_FIELD_TYPE_LIST` and a storage that matches something in `VTKM_FIELD_STORAGE_LIST`. VTKM_CONT bool IsSupportedType() const; VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Data.GetNumberOfValues(); } VTKM_CONT const std::string& GetName() const { return this->Name; } VTKM_CONT Association GetAssociation() const { return this->FieldAssociation; } const vtkm::cont::UnknownArrayHandle& GetData() const; vtkm::cont::UnknownArrayHandle& GetData(); /// @brief Returns the range of each component in the field array. /// /// The ranges of each component are returned in an `ArrayHandle` containing `vtkm::Range` /// values. /// So, for example, calling `GetRange` on a scalar field will return an `ArrayHandle` /// with exactly 1 entry in it. Calling `GetRange` on a field of 3D vectors will return /// an `ArrayHandle` with exactly 3 entries corresponding to each of the components in /// the range. VTKM_CONT const vtkm::cont::ArrayHandle& GetRange() const; VTKM_CONT void GetRange(vtkm::Range* range) const; /// \brief Get the data as an array with `vtkm::FloatDefault` components. /// /// Returns a `vtkm::cont::UnknownArrayHandle` that contains an array that either contains /// values of type `vtkm::FloatDefault` or contains `Vec`s with components of type /// `vtkm::FloatDefault`. If the array has value types that do not match this type, then /// it will be copied into an array that does. /// /// Additionally, the returned array will have a storage that is compatible with /// something in `VTKM_FIELD_STORAGE_LIST`. If this condition is not met, then the /// array will be copied. /// /// If the array contained in the field already matches the required criteria, the array /// will be returned without copying. /// VTKM_CONT vtkm::cont::UnknownArrayHandle GetDataAsDefaultFloat() const; /// \brief Get the data as an array of an expected type. /// /// Returns a `vtkm::cont::UnknownArrayHandle` that contains an array that (probably) has /// a value type that matches something in `VTKM_FIELD_TYPE_LIST` and a storage that matches /// something in `VTKM_FIELD_STORAGE_LIST`. If the array has a value type and storage that /// match `VTKM_FIELD_TYPE_LIST` and `VTKM_FIELD_STORAGE_LIST` respectively, then the same /// array is returned. If something does not match, then the data are copied to a /// `vtkm::cont::ArrayHandleBasic` with a value type component of `vtkm::FloatDefault`. /// /// Note that the returned array is likely to be compatible with `VTKM_FIELD_TYPE_LIST`, but /// not guaranteed. In particular, if this field contains `Vec`s, the returned array will also /// contain `Vec`s of the same size. For example, if the field contains `vtkm::Vec2i_16` values, /// they will (likely) be converted to `vtkm::Vec2f`. Howver, `vtkm::Vec2f` may still not be /// in `VTKM_FIELD_TYPE_LIST`. /// VTKM_CONT vtkm::cont::UnknownArrayHandle GetDataWithExpectedTypes() const; /// \brief Convert this field to use an array of an expected type. /// /// Copies the internal data, as necessary, to an array that (probably) has a value type /// that matches something in `VTKM_FIELD_TYPE_LIST` and a storage that matches something /// in `VTKM_FIELD_STORAGE_LIST`. If the field already has a value type and storage that /// match `VTKM_FIELD_TYPE_LIST` and `VTKM_FIELD_STORAGE_LIST` respectively, then nothing /// in the field is changed. If something does not match, then the data are copied to a /// `vtkm::cont::ArrayHandleBasic` with a value type component of `vtkm::FloatDefault`. /// /// Note that the returned array is likely to be compatible with `VTKM_FIELD_TYPE_LIST`, but /// not guaranteed. In particular, if this field contains `Vec`s, the returned array will also /// contain `Vec`s of the same size. For example, if the field contains `vtkm::Vec2i_16` values, /// they will (likely) be converted to `vtkm::Vec2f`. Howver, `vtkm::Vec2f` may still not be /// in `VTKM_FIELD_TYPE_LIST`. /// VTKM_CONT void ConvertToExpected(); VTKM_CONT void SetData(const vtkm::cont::UnknownArrayHandle& newdata); template VTKM_CONT void SetData(const vtkm::cont::ArrayHandle& newdata) { this->SetData(vtkm::cont::UnknownArrayHandle(newdata)); } VTKM_CONT virtual void PrintSummary(std::ostream& out) const; VTKM_CONT virtual void ReleaseResourcesExecution() { this->Data.ReleaseResourcesExecution(); this->Range.ReleaseResourcesExecution(); } private: std::string Name; ///< name of field Association FieldAssociation = Association::Any; vtkm::cont::UnknownArrayHandle Data; mutable vtkm::cont::ArrayHandle Range; mutable bool ModifiedFlag = true; }; template void CastAndCall(const vtkm::cont::Field& field, Functor&& f, Args&&... args) { vtkm::cont::CastAndCall(field.GetData(), std::forward(f), std::forward(args)...); } //@{ /// Convenience functions to build fields from C style arrays and std::vector template vtkm::cont::Field make_Field(std::string name, Field::Association association, const T* data, vtkm::Id size, vtkm::CopyFlag copy) { return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandle(data, size, copy)); } template vtkm::cont::Field make_Field(std::string name, Field::Association association, const std::vector& data, vtkm::CopyFlag copy) { return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandle(data, copy)); } template vtkm::cont::Field make_FieldMove(std::string name, Field::Association association, std::vector&& data) { return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandleMove(std::move(data))); } template vtkm::cont::Field make_Field(std::string name, Field::Association association, std::vector&& data, vtkm::CopyFlag vtkmNotUsed(copy)) { return make_FieldMove(name, association, std::move(data)); } template vtkm::cont::Field make_Field(std::string name, Field::Association association, std::initializer_list&& data) { return make_FieldMove(name, association, vtkm::cont::make_ArrayHandle(std::move(data))); } //@} /// Convenience function to build point fields from vtkm::cont::ArrayHandle template vtkm::cont::Field make_FieldPoint(std::string name, const vtkm::cont::ArrayHandle& data) { return vtkm::cont::Field(name, vtkm::cont::Field::Association::Points, data); } /// Convenience function to build point fields from vtkm::cont::UnknownArrayHandle inline vtkm::cont::Field make_FieldPoint(std::string name, const vtkm::cont::UnknownArrayHandle& data) { return vtkm::cont::Field(name, vtkm::cont::Field::Association::Points, data); } /// Convenience function to build cell fields from vtkm::cont::ArrayHandle template vtkm::cont::Field make_FieldCell(std::string name, const vtkm::cont::ArrayHandle& data) { return vtkm::cont::Field(name, vtkm::cont::Field::Association::Cells, data); } /// Convenience function to build cell fields from vtkm::cont::UnknownArrayHandle inline vtkm::cont::Field make_FieldCell(std::string name, const vtkm::cont::UnknownArrayHandle& data) { return vtkm::cont::Field(name, vtkm::cont::Field::Association::Cells, data); } } // namespace cont } // namespace vtkm namespace vtkm { namespace cont { namespace internal { template <> struct DynamicTransformTraits { using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; }; } // namespace internal } // namespace cont } // namespace vtkm //============================================================================= // Specializations of serialization related classes /// @cond SERIALIZATION namespace mangled_diy_namespace { template <> struct VTKM_CONT_EXPORT Serialization { static VTKM_CONT void save(BinaryBuffer& bb, const vtkm::cont::Field& field); static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::Field& field); }; } // diy /// @endcond SERIALIZATION #endif //vtk_m_cont_Field_h