Commit c1c4ad7c authored by Praetorius, Simon's avatar Praetorius, Simon

Merge branch 'feature/master_grid' into 'master'

Feature/master grid

See merge request !4
parents b54b6417 56785e12
......@@ -51,9 +51,8 @@ namespace Dune
template <class... Args>
explicit GridFactory (std::size_t n, Args&&... args)
{
gridFactories_.reserve(n);
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
......@@ -68,7 +67,7 @@ namespace Dune
virtual void insertVertex (const GlobalCoordinate& pos) override
{
for (auto& gridFactory : gridFactories_)
gridFactory.insertVertex(pos);
gridFactory->insertVertex(pos);
}
/// \brief Insert an element into the coarse grid
......@@ -80,7 +79,7 @@ namespace Dune
const std::vector<unsigned int>& vertices) override
{
for (auto& gridFactory : gridFactories_)
gridFactory.insertElement(type, vertices);
gridFactory->insertElement(type, vertices);
}
......@@ -104,7 +103,7 @@ namespace Dune
Hybrid::ifElse(Std::is_detected<HasInsertElement, GridFactory<HostGrid>>{},
[&](auto id) {
for (auto& gridFactory : gridFactories_)
id(gridFactory).insertElement(type, vertices, param);
id(gridFactory)->insertElement(type, vertices, param);
});
}
......@@ -117,7 +116,7 @@ namespace Dune
const std::vector<unsigned int>& vertices) override
{
for (auto& gridFactory : gridFactories_)
gridFactory.insertBoundarySegment(vertices);
gridFactory->insertBoundarySegment(vertices);
}
......@@ -138,7 +137,7 @@ namespace Dune
Hybrid::ifElse(Std::is_detected<HasInsertBoundarySegment, GridFactory<HostGrid>>{},
[&](auto id) {
for (auto& gridFactory : gridFactories_)
id(gridFactory).insertBoundarySegment(vertices, boundarySegment);
id(gridFactory)->insertBoundarySegment(vertices, boundarySegment);
});
}
......@@ -152,12 +151,12 @@ namespace Dune
{
Grid* multimesh = new Grid{};
for (auto& gridFactory : gridFactories_)
multimesh->grids_.emplace_back(gridFactory.createGrid());
multimesh->grids_.emplace_back(gridFactory->createGrid());
return multimesh;
}
private:
std::vector<GridFactory<HostGrid> > gridFactories_;
std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
};
} // end namespace Dune
......
......@@ -223,13 +223,13 @@ namespace Dune
class MultiMeshLeafGridView
{
public:
using Traits = MultiMeshLevelGridViewTraits<GridImp>;
using Traits = MultiMeshLeafGridViewTraits<GridImp>;
/// The MultiMesh GridType
using Grid = typename Traits::Grid;
/// 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 Intersection = typename Traits::Intersection;
......@@ -255,7 +255,7 @@ namespace Dune
const HostGrid& grid (std::size_t i) const
{
return multiMesh_->grid(i);
return multiMesh_[i];
}
/// Obtain the level-indexSet
......
......@@ -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())
template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshLeafIterator : public DummyIterator
{
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));
}
using DummyIterator::DummyIterator;
};
// go to first leaf entity on all grids
for (std::size_t i = 0; i < entityStacks_.size(); ++i)
initialIncrement(i);
}
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;
template <class... GV>
MultiMeshIterator (const std::vector<std::variant<GV...>>& gridViews, bool endDummy)
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())
{
for (auto const& gvs : gridViews) {
macroIterators_.push_back(std::visit([](auto const& gv) {
return gv.grid().levelGridView(0).template end<0,pitype>(); }, gvs));
this->initialIncrement();
}
// End iterator
template <class GridImp>
MultiMeshLeafIterator (tag::end_iterator, const GridImp* multiMesh)
: Super{tag::end_iterator{}, multiMesh}
{}
void initialIncrement_impl ()
{
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)
private:
std::vector<bool> incrementAllowed_;
mutable MultiEntity<HostGrid> multiEntity_;
};
template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshMasterLeafIterator : public DummyIterator
{
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;
}
}
using DummyIterator::DummyIterator;
};
// 2. if entityStack is empty, go to next macroElement
if (entityStack.empty()) {
++macroIt;
if (macroIt == macroEnd)
return;
}
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;
// 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]);
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();
}
// assert(contains_[i](child) && "No valid child element found in gridView");
}
// End iterator
template <class GridImp>
MultiMeshMasterLeafIterator (tag::end_iterator, const GridImp* multiMesh)
: Super{tag::end_iterator{}, multiMesh}
{}
/// Return true, if all stacks with size > stack[i].size are finished
bool incrementAllowed (std::size_t i) const
// 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);
// assert(contains_[i](child) && "No valid child element found in gridView");
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);
}
}
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,typename Grid::HostGrid>;
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());