Commit 03a3282a authored by Praetorius, Simon's avatar Praetorius, Simon

Merge branch 'master' of gitlab.mn.tu-dresden.de:spraetor/dune-multimesh

parents 8901e45a c1c4ad7c
...@@ -51,9 +51,8 @@ namespace Dune ...@@ -51,9 +51,8 @@ namespace Dune
template <class... Args> template <class... Args>
explicit GridFactory (std::size_t n, Args&&... args) explicit GridFactory (std::size_t n, Args&&... args)
{ {
gridFactories_.reserve(n);
for (std::size_t i = 0; i < n; ++i) for (std::size_t i = 0; i < n; ++i)
gridFactories_.emplace_back(std::forward<Args>(args)...); gridFactories_.emplace_back(new GridFactory<HostGrid>{args...});
} }
// initialize at least 1 grid // initialize at least 1 grid
...@@ -68,7 +67,7 @@ namespace Dune ...@@ -68,7 +67,7 @@ namespace Dune
virtual void insertVertex (const GlobalCoordinate& pos) override virtual void insertVertex (const GlobalCoordinate& pos) override
{ {
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
gridFactory.insertVertex(pos); gridFactory->insertVertex(pos);
} }
/// \brief Insert an element into the coarse grid /// \brief Insert an element into the coarse grid
...@@ -80,7 +79,7 @@ namespace Dune ...@@ -80,7 +79,7 @@ namespace Dune
const std::vector<unsigned int>& vertices) override const std::vector<unsigned int>& vertices) override
{ {
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
gridFactory.insertElement(type, vertices); gridFactory->insertElement(type, vertices);
} }
...@@ -104,7 +103,7 @@ namespace Dune ...@@ -104,7 +103,7 @@ namespace Dune
Hybrid::ifElse(Std::is_detected<HasInsertElement, GridFactory<HostGrid>>{}, Hybrid::ifElse(Std::is_detected<HasInsertElement, GridFactory<HostGrid>>{},
[&](auto id) { [&](auto id) {
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
id(gridFactory).insertElement(type, vertices, param); id(gridFactory)->insertElement(type, vertices, param);
}); });
} }
...@@ -117,7 +116,7 @@ namespace Dune ...@@ -117,7 +116,7 @@ namespace Dune
const std::vector<unsigned int>& vertices) override const std::vector<unsigned int>& vertices) override
{ {
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
gridFactory.insertBoundarySegment(vertices); gridFactory->insertBoundarySegment(vertices);
} }
...@@ -138,7 +137,7 @@ namespace Dune ...@@ -138,7 +137,7 @@ namespace Dune
Hybrid::ifElse(Std::is_detected<HasInsertBoundarySegment, GridFactory<HostGrid>>{}, Hybrid::ifElse(Std::is_detected<HasInsertBoundarySegment, GridFactory<HostGrid>>{},
[&](auto id) { [&](auto id) {
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
id(gridFactory).insertBoundarySegment(vertices, boundarySegment); id(gridFactory)->insertBoundarySegment(vertices, boundarySegment);
}); });
} }
...@@ -152,12 +151,12 @@ namespace Dune ...@@ -152,12 +151,12 @@ namespace Dune
{ {
Grid* multimesh = new Grid{}; Grid* multimesh = new Grid{};
for (auto& gridFactory : gridFactories_) for (auto& gridFactory : gridFactories_)
multimesh->grids_.emplace_back(gridFactory.createGrid()); multimesh->grids_.emplace_back(gridFactory->createGrid());
return multimesh; return multimesh;
} }
private: private:
std::vector<GridFactory<HostGrid> > gridFactories_; std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
}; };
} // end namespace Dune } // end namespace Dune
......
...@@ -223,13 +223,13 @@ namespace Dune ...@@ -223,13 +223,13 @@ 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;
/// Type of the corresponding GridType hosted by the MultiMesh /// Type of the corresponding GridType hosted by the MultiMesh
using HostGrid = typename GridImp::HostGridType; using HostGrid = typename GridImp::HostGrid;
using IndexSet = typename Traits::IndexSet; using IndexSet = typename Traits::IndexSet;
using Intersection = typename Traits::Intersection; using Intersection = typename Traits::Intersection;
...@@ -255,7 +255,7 @@ namespace Dune ...@@ -255,7 +255,7 @@ namespace Dune
const HostGrid& grid (std::size_t i) const const HostGrid& grid (std::size_t i) const
{ {
return multiMesh_->grid(i); return multiMesh_[i];
} }
/// Obtain the level-indexSet /// Obtain the level-indexSet
......
...@@ -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_;
}