Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

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

reorganization of multimesh iterator to support various implementation of increment

parent b54b6417
......@@ -223,7 +223,7 @@ namespace Dune
class MultiMeshLeafGridView
{
public:
using Traits = MultiMeshLevelGridViewTraits<GridImp>;
using Traits = MultiMeshLeafGridViewTraits<GridImp>;
/// The MultiMesh GridType
using Grid = typename Traits::Grid;
......
......@@ -22,8 +22,8 @@ namespace Dune
typename HostGrid::template Codim<0>::Entity>
{
private:
template <int codim, PartitionIteratorType pitype, class HostGrid_>
friend class MultiMeshIterator;
template <PartitionIteratorType pitype, class HG, class D>
friend class MultiMeshIteratorBase;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = std::function<bool(HostEntity)>;
......
......@@ -4,295 +4,245 @@
#define DUNE_MULTIMESH_ITERATOR_HH
#include <numeric>
#include <stack>
#include <variant>
#include <vector>
#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 "mmentity.hh"
#include "mmhierarchiciterator.hh"
#include "mmiteratorbase.hh"
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>
class MultiMeshIterator
class MultiMeshLevelIterator : public DummyIterator
{
public:
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; }
using DummyIterator::DummyIterator;
};
// Implemented for codim 0 entities only
template <PartitionIteratorType pitype, class HostGrid>
class MultiMeshIterator<0, pitype, HostGrid>
: public ForwardIteratorFacade<MultiMeshIterator<0,pitype,HostGrid>,
MultiEntity<HostGrid>,
MultiEntity<HostGrid> const&>
class MultiMeshLevelIterator<0,pitype,HostGrid>
: public MultiMeshIteratorBase<pitype,HostGrid,MultiMeshLevelIterator<0,pitype,HostGrid>>
{
private:
// LevelIterator to the equivalent entity in the host grid
using HostGridLevelIterator =
typename HostGrid::template Codim<0>::template Partition<pitype>::LevelIterator;
using Self = MultiMeshLevelIterator;
using Super = MultiMeshIteratorBase<pitype,HostGrid,Self>;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = typename MultiMeshHierarchicIterator<HostGrid>::EntityTest;
using EntityStack = typename MultiMeshHierarchicIterator<HostGrid>::EntityStack;
using EntityTest = typename Super::EntityTest;
public:
/// Constructor. Stores a pointer to the grid
// Level iterator
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, int level)
: incrementAllowed_(multiMesh->size(), true)
MultiMeshLevelIterator (tag::begin_iterator, const GridImp* multiMesh, int level)
: Super{tag::begin_iterator{}, multiMesh}
, incrementAllowed_(multiMesh->size(), true)
, contains_(multiMesh->size(), EntityTest{[level](const HostEntity& entity) { return entity.level() == level; }})
, maxLevel_(multiMesh->size(), level)
, multiEntity_(multiMesh->size())
{
for (auto const& grid : multiMesh->grids_) {
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);
}
this->initialIncrement();
}
/// Constructor which create the end iterator
/**
* \param multiMesh Pointer to grid instance
* \param endDummy Here only to distinguish it from the other constructor
*/
// End iterator
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_)
macroIterators_.push_back(grid->levelGridView(0).template end<0,pitype>());
for (std::size_t i = 0; i < this->size(); ++i)
this->initialIncrement(i);
}
/// Constructor which create the leaf-iterator
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh)
: MultiMeshIterator{multiMesh, -1}
{}
void increment_impl ()
{
for (std::size_t i = 0; i < this->size(); ++i)
incrementAllowed_[i] = this->incrementAllowed(i);
/// Constructor which create the end leaf-iterator
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, bool endDummy)
: MultiMeshIterator{multiMesh, -1, endDummy}
{}
for (std::size_t i = 0; i < this->size(); ++i) {
if (incrementAllowed_[i])
this->increment(i);
}
}
/// Construct an iterator from n gridViews of possibly different type
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()}...}
const MultiEntity<HostGrid>& dereference_impl () const
{
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); });
});
// 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_;
}
for (std::size_t i = 0; i < sizeof...(GridViews); ++i)
initialIncrement(i);
bool levelReached_impl (std::size_t i, const HostEntity& entity) const
{
return contains_[i](entity) || entity.isLeaf();
}
template <class... GridViews>
MultiMeshIterator (bool endDummy, GridViews const&... gridViews)
: macroIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...}
{}
private:
std::vector<bool> incrementAllowed_;
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
for (std::size_t i = 0; i < entityStacks_.size(); ++i)
initialIncrement(i);
template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshLeafIterator : public DummyIterator
{
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>
MultiMeshIterator (const std::vector<std::variant<GV...>>& gridViews, bool endDummy)
// End iterator
template <class GridImp>
MultiMeshLeafIterator (tag::end_iterator, const GridImp* multiMesh)
: Super{tag::end_iterator{}, multiMesh}
{}
void initialIncrement_impl ()
{
for (auto const& gvs : gridViews) {
macroIterators_.push_back(std::visit([](auto const& gv) {
return gv.grid().levelGridView(0).template end<0,pitype>(); }, gvs));
}
for (std::size_t i = 0; i < this->size(); ++i)
this->initialIncrement(i);
}
#endif
/// prefix increment
void increment ()
void increment_impl ()
{
for (std::size_t i = 0; i < entityStacks_.size(); ++i)
incrementAllowed_[i] = incrementAllowed(i);
for (std::size_t i = 0; i < this->size(); ++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])
increment(i);
this->increment(i);
}
}
/// dereferencing
MultiEntity<HostGrid> const& dereference () const
const MultiEntity<HostGrid>& dereference_impl () const
{
// 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])
multiEntity_[i] = dereference(i);
multiEntity_[i] = this->dereference(i);
}
return multiEntity_;
}
/// equality
bool equals (const MultiMeshIterator& that) const
bool levelReached_impl (std::size_t /*i*/, const HostEntity& entity) const
{
return macroIterators_ == that.macroIterators_;
return entity.isLeaf();
}
protected:
// got to next entity in grid i
void increment (std::size_t i)
{
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;
}
}
private:
std::vector<bool> incrementAllowed_;
mutable MultiEntity<HostGrid> multiEntity_;
};
// 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
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]);
}
template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshMasterLeafIterator : public DummyIterator
{
using DummyIterator::DummyIterator;
};
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
bool incrementAllowed (std::size_t i) const
// End iterator
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();
return std::accumulate(entityStacks_.begin(), entityStacks_.end(), true,
[i,size](bool allowed, auto const& entityStack) {
return allowed && (entityStack.size() <= size || entityStack.finished(size));
});
level_[master_] = this->initialIncrement(master_);
for (std::size_t i = 0; i < this->size(); ++i)
if (i != master_)
level_[i] = this->initialIncrement(i);
}
// got to first leaf entity on grid i
void initialIncrement (std::size_t i)
// first increment the master grid then the others
void increment_impl ()
{
auto& entityStack = entityStacks_[i];
auto& macroIt = macroIterators_[i];
auto const& macroEnd = macroEndIterators_[i];
assert(entityStack.empty());
if (macroIt == macroEnd)
return;
// 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]);
for (std::size_t i = 0; i < this->size(); ++i)
incrementAllowed_[i] = this->incrementAllowed(i);
if (incrementAllowed_[master_])
level_[master_] = this->increment(master_);
for (std::size_t i = 0; i < this->size(); ++i) {
if (i != master_ && incrementAllowed_[i])
level_[i] = this->increment(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()) {
assert(macroIterators_[i] != macroEndIterators_[i]);
return *macroIterators_[i];
} else {
assert(entityStacks_[i].top().it != entityStacks_[i].top().end);
return *entityStacks_[i].top().it;
// 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_;
}
// 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:
std::vector<bool> incrementAllowed_;
std::vector<EntityTest> contains_;
std::vector<int> maxLevel_;
std::vector<int> level_;
mutable MultiEntity<HostGrid> multiEntity_;
std::vector<HostGridLevelIterator> macroIterators_;
std::vector<HostGridLevelIterator> macroEndIterators_;
std::vector<EntityStack> entityStacks_;
std::size_t master_;
};
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 = MultiMeshIterator<0,All_Partition,typename GridView0::Grid>;
using Iterator = MultiMeshMasterLeafIterator<0,pitype,Grid>;
using Range = IteratorRange<Iterator>;
return Range{ Iterator{gridViews...},
Iterator{true, gridViews...} };
return Range{ Iterator{tag::begin_iterator{}, &multiMesh, master},
Iterator{tag::end_iterator{}, &multiMesh} };
}
} // 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()}...}
{}
template <class... GridViews,
std::enable_if_t<Std::conjunction<IsGridView<GridViews>...>::value, int> = 0>
MultiMeshIteratorBase (tag::end_iterator, GridViews const&... gridViews)
: macroIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...}
{}
#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>
MultiMeshIteratorBase (tag::begin_iterator, const std::vector<std::variant<GV...>>& gridViews)
{
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));
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));
}
}