// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MULTI_GRIDVIEW_HH #define DUNE_MULTI_GRIDVIEW_HH #if ! DUNE_HAVE_CXX_VARIANT #error "Require C++17 variant!" #endif #include #include #include #include #include #include #include "mmiterator.hh" #include "multiindexset.hh" namespace Dune { // forward declaration template class MultiGridView; template struct MultiGridViewTraits { using Grid = typename std::remove_const::type; using IndexSet = MultiIndexSet; using Intersection = std::variant< typename HostGrid::Traits::LeafIntersection, typename HostGrid::Traits::LevelIntersection>; using IntersectionIterator = std::variant< typename HostGrid::Traits::LeafIntersectionIterator, typename HostGrid::Traits::LevelIntersectionIterator>; using CollectiveCommunication = typename HostGrid::Traits::CollectiveCommunication; template struct Codim { using Entity = typename Grid::Traits::template Codim::Entity; using Geometry = typename Grid::template Codim::Geometry; using LocalGeometry = typename Grid::template Codim::LocalGeometry; template struct Partition { using Iterator = MultiMeshIterator; }; }; enum { conforming = Capabilities::isLevelwiseConforming::v }; }; template class MultiGridView { public: using Traits = MultiGridViewTraits; /// The MultiMesh GridType using Grid = typename Traits::Grid; using GridViewTypes = std::variant; using IndexSet = typename Traits::IndexSet; using IndexSetTypes = typename IndexSet::IndexSetTypes; using IntersectionIterator = typename Traits::IntersectionIterator; using CollectiveCommunication = typename Traits::CollectiveCommunication; template using IsGridView = Std::disjunction< std::is_same,typename HostGrid::LeafGridView>, std::is_same,typename HostGrid::LevelGridView> >; template struct Codim : public Traits::template Codim {}; enum { dimension = HostGrid::dimension }; enum { dimensionworld = HostGrid::dimensionworld }; enum { conforming = Traits::conforming }; public: /// Constructor. template ...>::value, int> = 0> MultiGridView (GridViews&&... gridViews) : gridViews_{std::forward(gridViews)...} {} template ::value, int> = 0> MultiGridView (const std::vector& gridViews) : gridViews_(gridViews.begin(), gridViews.end()) {} template ::value_type>::value, int> = 0> MultiGridView (Iter first, Iter last) : gridViews_(first, last) {} template ::value_type>::value, int> = 0> MultiGridView (const IteratorRange& gridViews) : gridViews_(gridViews.begin(), gridViews.end()) {} /// Obtain a const reference to the underlying hierarchic grid const HostGrid& grid (std::size_t idx) const { return std::visit([](auto const& gv) { return gv.grid(); }, gridViews_[idx]); } /// Obtain the level-indexSet // NOTE: IndexSet is one of {LeafIndexSet, LevelIndexSet} // NOTE: do not return a reference, but a reference wrapper IndexSet indexSet (std::size_t idx) const { return std::visit([](auto const& gv) -> IndexSetTypes { return &gv.indexSet(); }, gridViews_[idx]); } /// Obtain number of entities in a given codimension int size (std::size_t idx, int codim) const { return std::visit([codim](auto const& gv) { return gv.size(codim); }, gridViews_[idx]); } /// Obtain number of entities with a given geometry type int size (std::size_t idx, const GeometryType& type) const { return std::visit([&type](auto const& gv) { return gv.size(type); }, gridViews_[idx]); } /// Obtain begin iterator for this view template typename Codim::template Partition::Iterator begin () const { static_assert(cd == 0, "Implemented for codim == 0 only"); return MultiMeshIterator(gridViews_); } /// Obtain end iterator for this view template typename Codim::template Partition::Iterator end () const { static_assert(cd == 0, "Implemented for codim == 0 only"); return MultiMeshIterator(gridViews_, true); } /// Obtain begin intersection iterator with respect to this view // NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator} IntersectionIterator ibegin (std::size_t idx, const typename Codim<0>::Entity& entity) const { using II = IntersectionIterator; return std::visit([&entity](auto const& gv) -> II { return gv.ibegin(entity); }, gridViews_[idx]); } /// Obtain end intersection iterator with respect to this view // NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator} IntersectionIterator iend (std::size_t idx, const typename Codim<0>::Entity& entity) const { using II = IntersectionIterator; return std::visit([&entity](auto const& gv) -> II { return gv.iend(entity); }, gridViews_[idx]); } /// Obtain collective communication object const CollectiveCommunication& comm (std::size_t idx) const { return std::visit([](auto const& gv) -> const auto& { return gv.comm(); }, gridViews_[idx]); } /// Return size of the overlap region for a given codim on the grid view. int overlapSize (std::size_t idx, int codim) const { return std::visit([codim](auto const& gv) { return gv.overlapSize(codim); }, gridViews_[idx]); } /// Return size of the ghost region for a given codim on the grid view. int ghostSize (std::size_t idx, int codim) const { return std::visit([codim](auto const& gv) { return gv.ghostSize(codim); }, gridViews_[idx]); } /// Communicate data on this view template void communicate (std::size_t idx, CommDataHandleIF& data, InterfaceType iftype, CommunicationDirection dir) const { std::visit([&data,iftype,dir](auto const& gv) { gv.communicate(data,iftype,dir); }, gridViews_[idx]); } private: std::vector gridViews_; }; } // end namespace Dune #endif // DUNE_MULTI_GRIDVIEW_HH