Commit 848b8812 authored by Praetorius, Simon's avatar Praetorius, Simon

reorganization of multimesh iterator to support various implementation of increment

parent b54b6417
...@@ -223,7 +223,7 @@ namespace Dune ...@@ -223,7 +223,7 @@ namespace Dune
class MultiMeshLeafGridView class MultiMeshLeafGridView
{ {
public: public:
using Traits = MultiMeshLevelGridViewTraits<GridImp>; using Traits = MultiMeshLeafGridViewTraits<GridImp>;
/// The MultiMesh GridType /// The MultiMesh GridType
using Grid = typename Traits::Grid; using Grid = typename Traits::Grid;
......
...@@ -22,8 +22,8 @@ namespace Dune ...@@ -22,8 +22,8 @@ namespace Dune
typename HostGrid::template Codim<0>::Entity> typename HostGrid::template Codim<0>::Entity>
{ {
private: private:
template <int codim, PartitionIteratorType pitype, class HostGrid_> template <PartitionIteratorType pitype, class HG, class D>
friend class MultiMeshIterator; friend class MultiMeshIteratorBase;
using HostEntity = typename HostGrid::template Codim<0>::Entity; using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = std::function<bool(HostEntity)>; using EntityTest = std::function<bool(HostEntity)>;
......
...@@ -4,295 +4,245 @@ ...@@ -4,295 +4,245 @@
#define DUNE_MULTIMESH_ITERATOR_HH #define DUNE_MULTIMESH_ITERATOR_HH
#include <numeric> #include <numeric>
#include <stack> #include <vector>
#include <variant>
#include <dune/common/iteratorfacades.hh> #include <dune/common/iteratorfacades.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/grid/common/exceptions.hh>
#include <dune/grid/common/gridenums.hh> #include <dune/grid/common/gridenums.hh>
#include "mmentity.hh" #include "mmentity.hh"
#include "mmhierarchiciterator.hh" #include "mmhierarchiciterator.hh"
#include "mmiteratorbase.hh"
namespace Dune namespace Dune
{ {
/** \brief Iterator over all entities of a given codimension and level of a grid.
* \ingroup MultiMesh
*/
template <int codim, PartitionIteratorType pitype, class HostGrid> template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshIterator class MultiMeshLevelIterator : public DummyIterator
{ {
public: using DummyIterator::DummyIterator;
template <class... Args>
MultiMeshIterator(Args&&... args)
{
DUNE_THROW(NotImplemented, "Not implemented for entity of codim != 0!");
}
int operator*() const { return 0; }
MultiMeshIterator& operator++() { return *this; }
MultiMeshIterator operator++(int) { return *this; }
bool operator!=(MultiMeshIterator const&) const { return false; }
}; };
// Implemented for codim 0 entities only
template <PartitionIteratorType pitype, class HostGrid> template <PartitionIteratorType pitype, class HostGrid>
class MultiMeshIterator<0, pitype, HostGrid> class MultiMeshLevelIterator<0,pitype,HostGrid>
: public ForwardIteratorFacade<MultiMeshIterator<0,pitype,HostGrid>, : public MultiMeshIteratorBase<pitype,HostGrid,MultiMeshLevelIterator<0,pitype,HostGrid>>
MultiEntity<HostGrid>,
MultiEntity<HostGrid> const&>
{ {
private: using Self = MultiMeshLevelIterator;
// LevelIterator to the equivalent entity in the host grid using Super = MultiMeshIteratorBase<pitype,HostGrid,Self>;
using HostGridLevelIterator =
typename HostGrid::template Codim<0>::template Partition<pitype>::LevelIterator;
using HostEntity = typename HostGrid::template Codim<0>::Entity; using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = typename Super::EntityTest;
using EntityTest = typename MultiMeshHierarchicIterator<HostGrid>::EntityTest;
using EntityStack = typename MultiMeshHierarchicIterator<HostGrid>::EntityStack;
public: public:
/// Constructor. Stores a pointer to the grid // Level iterator
template <class GridImp> template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, int level) MultiMeshLevelIterator (tag::begin_iterator, const GridImp* multiMesh, int level)
: incrementAllowed_(multiMesh->size(), true) : Super{tag::begin_iterator{}, multiMesh}
, incrementAllowed_(multiMesh->size(), true)
, contains_(multiMesh->size(), EntityTest{[level](const HostEntity& entity) { return entity.level() == level; }}) , contains_(multiMesh->size(), EntityTest{[level](const HostEntity& entity) { return entity.level() == level; }})
, maxLevel_(multiMesh->size(), level)
, multiEntity_(multiMesh->size()) , multiEntity_(multiMesh->size())
{ {
for (auto const& grid : multiMesh->grids_) { this->initialIncrement();
macroIterators_.push_back(grid->levelGridView(0).template begin<0,pitype>());
macroEndIterators_.push_back(grid->levelGridView(0).template end<0,pitype>());
}
// go to first leaf entity on all grids
entityStacks_.reserve(multiMesh->size());
for (std::size_t i = 0; i < multiMesh->size(); ++i) {
maxLevel_[i] = (*multiMesh)[i].maxLevel();
entityStacks_.emplace_back((*multiMesh)[i].maxLevel());
initialIncrement(i);
}
} }
/// Constructor which create the end iterator // End iterator
/**
* \param multiMesh Pointer to grid instance
* \param endDummy Here only to distinguish it from the other constructor
*/
template <class GridImp> template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, int level, bool endDummy) MultiMeshLevelIterator (tag::end_iterator, const GridImp* multiMesh, int level = -1)
: Super{tag::end_iterator{}, multiMesh}
{}
void initialIncrement_impl ()
{ {
for (auto const& grid : multiMesh->grids_) for (std::size_t i = 0; i < this->size(); ++i)
macroIterators_.push_back(grid->levelGridView(0).template end<0,pitype>()); this->initialIncrement(i);
} }
/// Constructor which create the leaf-iterator void increment_impl ()
template <class GridImp> {
MultiMeshIterator (const GridImp* multiMesh) for (std::size_t i = 0; i < this->size(); ++i)
: MultiMeshIterator{multiMesh, -1} incrementAllowed_[i] = this->incrementAllowed(i);
{}
/// Constructor which create the end leaf-iterator for (std::size_t i = 0; i < this->size(); ++i) {
template <class GridImp> if (incrementAllowed_[i])
MultiMeshIterator (const GridImp* multiMesh, bool endDummy) this->increment(i);
: MultiMeshIterator{multiMesh, -1, endDummy} }
{} }
/// Construct an iterator from n gridViews of possibly different type const MultiEntity<HostGrid>& dereference_impl () const
template <class... GridViews,
std::enable_if_t<not Std::disjunction<std::is_same<GridViews,bool>...>::value, int> = 0>
MultiMeshIterator (GridViews const&... gridViews)
: incrementAllowed_(sizeof...(GridViews), true)
, maxLevel_{gridViews.grid().maxLevel()...}
, multiEntity_(sizeof...(GridViews))
, macroIterators_{gridViews.grid().levelGridView(0).template begin<0,pitype>()...}
, macroEndIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...}
, entityStacks_{EntityStack{gridViews.grid().maxLevel()}...}
{ {
contains_.reserve(sizeof...(GridViews)); // update entries in multiEntity that have changed
Hybrid::forEach(std::forward_as_tuple(gridViews...), [this](auto const& gv) { for (std::size_t i = 0; i < this->size(); ++i) {
contains_.emplace_back([gv](const HostEntity& entity) { return gv.contains(entity); }); if (incrementAllowed_[i])
}); multiEntity_[i] = this->dereference(i);
}
return multiEntity_;
}
for (std::size_t i = 0; i < sizeof...(GridViews); ++i) bool levelReached_impl (std::size_t i, const HostEntity& entity) const
initialIncrement(i); {
return contains_[i](entity) || entity.isLeaf();
} }
template <class... GridViews> private:
MultiMeshIterator (bool endDummy, GridViews const&... gridViews) std::vector<bool> incrementAllowed_;
: macroIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...} std::vector<EntityTest> contains_;
{} mutable MultiEntity<HostGrid> multiEntity_;
};
#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 <class... GV>
MultiMeshIterator (const std::vector<std::variant<GV...>>& gridViews)
: incrementAllowed_(gridViews.size(), true)
, multiEntity_(gridViews.size())
{
contains_.reserve(gridViews.size());
entityStacks_.reserve(gridViews.size());
maxLevel_.reserve(gridViews.size());
for (auto const& gvs : gridViews) {
macroIterators_.push_back(std::visit([](auto const& gv) {
return gv.grid().levelGridView(0).template begin<0,pitype>(); }, gvs));
macroEndIterators_.push_back(std::visit([](auto const& gv) {
return gv.grid().levelGridView(0).template end<0,pitype>(); }, gvs));
contains_.emplace_back(std::visit([](auto const& gv) {
return EntityTest{[gv](const HostEntity& entity) { return gv.contains(entity); }}; }, gvs));
maxLevel_.push_back(std::visit([](auto const& gv) { return gv.grid().maxLevel(); }, gvs));
entityStacks_.emplace_back(std::visit([](auto const& gv) { return gv.grid().maxLevel(); }, gvs));
}
// go to first leaf entity on all grids template <int codim, PartitionIteratorType pitype, class HostGrid>
for (std::size_t i = 0; i < entityStacks_.size(); ++i) class MultiMeshLeafIterator : public DummyIterator
initialIncrement(i); {
using DummyIterator::DummyIterator;
};
template <PartitionIteratorType pitype, class HostGrid>
class MultiMeshLeafIterator<0,pitype,HostGrid>
: public MultiMeshIteratorBase<pitype,HostGrid,MultiMeshLeafIterator<0,pitype,HostGrid>>
{
using Self = MultiMeshLeafIterator;
using Super = MultiMeshIteratorBase<pitype,HostGrid,Self>;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
public:
// Leaf iterator
template <class GridImp>
MultiMeshLeafIterator (tag::begin_iterator, const GridImp* multiMesh)
: Super{tag::begin_iterator{}, multiMesh}
, incrementAllowed_(multiMesh->size(), true)
, multiEntity_(multiMesh->size())
{
this->initialIncrement();
} }
template <class... GV> // End iterator
MultiMeshIterator (const std::vector<std::variant<GV...>>& gridViews, bool endDummy) template <class GridImp>
MultiMeshLeafIterator (tag::end_iterator, const GridImp* multiMesh)
: Super{tag::end_iterator{}, multiMesh}
{}
void initialIncrement_impl ()
{ {
for (auto const& gvs : gridViews) { for (std::size_t i = 0; i < this->size(); ++i)
macroIterators_.push_back(std::visit([](auto const& gv) { this->initialIncrement(i);
return gv.grid().levelGridView(0).template end<0,pitype>(); }, gvs));
}
} }
#endif
/// prefix increment void increment_impl ()
void increment ()
{ {
for (std::size_t i = 0; i < entityStacks_.size(); ++i) for (std::size_t i = 0; i < this->size(); ++i)
incrementAllowed_[i] = incrementAllowed(i); incrementAllowed_[i] = this->incrementAllowed(i);
for (std::size_t i = 0; i < entityStacks_.size(); ++i) { for (std::size_t i = 0; i < this->size(); ++i) {
if (incrementAllowed_[i]) if (incrementAllowed_[i])
increment(i); this->increment(i);
} }
} }
/// dereferencing const MultiEntity<HostGrid>& dereference_impl () const
MultiEntity<HostGrid> const& dereference () const
{ {
// update entries in multiEntity that have changed // update entries in multiEntity that have changed
for (std::size_t i = 0; i < entityStacks_.size(); ++i) { for (std::size_t i = 0; i < this->size(); ++i) {
if (incrementAllowed_[i]) if (incrementAllowed_[i])
multiEntity_[i] = dereference(i); multiEntity_[i] = this->dereference(i);
} }
return multiEntity_; return multiEntity_;
} }
/// equality bool levelReached_impl (std::size_t /*i*/, const HostEntity& entity) const
bool equals (const MultiMeshIterator& that) const
{ {
return macroIterators_ == that.macroIterators_; return entity.isLeaf();
} }
protected: private:
// got to next entity in grid i std::vector<bool> incrementAllowed_;
void increment (std::size_t i) mutable MultiEntity<HostGrid> multiEntity_;
{ };
auto& entityStack = entityStacks_[i];
auto& macroIt = macroIterators_[i];
auto const& macroEnd = macroEndIterators_[i];
// 1. go up in tree or to next entity on current level until we can go down again
while (!entityStack.empty()) {
auto& top = entityStack.top();
++top.it;
if (top.it == top.end) {
entityStack.pop();
} else {
break;
}
}
// 2. if entityStack is empty, go to next macroElement
if (entityStack.empty()) {
++macroIt;
if (macroIt == macroEnd)
return;
}
// 3. go down in tree until leaf entity template <int codim, PartitionIteratorType pitype, class HostGrid>
auto child = dereference(i); class MultiMeshMasterLeafIterator : public DummyIterator
for (; !(contains_[i](child) || child.isLeaf()); child = dereference(i)) { {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal"); using DummyIterator::DummyIterator;
entityStack.emplace(child); };
assert(entityStack.size() <= maxLevel_[i]);
} template <PartitionIteratorType pitype, class HostGrid>
class MultiMeshMasterLeafIterator<0,pitype,HostGrid>
: public MultiMeshIteratorBase<pitype,HostGrid,MultiMeshMasterLeafIterator<0,pitype,HostGrid>>
{
using Self = MultiMeshMasterLeafIterator;
using Super = MultiMeshIteratorBase<pitype,HostGrid,Self>;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
// assert(contains_[i](child) && "No valid child element found in gridView"); public:
// Leaf iterator
template <class GridImp>
MultiMeshMasterLeafIterator (tag::begin_iterator, const GridImp* multiMesh, std::size_t master)
: Super{tag::begin_iterator{}, multiMesh}
, incrementAllowed_(multiMesh->size(), true)
, level_(multiMesh->size())
, multiEntity_(multiMesh->size())
, master_(master)
{
this->initialIncrement();
} }
/// Return true, if all stacks with size > stack[i].size are finished // End iterator
bool incrementAllowed (std::size_t i) const template <class GridImp>
MultiMeshMasterLeafIterator (tag::end_iterator, const GridImp* multiMesh)
: Super{tag::end_iterator{}, multiMesh}
{}
// first increment the master grid then the others
void initialIncrement_impl ()
{ {
std::size_t size = entityStacks_[i].size(); level_[master_] = this->initialIncrement(master_);
return std::accumulate(entityStacks_.begin(), entityStacks_.end(), true, for (std::size_t i = 0; i < this->size(); ++i)
[i,size](bool allowed, auto const& entityStack) { if (i != master_)
return allowed && (entityStack.size() <= size || entityStack.finished(size)); level_[i] = this->initialIncrement(i);
});
} }
// got to first leaf entity on grid i // first increment the master grid then the others
void initialIncrement (std::size_t i) void increment_impl ()
{ {
auto& entityStack = entityStacks_[i]; for (std::size_t i = 0; i < this->size(); ++i)
auto& macroIt = macroIterators_[i]; incrementAllowed_[i] = this->incrementAllowed(i);
auto const& macroEnd = macroEndIterators_[i];
if (incrementAllowed_[master_])
assert(entityStack.empty()); level_[master_] = this->increment(master_);
if (macroIt == macroEnd) for (std::size_t i = 0; i < this->size(); ++i) {
return; if (i != master_ && incrementAllowed_[i])
level_[i] = this->increment(i);
// 1. go down in tree until leaf entity
auto child = dereference(i);
for (; !(contains_[i](child) || child.isLeaf()); child = dereference(i)) {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal");
entityStack.emplace(child);
assert(entityStack.size() <= maxLevel_[i]);
} }
// assert(contains_[i](child) && "No valid child element found in gridView");
} }
HostEntity dereference (std::size_t i) const const MultiEntity<HostGrid>& dereference_impl () const
{ {
if (entityStacks_[i].empty()) { // update entries in multiEntity that have changed
assert(macroIterators_[i] != macroEndIterators_[i]); for (std::size_t i = 0; i < this->size(); ++i) {
return *macroIterators_[i]; if (incrementAllowed_[i])
} else { multiEntity_[i] = this->dereference(i);
assert(entityStacks_[i].top().it != entityStacks_[i].top().end);
return *entityStacks_[i].top().it;
} }
return multiEntity_;
}
// got down to leaf entity on master grid and until the master grid level for the other grids
bool levelReached_impl (std::size_t i, const HostEntity& entity) const
{
return (i == master_ && entity.isLeaf()) || entity.level() == level_[master_];
} }
private: private:
std::vector<bool> incrementAllowed_; std::vector<bool> incrementAllowed_;
std::vector<EntityTest> contains_; std::vector<int> level_;
std::vector<int> maxLevel_;
mutable MultiEntity<HostGrid> multiEntity_; mutable MultiEntity<HostGrid> multiEntity_;
std::size_t master_;
std::vector<HostGridLevelIterator> macroIterators_;
std::vector<HostGridLevelIterator> macroEndIterators_;
std::vector<EntityStack> entityStacks_;
}; };
template <class... GridViews>
inline auto multi_elements(GridViews const&... gridViews) template <PartitionIteratorType pitype = All_Partition, class Grid>
inline auto master_leaf_elements(Grid const& multiMesh, std::size_t master)
{ {
using GridView0 = std::tuple_element_t<0,std::tuple<GridViews...>>; using Iterator = MultiMeshMasterLeafIterator<0,pitype,Grid>;
using Iterator = MultiMeshIterator<0,All_Partition,typename GridView0::Grid>;
using Range = IteratorRange<Iterator>; using Range = IteratorRange<Iterator>;
return Range{ Iterator{gridViews...}, return Range{ Iterator{tag::begin_iterator{}, &multiMesh, master},
Iterator{true, gridViews...} }; Iterator{tag::end_iterator{}, &multiMesh} };
} }
} // end namespace Dune } // end namespace Dune
......
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_MULTIMESH_ITERATOR_BASE_HH
#define DUNE_MULTIMESH_ITERATOR_BASE_HH
#include <numeric>
#include <stack>
#include <type_traits>
#include <dune/common/std/type_traits.hh>
#include <dune/grid/common/gridenums.hh>
#include "mmentity.hh"
#include "mmhierarchiciterator.hh"
#include "mmiteratorinterface.hh"
namespace Dune
{
template <PartitionIteratorType pitype, class HostGrid, class Derived>
class MultiMeshIteratorBase
: public MultiMeshIteratorInterface<HostGrid,Derived>
{
using Super = MultiMeshIteratorInterface<HostGrid,Derived>;
protected:
// LevelIterator to the equivalent entity in the host grid
using HostGridLevelIterator =
typename HostGrid::template Codim<0>::template Partition<pitype>::LevelIterator;
template <class GV>
using IsGridView = Std::disjunction<
std::is_same<std::decay_t<GV>,typename HostGrid::LeafGridView>,
std::is_same<std::decay_t<GV>,typename HostGrid::LevelGridView> >;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = typename MultiMeshHierarchicIterator<HostGrid>::EntityTest;
using EntityStack = typename MultiMeshHierarchicIterator<HostGrid>::EntityStack;
public:
/// Constructor which creates the begin iterator
/**
* \param multiMesh Pointer to grid instance
*/
template <class GridImp>
MultiMeshIteratorBase (tag::begin_iterator, const GridImp* multiMesh)
: maxLevel_(multiMesh->size())
{
for (std::size_t i = 0; i < multiMesh->size(); ++i) {
macroIterators_.push_back(multiMesh->levelGridView(i,0).template begin<0,pitype>());
macroEndIterators_.push_back(multiMesh->levelGridView(i,0).template end<0,pitype>());
}
// go to first leaf entity on all grids
entityStacks_.reserve(multiMesh->size());
for (std::size_t i = 0; i < multiMesh->size(); ++i) {
maxLevel_[i] = (*multiMesh)[i].maxLevel();
entityStacks_.emplace_back((*multiMesh)[i].maxLevel());
}
}
/// Constructor which creates the end iterator
/**
* \param multiMesh Pointer to grid instance
*/
template <class GridImp>
MultiMeshIteratorBase (tag::end_iterator, const GridImp* multiMesh)
{
for (std::size_t i = 0; i < multiMesh->size(); ++i)
macroIterators_.push_back(multiMesh->levelGridView(i,0).template end<0,pitype>());
}
/// Construct an iterator from n gridViews of possibly different type
template <class... GridViews,
std::enable_if_t<Std::conjunction<IsGridView<GridViews>...>::value, int> = 0>
MultiMeshIteratorBase (tag::begin_iterator, GridViews const&... gridViews)
: maxLevel_{gridViews.grid().maxLevel()...}
, macroIterators_{gridViews.grid().levelGridView(0).template begin<0,pitype>()...}
, macroEndIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...}
, entityStacks_{EntityStack{gridViews.grid().maxLevel()}...}
{}