// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // vi: set et ts=4 sw=2 sts=2: #ifndef DUNE_MULTI_ITERATOR_HH #define DUNE_MULTI_ITERATOR_HH #include #include #include #include #include #include #include "mmentity.hh" #include "mmhierarchiciterator.hh" #include "mmiteratorbase.hh" namespace Dune { template class MultiIterator : public DummyIterator { using DummyIterator::DummyIterator; }; template class MultiIterator<0,pitype,HostGrid> : public MultiMeshIteratorBase> { using Self = MultiIterator; using Super = MultiMeshIteratorBase; using HostEntity = typename HostGrid::template Codim<0>::Entity; using EntityTest = typename Super::EntityTest; template using IsGridView = Std::disjunction< std::is_same,typename HostGrid::LeafGridView>, std::is_same,typename HostGrid::LevelGridView> >; public: template ...>::value, int> = 0> MultiIterator (tag::begin_iterator, GridViews const&... gridViews) : Super{tag::begin_iterator{}, gridViews...} , incrementAllowed_(sizeof...(GridViews), true) , multiEntity_(sizeof...(GridViews)) { contains_.reserve(sizeof...(GridViews)); Hybrid::forEach(std::forward_as_tuple(gridViews...), [this](auto const& gv) { contains_.emplace_back([gv](const HostEntity& entity) { return gv.contains(entity); }); }); this->initialIncrement(); } #if DUNE_HAVE_CXX_VARIANT /// Construct an iterator from a vector of GridViews, where each GridView can be /// either a leaf- or a level-gridView, thus we need to use a variant. template MultiIterator (tag::begin_iterator, const std::vector>& gridViews) : Super{tag::begin_iterator{}, gridViews} , incrementAllowed_(gridViews.size(), true) , multiEntity_(gridViews.size()) { contains_.reserve(gridViews.size()); for (auto const& gvs : gridViews) { contains_.emplace_back(std::visit([](auto const& gv) { return EntityTest{[gv](const HostEntity& entity) { return gv.contains(entity); }}; }, gvs)); } this->initialIncrement(); } #endif // End iterator template MultiIterator (tag::end_iterator, Args&&... args) : Super{tag::end_iterator{}, std::forward(args)...} {} void initialIncrement_impl () { for (std::size_t i = 0; i < this->size(); ++i) this->initialIncrement(i); } void increment_impl () { for (std::size_t i = 0; i < this->size(); ++i) incrementAllowed_[i] = this->incrementAllowed(i); for (std::size_t i = 0; i < this->size(); ++i) { if (incrementAllowed_[i]) this->increment(i); } } const MultiEntity& dereference_impl () const { // update entries in multiEntity that have changed for (std::size_t i = 0; i < this->size(); ++i) { if (incrementAllowed_[i]) multiEntity_[i] = this->dereference(i); } return multiEntity_; } bool levelReached_impl (std::size_t i, const HostEntity& entity) const { return contains_[i](entity) || entity.isLeaf(); } private: std::vector incrementAllowed_; std::vector contains_; mutable MultiEntity multiEntity_; }; template inline auto multi_elements(GridViews const&... gridViews) { using GridView0 = std::tuple_element_t<0,std::tuple>; using Iterator = MultiIterator<0,All_Partition,typename GridView0::Grid>; using Range = IteratorRange; return Range{ Iterator{tag::begin_iterator{}, gridViews...}, Iterator{tag::end_iterator{}, gridViews...} }; } } // end namespace Dune #endif // DUNE_MULTI_ITERATOR_HH