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

resolved a merge conflict

parents 42349adf f1028dc2
set(modules "DuneMultimeshMacros.cmake")
install(FILES ${modules} DESTINATION ${DUNE_INSTALL_MODULEDIR})
install(FILES
DuneMultimeshMacros.cmake
CXXFeatures.cmake
DESTINATION ${DUNE_INSTALL_MODULEDIR})
include(CheckCXXSourceCompiles)
# support for C++17's variant implementation
check_cxx_source_compiles("
#include <variant>
int main()
{
std::variant<int,double> a;
a = 1;
a = 2.0;
bool positive = std::visit([](auto&& x) { return x > 0; }, a);
}
" DUNE_HAVE_CXX_VARIANT )
# File for module specific CMake tests.
include(CXXFeatures)
......@@ -40,6 +40,9 @@
/* Define to the revision of dune-multimesh */
#define DUNE_MULTIMESH_VERSION_REVISION @DUNE_MULTIMESH_VERSION_REVISION@
/* some detected compiler features may be used in this module */
#cmakedefine DUNE_HAVE_CXX_VARIANT 1
/* end dune-multimesh
Everything below here will be overwritten
*/
......@@ -12,23 +12,23 @@
namespace Dune
{
template <class GridImp>
template <class HostGrid>
class MultiEntity
: public std::vector<typename GridImp::HostGridType::Traits::template Codim<0>::Entity>
: public std::vector<typename HostGrid::Traits::template Codim<0>::Entity>
{
private:
using ctype = typename GridImp::ctype;
using ctype = typename HostGrid::ctype;
public:
enum { dimension = GridImp::dimension };
enum { dimension = HostGrid::dimension };
/// The type of a local geometry
using LocalGeometry = Dune::Geometry<dimension, dimension, const GridImp, MultiMeshLocalGeometry>;
using LocalGeometry = MultiMeshLocalGeometry<dimension, dimension, HostGrid>;
using EntitySeed = typename GridImp::Traits::template Codim<0>::EntitySeed;
using EntitySeed = MultiMeshEntitySeed<0, HostGrid>;
/// Entity in the host grid
using HostGridEntity = typename GridImp::HostGridType::Traits::template Codim<0>::Entity;
using HostGridEntity = typename HostGrid::Traits::template Codim<0>::Entity;
/// Containertype
using Super = std::vector<HostGridEntity>;
......@@ -39,15 +39,13 @@ namespace Dune
/// Return a local geometry of source in target
static LocalGeometry localGeometry (HostGridEntity const& source, HostGridEntity const& target)
{
using LocalGeometryImp = MultiMeshLocalGeometry<dimension, dimension, const GridImp>;
return LocalGeometry{LocalGeometryImp{source, target}};
return {source, target};
}
/// Return a local geometry of source_i'th entity in target_t'th entity
LocalGeometry localGeometry (std::size_t source_i, std::size_t target_i) const
{
using LocalGeometryImp = MultiMeshLocalGeometry<dimension, dimension, const GridImp>;
return LocalGeometry{LocalGeometryImp{(*this)[source_i], (*this)[target_i]}};
return {(*this)[source_i], (*this)[target_i]};
}
/// Return coordinate `sourceLocal` in coordinates of target entity
......@@ -73,8 +71,7 @@ namespace Dune
**/
EntitySeed seed (std::size_t entity_i) const
{
using EntitySeedImp = MultiMeshEntitySeed<0, const GridImp>;
return EntitySeedImp{(*this)[entity_i], entity_i};
return {(*this)[entity_i], entity_i};
}
/// Return the entity with maximal level
......
......@@ -9,23 +9,23 @@
namespace Dune
{
template <int mydim, int coorddim, class GridImp>
template <int mydim, int coorddim, class HostGrid>
class MultiMeshLocalGeometry
: public GeometryDefaultImplementation<mydim, coorddim, GridImp, MultiMeshLocalGeometry>
: public GeometryDefaultImplementation<mydim, coorddim, HostGrid, MultiMeshLocalGeometry>
{
private:
using ctype = typename GridImp::ctype;
using ctype = typename HostGrid::ctype;
public:
// The codimension of this entitypointer wrt the host grid
enum { codimension = GridImp::HostGridType::dimension - mydim };
enum { dimensionworld = GridImp::HostGridType::dimensionworld };
enum { codimension = HostGrid::dimension - mydim };
enum { dimensionworld = HostGrid::dimensionworld };
// select appropriate hostgrid geometry via typeswitch
using HostLocalGeometry = typename GridImp::HostGridType::Traits::template Codim<codimension>::LocalGeometry;
using HostLocalGeometry = typename HostGrid::Traits::template Codim<codimension>::LocalGeometry;
/// entity in the host grid
using HostGridEntity = typename GridImp::HostGridType::Traits::template Codim<codimension>::Entity;
using HostGridEntity = typename HostGrid::Traits::template Codim<codimension>::Entity;
//! type of jacobian transposed
using JacobianInverseTransposed = typename HostLocalGeometry::JacobianInverseTransposed;
......
......@@ -5,8 +5,10 @@
#include <numeric>
#include <stack>
#include <variant>
#include <dune/common/iteratorfacades.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/grid/common/exceptions.hh>
#include <dune/grid/common/gridenums.hh>
......@@ -14,10 +16,15 @@
namespace Dune
{
namespace tag
{
struct with_gridview {};
}
/** \brief Iterator over all entities of a given codimension and level of a grid.
* \ingroup MultiMesh
*/
template <int codim, PartitionIteratorType pitype, class GridImp>
template <int codim, PartitionIteratorType pitype, class HostGrid>
class MultiMeshIterator
{
public:
......@@ -35,18 +42,20 @@ namespace Dune
// Implemented for codim 0 entities only
template <PartitionIteratorType pitype, class GridImp>
class MultiMeshIterator<0, pitype, GridImp>
: public ForwardIteratorFacade<MultiMeshIterator<0,pitype,GridImp>,
MultiEntity<GridImp>,
MultiEntity<GridImp> const&>
template <PartitionIteratorType pitype, class HostGrid>
class MultiMeshIterator<0, pitype, HostGrid>
: public ForwardIteratorFacade<MultiMeshIterator<0,pitype,HostGrid>,
MultiEntity<HostGrid>,
MultiEntity<HostGrid> const&>
{
private:
// LevelIterator to the equivalent entity in the host grid
using HostGridLevelIterator =
typename GridImp::HostGridType::template Codim<0>::template Partition<pitype>::LevelIterator;
typename HostGrid::template Codim<0>::template Partition<pitype>::LevelIterator;
using HostEntity = typename GridImp::HostGridType::template Codim<0>::Entity;
using HostEntity = typename HostGrid::template Codim<0>::Entity;
using EntityTest = std::function<bool(HostEntity)>;
struct EntityStackEntry
{
......@@ -88,21 +97,23 @@ namespace Dune
public:
/// Constructor. Stores a pointer to the grid
explicit MultiMeshIterator (const GridImp* multiMesh, int level)
: multiMesh_(multiMesh)
, incrementAllowed_(multiMesh->size(), true)
, level_(level)
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, int level)
: 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_) {
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) {
entityStacks_.emplace_back((*multiMesh_)[i].maxLevel());
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);
}
}
......@@ -112,26 +123,84 @@ namespace Dune
* \param multiMesh Pointer to grid instance
* \param endDummy Here only to distinguish it from the other constructor
*/
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, int level, bool endDummy)
: multiMesh_(multiMesh)
, level_(level)
{
for (auto const& grid : multiMesh_->grids_) {
for (auto const& grid : multiMesh->grids_)
macroIterators_.push_back(grid->levelGridView(0).template end<0,pitype>());
macroEndIterators_.push_back(grid->levelGridView(0).template end<0,pitype>());
}
}
/// Constructor which create the leaf-iterator
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh)
: MultiMeshIterator{multiMesh, -1}
{}
/// Constructor which create the end leaf-iterator
template <class GridImp>
MultiMeshIterator (const GridImp* multiMesh, bool endDummy)
: MultiMeshIterator{multiMesh, -1, endDummy}
{}
template <class... GridViews,
std::enable_if_t<not Std::disjunction<std::is_same<GridViews,bool>...>::value, int> = 0>
MultiMeshIterator (tag::with_gridview, 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));
Hybrid::forEach(std::forward_as_tuple(gridViews...), [this](auto const& gv) {
contains_.emplace_back([gv](const HostEntity& entity) { return gv.contains(entity); });
});
for (std::size_t i = 0; i < sizeof...(GridViews); ++i)
initialIncrement(i);
}
template <class... GridViews>
MultiMeshIterator (tag::with_gridview, bool endDummy, GridViews const&... gridViews)
: macroIterators_{gridViews.grid().levelGridView(0).template end<0,pitype>()...}
{}
#if DUNE_HAVE_CXX_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 <class... GV>
MultiMeshIterator (const std::vector<std::variant<GV...>>& gridViews, bool endDummy)
{
for (auto const& gvs : gridViews) {
macroIterators_.push_back(std::visit([](auto const& gv) {
return gv.grid().levelGridView(0).template end<0,pitype>(); }, gvs));
}
}
#endif
/// prefix increment
void increment ()
......@@ -146,7 +215,7 @@ namespace Dune
}
/// dereferencing
MultiEntity<GridImp> const& dereference () const
MultiEntity<HostGrid> const& dereference () const
{
// update entries in multiEntity that have changed
for (std::size_t i = 0; i < entityStacks_.size(); ++i) {
......@@ -189,10 +258,10 @@ namespace Dune
}
// 3. go down in tree until leaf entity
for (auto child = dereference(i); !entityTest(child);
for (auto child = dereference(i); !entityTest(i,child);
child = dereference(i)) {
entityStack.emplace(child);
assert( entityStack.size() <= (*multiMesh_)[i].maxLevel() );
assert( entityStack.size() <= maxLevel_[i] );
}
}
......@@ -218,10 +287,10 @@ namespace Dune
return;
// 2. go down in tree until leaf entity
for (auto child = dereference(i); !entityTest(child);
for (auto child = dereference(i); !entityTest(i,child);
child = dereference(i)) {
entityStack.emplace(child);
assert( entityStack.size() <= (*multiMesh_)[i].maxLevel() );
assert( entityStack.size() <= maxLevel_[i] );
}
}
......@@ -236,24 +305,35 @@ namespace Dune
}
}
bool entityTest (HostEntity const& entity)
bool entityTest (std::size_t i, HostEntity const& entity) const
{
return entity.level() == level_ || entity.isLeaf() || !entity.isRegular();
return contains_[i](entity) || entity.isLeaf() || !entity.isRegular();
}
private:
const GridImp* multiMesh_;
std::vector<bool> incrementAllowed_;
std::vector<EntityTest> contains_;
std::vector<int> maxLevel_;
mutable MultiEntity<HostGrid> multiEntity_;
std::vector<HostGridLevelIterator> macroIterators_;
std::vector<HostGridLevelIterator> macroEndIterators_;
std::vector<EntityStack> entityStacks_;
std::vector<bool> incrementAllowed_;
int level_ = -1;
mutable MultiEntity<GridImp> multiEntity_;
};
template <class> class MultiMesh;
template <class... GridViews>
inline auto multi_elements(GridViews const&... gridViews)
{
using GridView0 = std::tuple_element_t<0,std::tuple<GridViews...>>;
using Iterator = MultiMeshIterator<0,All_Partition,typename GridView0::Grid>;
using Range = IteratorRange<Iterator>;
return Range{ Iterator{tag::with_gridview{}, gridViews...},
Iterator{tag::with_gridview{}, true, gridViews...} };
}
} // end namespace Dune
#endif // DUNE_MULTIMESH_ITERATOR_HH
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_MULTI_GRIDVIEW_HH
#define DUNE_MULTI_GRIDVIEW_HH
#if ! DUNE_HAVE_CXX_VARIANT
#error "Require C++17 variant!"
#endif
#include <variant>
#include <dune/common/typetraits.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/grid/common/capabilities.hh>
#include <dune/grid/common/gridview.hh>
#include "mmiterator.hh"
#include "multiindexset.hh"
namespace Dune
{
// forward declaration
template <class HostGrid>
class MultiGridView;
template <class HostGrid>
struct MultiGridViewTraits
{
using Grid = typename std::remove_const<HostGrid>::type;
using IndexSet = MultiIndexSet<HostGrid>;
using Intersection = std::variant<
typename HostGrid::Traits::LeafIntersection, typename HostGrid::Traits::LevelIntersection>;
using IntersectionIterator = std::variant<
typename HostGrid::Traits::LeafIntersectionIterator, typename HostGrid::Traits::LevelIntersectionIterator>;
using CollectiveCommunication = typename HostGrid::Traits::CollectiveCommunication;
template <int cd>
struct Codim
{
using Entity = typename Grid::Traits::template Codim<cd>::Entity;
using Geometry = typename Grid::template Codim<cd>::Geometry;
using LocalGeometry = typename Grid::template Codim<cd>::LocalGeometry;
template <PartitionIteratorType pit>
struct Partition
{
using Iterator = MultiMeshIterator<cd,pit,HostGrid>;
};
};
enum { conforming = Capabilities::isLevelwiseConforming<HostGrid>::v };
};
template <class HostGrid>
class MultiGridView
{
public:
using Traits = MultiGridViewTraits<HostGrid>;
/// The MultiMesh GridType
using Grid = typename Traits::Grid;
using GridViewTypes = std::variant<typename HostGrid::LeafGridView, typename HostGrid::LevelGridView>;
using IndexSet = typename Traits::IndexSet;
using IndexSetTypes = typename IndexSet::IndexSetTypes;
using IntersectionIterator = typename Traits::IntersectionIterator;
using CollectiveCommunication = typename Traits::CollectiveCommunication;
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> >;
template <int cd>
struct Codim : public Traits::template Codim<cd> {};
enum { dimension = HostGrid::dimension };
enum { dimensionworld = HostGrid::dimensionworld };
enum { conforming = Traits::conforming };
public:
/// Constructor.
template <class... GridViews,
std::enable_if_t<Std::conjunction<IsGridView<GridViews>...>::value, int> = 0>
MultiGridView (GridViews&&... gridViews)
: gridViews_{std::forward<GridViews>(gridViews)...}
{}
template <class GridView,
std::enable_if_t<IsGridView<GridView>::value, int> = 0>
MultiGridView (const std::vector<GridView>& gridViews)
: gridViews_(gridViews.begin(), gridViews.end())
{}
template <class Iter,
std::enable_if_t<IsGridView<typename std::iterator_traits<Iter>::value_type>::value, int> = 0>
MultiGridView (Iter first, Iter last)
: gridViews_(first, last)
{}
template <class Iter,
std::enable_if_t<IsGridView<typename std::iterator_traits<Iter>::value_type>::value, int> = 0>
MultiGridView (const IteratorRange<Iter>& gridViews)
: gridViews_(gridViews.begin(), gridViews.end())
{}
/// Obtain a const reference to the underlying hierarchic grid
const HostGrid& grid (std::size_t idx) const
{
return std::visit([](auto const& gv) { return gv.grid(); }, gridViews_[idx]);
}
/// Obtain the level-indexSet
// NOTE: IndexSet is one of {LeafIndexSet, LevelIndexSet}
// NOTE: do not return a reference, but a reference wrapper
IndexSet indexSet (std::size_t idx) const
{
return std::visit([](auto const& gv) -> IndexSetTypes { return &gv.indexSet(); }, gridViews_[idx]);
}
/// Obtain number of entities in a given codimension
int size (std::size_t idx, int codim) const
{
return std::visit([codim](auto const& gv) { return gv.size(codim); }, gridViews_[idx]);
}
/// Obtain number of entities with a given geometry type
int size (std::size_t idx, const GeometryType& type) const
{
return std::visit([&type](auto const& gv) { return gv.size(type); }, gridViews_[idx]);
}
/// Obtain begin iterator for this view
template <int cd, PartitionIteratorType pit = All_Partition>
typename Codim<cd>::template Partition<pit>::Iterator begin () const
{
static_assert(cd == 0, "Implemented for codim == 0 only");
return MultiMeshIterator<cd,pit,HostGrid>(gridViews_);
}
/// Obtain end iterator for this view
template <int cd, PartitionIteratorType pit = All_Partition>
typename Codim<cd>::template Partition<pit>::Iterator end () const
{
static_assert(cd == 0, "Implemented for codim == 0 only");
return MultiMeshIterator<cd,pit,HostGrid>(gridViews_, true);
}
/// Obtain begin intersection iterator with respect to this view
// NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator}
IntersectionIterator ibegin (std::size_t idx, const typename Codim<0>::Entity& entity) const
{
using II = IntersectionIterator;
return std::visit([&entity](auto const& gv) -> II { return gv.ibegin(entity); }, gridViews_[idx]);
}
/// Obtain end intersection iterator with respect to this view
// NOTE: IntersectionIterator is one of {LeafIntersectionIterator, LevelIntersectionIterator}
IntersectionIterator iend (std::size_t idx, const typename Codim<0>::Entity& entity) const
{
using II = IntersectionIterator;
return std::visit([&entity](auto const& gv) -> II { return gv.iend(entity); }, gridViews_[idx]);
}
/// Obtain collective communication object
const CollectiveCommunication& comm (std::size_t idx) const
{
return std::visit([](auto const& gv) -> const auto& { return gv.comm(); }, gridViews_[idx]);
}
/// Return size of the overlap region for a given codim on the grid view.
int overlapSize (std::size_t idx, int codim) const
{
return std::visit([codim](auto const& gv) { return gv.overlapSize(codim); }, gridViews_[idx]);
}
/// Return size of the ghost region for a given codim on the grid view.
int ghostSize (std::size_t idx, int codim) const
{
return std::visit([codim](auto const& gv) { return gv.ghostSize(codim); }, gridViews_[idx]);
}
/// Communicate data on this view
template <class DataHandleImp, class DataType>
void communicate (std::size_t idx,
CommDataHandleIF<DataHandleImp, DataType>& data,
InterfaceType iftype,
CommunicationDirection dir) const
{
std::visit([&data,iftype,dir](auto const& gv) { gv.communicate(data,iftype,dir); }, gridViews_[idx]);
}
private:
std::vector<GridViewTypes> gridViews_;
};
} // end namespace Dune
#endif // DUNE_MULTI_GRIDVIEW_HH
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_MULTI_INDEXSET_HH
#define DUNE_MULTI_INDEXSET_HH
#if ! DUNE_HAVE_CXX_VARIANT
#error "Require C++17 variant!"
#endif
#include <type_traits>
#include <variant>
#include <dune/common/typetraits.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/std/type_traits.hh>
#include <dune/grid/common/indexidset.hh>
namespace Dune
{
// forward declaration
template <class HostGrid>
class MultiGridView;
template <class HostGrid>
class MultiIndexSet
{
private:
using LeafIndexSet = typename HostGrid::Traits::LeafIndexSet;
using LevelIndexSet = typename HostGrid::Traits::LevelIndexSet;
using IndexSetTypes = std::variant<LeafIndexSet const*, LevelIndexSet const*>;
friend class MultiGridView<HostGrid>;
public:
using IndexType = typename LeafIndexSet::IndexType;
using Types = typename LeafIndexSet::Types;
static const int dimension = LeafIndexSet::dimension;
public:
template <class IndexSet>
MultiIndexSet (IndexSet const* indexSet)
: indexSets_(indexSet)
{}
MultiIndexSet (IndexSetTypes const& indexSet)
: indexSets_(indexSet)
{}
/// Map entity to index.
template <class Entity>
IndexType index (const Entity& e) const
{
return std::visit([&e](auto const* is) { return is->index(e); }, indexSets_);
}
/// Map entity to index.
template <int cc>
IndexType index (const typename LeafIndexSet::Traits::template Codim<cc>::Entity& e) const
{
return std::visit([&e](auto const* is) { return is->template index<cc>(e); }, indexSets_);
}
/// Map a subentity to an index.
template <class Entity>
IndexType subIndex (const Entity& e, int i, unsigned int codim) const
{
return std::visit([&e,i,codim](auto const* is) { return is->subIndex(e,i,codim); }, indexSets_);
}
/// Map a subentity to an index.
template <int cc>
IndexType subIndex (const typename LeafIndexSet::Traits::template Codim<cc>::Entity& e,
int i, unsigned int codim) const
{
return std::visit([&e,i,codim](auto const* is) { return is->template subIndex<cc>(e,i,codim); }, indexSets_);
}
/// Obtain all geometry types of entities in domain
Types types (int codim) const
{
return std::visit([codim](auto const* is) { return is->types(codim); }, indexSets_);
}
/// Return total number of entities of given geometry type in entity set \f$E\f$.
IndexType size (GeometryType type) const
{
return std::visit([&type](auto const* is) { return is->size(type); }, indexSets_);
}
/// Return total number of entities of given codim in the entity set \f$E\f$. This
/// is simply a sum over all geometry types.
IndexType size (int codim) const
{
return std::visit([codim](auto const* is) { return is->size(codim); }, indexSets_);
}
/// Return true if the given entity is contained in \f$E\f$.
template <class Entity>
bool contains (const Entity& e) const
{
return std::visit([&e](auto const* is) { return is->contains(e); }, indexSets_);
}
private:
IndexSetTypes indexSets_;
};
} // end namespace Dune
#endif // DUNE_MULTI_INDEXSET_HH
......@@ -46,11 +46,11 @@ namespace Dune
{
/// The type of the iterator over the level entities of this codim on this partition.