#ifndef SUBITEM_VALUE_PER_ITEM_HPP #define SUBITEM_VALUE_PER_ITEM_HPP #include <Kokkos_StaticCrsGraph.hpp> #include <TypeOfItem.hpp> #include <PastisAssert.hpp> #include <ConnectivityMatrix.hpp> #include <IConnectivity.hpp> #include <ConnectivityUtils.hpp> template <typename DataType, TypeOfItem SubItemType, TypeOfItem ItemType> class SubItemValuePerItem { private: ConnectivityMatrix::HostRowType m_host_row_map; Kokkos::View<DataType*> m_values; friend SubItemValuePerItem<std::add_const_t<DataType>, SubItemType, ItemType>; public: class SubView { private: KOKKOS_RESTRICT DataType* const m_sub_values; const size_t m_size; public: KOKKOS_INLINE_FUNCTION const DataType& operator[](const size_t& i) const { Assert(i<m_size); return m_sub_values[i]; } KOKKOS_FORCEINLINE_FUNCTION DataType& operator[](const size_t& i) { Assert(i<m_size); return m_sub_values[i]; } KOKKOS_INLINE_FUNCTION const size_t& size() const { return m_size; } SubView(const SubView&) = delete; KOKKOS_INLINE_FUNCTION SubView(SubView&&) = default; KOKKOS_INLINE_FUNCTION SubView(const Kokkos::View<DataType*>& values, const size_t& begin, const size_t& end) : m_sub_values(&(values[begin])), m_size(end-begin) { Assert(begin<=end); Assert(end<=values.extent(0)); } }; KOKKOS_FORCEINLINE_FUNCTION DataType& operator()(const size_t& j, const size_t& r) { return m_values[m_host_row_map(j)+r]; } // Following Kokkos logic, these classes are view and const view does allow // changes in data KOKKOS_FORCEINLINE_FUNCTION DataType& operator()(const size_t& j, const size_t& r) const { return m_values[m_host_row_map(j)+r]; } KOKKOS_INLINE_FUNCTION size_t numberOfValues() const { return m_values.extent(0); } KOKKOS_FORCEINLINE_FUNCTION DataType& operator[](const size_t& i) { return m_values[i]; } // Following Kokkos logic, these classes are view and const view does allow // changes in data KOKKOS_FORCEINLINE_FUNCTION DataType& operator[](const size_t & i) const { return m_values[i]; } KOKKOS_INLINE_FUNCTION size_t numberOfItems() const { Assert(m_host_row_map.extent(0) != 0); return m_host_row_map.extent(0); } KOKKOS_INLINE_FUNCTION size_t numberOfSubValues(const size_t& i_cell) const { return m_host_row_map(i_cell+1)-m_host_row_map(i_cell); } KOKKOS_INLINE_FUNCTION SubView itemValues(const size_t& i_cell) { const auto& cell_begin = m_host_row_map(i_cell); const auto& cell_end = m_host_row_map(i_cell+1); return SubView(m_values, cell_begin, cell_end); } // Following Kokkos logic, these classes are view and const view does allow // changes in data KOKKOS_INLINE_FUNCTION SubView itemValues(const size_t& i_cell) const { const auto& cell_begin = m_host_row_map(i_cell); const auto& cell_end = m_host_row_map(i_cell+1); return SubView(m_values, cell_begin, cell_end); } template <typename DataType2> KOKKOS_INLINE_FUNCTION SubItemValuePerItem& operator=(const SubItemValuePerItem<DataType2, SubItemType, ItemType>& sub_item_value_per_item) { // ensures that DataType is the same as source DataType2 static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(), "Cannot assign SubItemValuePerItem of different type"); // ensures that const is not lost through copy static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()), "Cannot assign const SubItemValuePerItem to a non const SubItemValuePerItem"); m_host_row_map = sub_item_value_per_item.m_host_row_map; m_values = sub_item_value_per_item.m_values; return *this; } template <typename DataType2> KOKKOS_INLINE_FUNCTION SubItemValuePerItem(const SubItemValuePerItem<DataType2, SubItemType, ItemType>& sub_item_value_per_item) { this->operator=(sub_item_value_per_item); } SubItemValuePerItem() = default; SubItemValuePerItem(const IConnectivity& connectivity) { ConnectivityMatrix connectivity_matrix = connectivity.getMatrix(ItemType,SubItemType); m_host_row_map = connectivity_matrix.rowsMap(); m_values = Kokkos::View<DataType*>("values", connectivity_matrix.numEntries()); } ~SubItemValuePerItem() = default; }; template <typename DataType> using NodeValuePerCell = SubItemValuePerItem<DataType, TypeOfItem::node, TypeOfItem::cell>; template <typename DataType> using NodeValuePerFace = SubItemValuePerItem<DataType, TypeOfItem::node, TypeOfItem::face>; template <typename DataType> using FaceValuePerNode = SubItemValuePerItem<DataType, TypeOfItem::face, TypeOfItem::node>; template <typename DataType> using FaceValuePerCell = SubItemValuePerItem<DataType, TypeOfItem::face, TypeOfItem::cell>; template <typename DataType> using CellValuePerNode = SubItemValuePerItem<DataType, TypeOfItem::cell, TypeOfItem::node>; template <typename DataType> using CellValuePerFace = SubItemValuePerItem<DataType, TypeOfItem::cell, TypeOfItem::face>; #endif // SUBITEM_VALUE_PER_ITEM_HPP