Commit 0af88a98 authored by Praetorius, Simon's avatar Praetorius, Simon

Merge branch 'feature/interpolation' into 'master'

Feature/interpolation

See merge request !5
parents 31f111d0 c7def655
Pipeline #1495 passed with stage
in 10 minutes and 11 seconds
---
before_script:
- source ~/toolchain
- export CMAKE_FLAGS="-DCMAKE_C_COMPILER='$CC' -DCMAKE_CXX_COMPILER='$CXX'"
dune-2.6 gcc-6-14:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:2.6-debian-9-gcc-6-14
script: duneci-standard-test
dune-2.6 gcc-8-17:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:2.6-debian-10-gcc-8-17
script: duneci-standard-test
dune-2.6 clang-6-17:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:2.6-debian-10-clang-6-libcpp-17
script: duneci-standard-test
dune-git gcc-7-14:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:git-debian-10-gcc-7-14
script: duneci-standard-test
dune-git gcc-8-17:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:git-debian-10-gcc-8-noassert-17
script: duneci-standard-test
dune-git clang-6-17:
image: registry.dune-project.org/docker/ci/dune-pdelab-deps:git-debian-10-clang-6-libcpp-17
script: duneci-standard-test
\ No newline at end of file
...@@ -7,5 +7,5 @@ Module: dune-multimesh ...@@ -7,5 +7,5 @@ Module: dune-multimesh
Version: 0.1 Version: 0.1
Maintainer: simon.praetorius@tu-dresden.de Maintainer: simon.praetorius@tu-dresden.de
#depending on #depending on
Depends: dune-common dune-grid Depends: dune-grid
Suggests: dune-uggrid dune-alugrid dune-foamgrid dune-functions dune-geometry dune-istl Suggests: dune-alugrid dune-foamgrid dune-functions dune-istl dune-spgrid dune-uggrid
...@@ -19,20 +19,21 @@ namespace Dune ...@@ -19,20 +19,21 @@ namespace Dune
private: private:
using ctype = typename HostGrid::ctype; using ctype = typename HostGrid::ctype;
/// Entity in the host grid
using HostGridEntity = typename HostGrid::Traits::template Codim<0>::Entity;
public: public:
enum { dimension = HostGrid::dimension }; enum { codimension = 0 };
enum { dimension = HostGridEntity::dimension };
enum { mydimension = HostGridEntity::mydimension };
/// The type of a local geometry /// The type of a local geometry
using LocalGeometry = MultiMeshLocalGeometry<dimension, dimension, HostGrid>; using LocalGeometry = MultiMeshLocalGeometry<dimension, dimension, HostGrid>;
using EntitySeed = MultiMeshEntitySeed<0, HostGrid>; /// Seed representing the vector of entities in the MultiMesh
using EntitySeed = MultiEntitySeed<0, HostGrid>;
/// Entity in the host grid
using HostGridEntity = typename HostGrid::Traits::template Codim<0>::Entity;
/// Containertype
using Super = std::vector<HostGridEntity>;
public:
/// Constructor from std::vector /// Constructor from std::vector
using std::vector<HostGridEntity>::vector; using std::vector<HostGridEntity>::vector;
...@@ -62,6 +63,39 @@ namespace Dune ...@@ -62,6 +63,39 @@ namespace Dune
return localGeometry(source, target).global(sourceLocal); return localGeometry(source, target).global(sourceLocal);
} }
/// Return the partitionType of any entity in the multiEntity
// [[ expects: all partitionType are the same ]]
PartitionType partitionType () const
{
return max().partitionType();
}
/// Return the geometry of the entity with maximal level
typename HostGridEntity::Geometry geometry () const
{
return max().geometry();
}
/// Return the type of the entity with maximal level
GeometryType type () const
{
return max().type();
}
/// The entities are always regular, since irregular entities are not allowed in multimesh
bool isRegular() const { return true; }
/// Return the maximal level
int level () const
{
return max().level();
}
/// Return whether the entity with minimal level has boundary intersections
bool hasBoundaryIntersections () const
{
return min().hasBoundaryIntersections();
}
/// \brief Return the entity seed which contains sufficient information /// \brief Return the entity seed which contains sufficient information
/// to generate the entity again and uses as little memory as possible. /// to generate the entity again and uses as little memory as possible.
...@@ -69,9 +103,15 @@ namespace Dune ...@@ -69,9 +103,15 @@ namespace Dune
* The MultiMeshEntitySeed contains the HostGridEntitySeed and the index of * The MultiMeshEntitySeed contains the HostGridEntitySeed and the index of
* the grid it is extracted from. * the grid it is extracted from.
**/ **/
EntitySeed seed (std::size_t entity_i) const MultiMeshEntitySeed<0,HostGrid> seed (std::size_t idx) const
{
return {(*this)[idx], idx};
}
/// Return an entity seed to restore the multi-entity.
EntitySeed seed () const
{ {
return {(*this)[entity_i], entity_i}; return {*this};
} }
/// Return the entity with maximal level /// Return the entity with maximal level
......
...@@ -10,16 +10,16 @@ namespace Dune ...@@ -10,16 +10,16 @@ namespace Dune
* \ingroup MultiMesh * \ingroup MultiMesh
* *
*/ */
template <int codim, class GridImp> template <int codim, class HostGrid>
class MultiMeshEntitySeed class MultiMeshEntitySeed
{ {
protected: protected:
/// Entity type of the hostgrid /// Entity type of the hostgrid
typedef typename GridImp::HostGridType::Traits::template Codim<codim>::Entity HostEntity; using HostEntity = typename HostGrid::Traits::template Codim<codim>::Entity;
/// EntitySeed type of the hostgrid /// EntitySeed type of the hostgrid
typedef typename GridImp::HostGridType::Traits::template Codim<codim>::EntitySeed HostEntitySeed; using HostEntitySeed = typename HostGrid::Traits::template Codim<codim>::EntitySeed;
public: public:
enum { codimension = codim }; enum { codimension = codim };
...@@ -61,6 +61,55 @@ namespace Dune ...@@ -61,6 +61,55 @@ namespace Dune
std::size_t gridIdx_; std::size_t gridIdx_;
}; };
template <class HG>
class MultiEntity;
// An entity seed for a vector of entities
template <int codim, class HostGrid>
class MultiEntitySeed
{
protected:
/// Entity type of the hostgrid
using HostEntity = typename HostGrid::Traits::template Codim<codim>::Entity;
/// EntitySeed type of the hostgrid
using HostEntitySeed = typename HostGrid::Traits::template Codim<codim>::EntitySeed;
public:
enum { codimension = codim };
/// Construct an empty (i.e. isValid() == false) seed.
MultiEntitySeed()
{}
/// \brief Create EntitySeed from hostgrid Entity
template <class MultiEntity>
MultiEntitySeed (const MultiEntity& multiEntity)
{
for (auto const& e : multiEntity)
hostEntitySeeds_.emplace_back(e.seed());
}
/// Get stored HostEntitySeed
const std::vector<HostEntitySeed>& hostEntitySeeds () const
{
return hostEntitySeeds_;
}
/// Check whether it is safe to create an Entity from this Seed
bool isValid () const
{
return hostEntitySeeds_.empty() ? false :
std::all_of(hostEntitySeeds_.begin(), hostEntitySeeds_.end(),
[](auto const& seed) { return seed.isValid(); });
}
private:
std::vector<HostEntitySeed> hostEntitySeeds_;
};
} // end namespace Dune } // end namespace Dune
#endif // DUNE_MULTIMESH_ENTITYSEED_HH #endif // DUNE_MULTIMESH_ENTITYSEED_HH
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <vector> #include <vector>
#include <dune/common/hybridutilities.hh> #include <dune/common/hybridutilities.hh>
#include <dune/common/to_unique_ptr.hh>
#include <dune/common/version.hh>
#include <dune/common/std/type_traits.hh> #include <dune/common/std/type_traits.hh>
#include <dune/grid/common/gridfactory.hh> #include <dune/grid/common/gridfactory.hh>
...@@ -147,6 +149,7 @@ namespace Dune ...@@ -147,6 +149,7 @@ namespace Dune
* Create n copies of the grid and store it in unique_pointers * Create n copies of the grid and store it in unique_pointers
* inside the multimesh grid. * inside the multimesh grid.
**/ **/
#if DUNE_VERSION_LT(DUNE_GRID,2,7)
virtual Grid* createGrid () override virtual Grid* createGrid () override
{ {
Grid* multimesh = new Grid{}; Grid* multimesh = new Grid{};
...@@ -154,6 +157,15 @@ namespace Dune ...@@ -154,6 +157,15 @@ namespace Dune
multimesh->grids_.emplace_back(gridFactory->createGrid()); multimesh->grids_.emplace_back(gridFactory->createGrid());
return multimesh; return multimesh;
} }
#else
virtual ToUniquePtr<Grid> createGrid () override
{
auto multimesh = makeToUnique<Grid>();
for (auto& gridFactory : gridFactories_)
multimesh->grids_.emplace_back(gridFactory->createGrid());
return std::move(multimesh);
}
#endif
private: private:
std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_; std::vector<std::unique_ptr<GridFactory<HostGrid>>> gridFactories_;
......
...@@ -56,7 +56,7 @@ namespace Dune ...@@ -56,7 +56,7 @@ namespace Dune
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;
...@@ -84,7 +84,7 @@ namespace Dune ...@@ -84,7 +84,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
...@@ -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_[i]; return (*multiMesh_)[i];
} }
/// Obtain the level-indexSet /// Obtain the level-indexSet
......
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
#include <numeric> #include <numeric>
#include <stack> #include <stack>
#include <variant>
#include <dune/common/iteratorfacades.hh> #include <dune/common/iteratorfacades.hh>
#include <dune/common/iteratorrange.hh>
#include <dune/common/std/type_traits.hh> #include <dune/common/std/type_traits.hh>
#include <dune/grid/common/gridenums.hh>
namespace Dune namespace Dune
{ {
...@@ -30,7 +31,8 @@ namespace Dune ...@@ -30,7 +31,8 @@ namespace Dune
struct EntityStackEntry struct EntityStackEntry
{ {
template <class Entity> template <class Entity,
std::enable_if_t<std::is_same<std::decay_t<Entity>, HostEntity>::value, int> = 0>
explicit EntityStackEntry (Entity&& entity) explicit EntityStackEntry (Entity&& entity)
: it(entity.hbegin(entity.level()+1)) : it(entity.hbegin(entity.level()+1))
, end(entity.hend(entity.level()+1)) , end(entity.hend(entity.level()+1))
...@@ -117,11 +119,17 @@ namespace Dune ...@@ -117,11 +119,17 @@ namespace Dune
// 3. go down in tree until leaf entity // 3. go down in tree until leaf entity
auto child = dereference(); auto child = dereference();
for (; !(contains_(child) || child.isLeaf()); child = dereference()) { for (; !(contains_(child) || child.isLeaf()); child = dereference()) {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal");
entityStack_.emplace(child); entityStack_.emplace(child);
assert( entityStack_.size() <= maxLevel_ ); assert( entityStack_.size() <= maxLevel_ );
} }
// 4. go up in tree again to the first regular entity, since
// irregular element can not be traversed in a multi-mesh sense
while (!child.isRegular() && !entityStack_.empty()) {
entityStack_.pop();
child = dereference();
}
assert(contains_(child) && "No valid child element found in gridView"); assert(contains_(child) && "No valid child element found in gridView");
} }
...@@ -150,11 +158,17 @@ namespace Dune ...@@ -150,11 +158,17 @@ namespace Dune
// 1. go down in tree until leaf entity // 1. go down in tree until leaf entity
auto child = dereference(); auto child = dereference();
for (; !(contains_(child) || child.isLeaf()); child = dereference()) { for (; !(contains_(child) || child.isLeaf()); child = dereference()) {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal");
entityStack_.emplace(child); entityStack_.emplace(child);
assert( entityStack_.size() <= maxLevel_ ); assert( entityStack_.size() <= maxLevel_ );
} }
// 2. go up in tree again to the first regular entity, since
// irregular element can not be traversed in a multi-mesh sense
while (!child.isRegular() && !entityStack_.empty()) {
entityStack_.pop();
child = dereference();
}
assert(contains_(child) && "No valid child element found in gridView"); assert(contains_(child) && "No valid child element found in gridView");
} }
...@@ -167,7 +181,7 @@ namespace Dune ...@@ -167,7 +181,7 @@ namespace Dune
}; };
template <class Entity, class GridView> template <class Entity, class GridView>
inline auto childs(const Entity& entity, const GridView& gridView) inline auto childs (const Entity& entity, const GridView& gridView)
{ {
using Iterator = MultiMeshHierarchicIterator<typename GridView::Grid>; using Iterator = MultiMeshHierarchicIterator<typename GridView::Grid>;
return IteratorRange<Iterator>{ Iterator{entity, gridView}, Iterator{true} }; return IteratorRange<Iterator>{ Iterator{entity, gridView}, Iterator{true} };
......
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include <numeric> #include <numeric>
#include <stack> #include <stack>
#include <type_traits> #include <type_traits>
#if DUNE_HAVE_CXX_VARIANT
#include <variant>
#endif
#include <dune/common/std/type_traits.hh> #include <dune/common/std/type_traits.hh>
#include <dune/grid/common/gridenums.hh> #include <dune/grid/common/gridenums.hh>
...@@ -55,8 +58,8 @@ namespace Dune ...@@ -55,8 +58,8 @@ namespace Dune
// go to first leaf entity on all grids // go to first leaf entity on all grids
entityStacks_.reserve(multiMesh->size()); entityStacks_.reserve(multiMesh->size());
for (std::size_t i = 0; i < multiMesh->size(); ++i) { for (std::size_t i = 0; i < multiMesh->size(); ++i) {
maxLevel_[i] = (*multiMesh)[i].maxLevel(); maxLevel_[i] = multiMesh->maxLevel(i);
entityStacks_.emplace_back((*multiMesh)[i].maxLevel()); entityStacks_.emplace_back(multiMesh->maxLevel(i));
} }
} }
...@@ -152,13 +155,18 @@ namespace Dune ...@@ -152,13 +155,18 @@ namespace Dune
// 3. go down in tree until leaf entity // 3. go down in tree until leaf entity
auto child = dereference(i); auto child = dereference(i);
for (; !this->levelReached(i, child); child = dereference(i)) { for (; !this->levelReached(i, child); child = dereference(i)) {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal");
entityStack.emplace(child); entityStack.emplace(child);
assert(int(entityStack.size()) <= maxLevel_[i]); assert(int(entityStack.size()) <= maxLevel_[i]);
} }
// 4. go up in tree again to the first regular entity, since
// irregular element can not be traversed in a multi-mesh sense
while (!child.isRegular() && !entityStack.empty()) {
entityStack.pop();
child = dereference(i);
}
return entityStack.size(); return entityStack.size();
// assert(contains_[i](child) && "No valid child element found in gridView");
} }
using Super::increment; using Super::increment;
...@@ -167,12 +175,12 @@ namespace Dune ...@@ -167,12 +175,12 @@ namespace Dune
{ {
std::size_t size = entityStacks_[i].size(); std::size_t size = entityStacks_[i].size();
return std::accumulate(entityStacks_.begin(), entityStacks_.end(), true, return std::accumulate(entityStacks_.begin(), entityStacks_.end(), true,
[i,size](bool allowed, auto const& entityStack) { [size](bool allowed, auto const& entityStack) {
return allowed && (entityStack.size() <= size || entityStack.finished(size)); return allowed && (entityStack.size() <= size || entityStack.finished(size));
}); });
} }
// got to first leaf entity on grid i // go to first entity on grid i on the desired level
int initialIncrement (std::size_t i) int initialIncrement (std::size_t i)
{ {
auto& entityStack = entityStacks_[i]; auto& entityStack = entityStacks_[i];
...@@ -186,16 +194,22 @@ namespace Dune ...@@ -186,16 +194,22 @@ namespace Dune
// 1. go down in tree until desired level is reached // 1. go down in tree until desired level is reached
auto child = dereference(i); auto child = dereference(i);
for (; !this->levelReached(i, child); child = dereference(i)) { for (; !this->levelReached(i, child); child = dereference(i)) {
assert(child.isRegular() && "No irregular elements allowed in multi-mesh traversal");
entityStack.emplace(child); entityStack.emplace(child);
assert(int(entityStack.size()) <= maxLevel_[i]); assert(int(entityStack.size()) <= maxLevel_[i]);
} }
// 2. go up in tree again to the first regular entity, since
// irregular element can not be traversed in a multi-mesh sense
while (!child.isRegular() && !entityStack.empty()) {
entityStack.pop();
child = dereference(i);
}
return entityStack.size(); return entityStack.size();
// assert(contains_[i](child) && "No valid child element found in gridView");
} }
using Super::initialIncrement; using Super::initialIncrement;
// Return the current entity the hierarchic iterator or macro iterator pointing to
HostEntity dereference (std::size_t i) const HostEntity dereference (std::size_t i) const
{ {
if (entityStacks_[i].empty()) { if (entityStacks_[i].empty()) {
......
...@@ -97,6 +97,8 @@ namespace Dune ...@@ -97,6 +97,8 @@ namespace Dune
using Super = GridDefaultImplementation<HG::dimension, HG::dimensionworld, using Super = GridDefaultImplementation<HG::dimension, HG::dimensionworld,
typename HG::ctype, MultiMeshFamily<HG> >; typename HG::ctype, MultiMeshFamily<HG> >;
using Self = MultiMesh;
public: public:
using HostGrid = HG; using HostGrid = HG;
...@@ -109,6 +111,8 @@ namespace Dune ...@@ -109,6 +111,8 @@ namespace Dune
/// The type used to store coordinates, inherited from the HostGrid /// The type used to store coordinates, inherited from the HostGrid
using ctype = typename HostGrid::ctype; using ctype = typename HostGrid::ctype;
enum { dimension = HostGrid::dimension };
enum { dimensionworld = HostGrid::dimensionworld };
/// \brief Constructor, stores n copies of the hostgrid /// \brief Constructor, stores n copies of the hostgrid
/** /**
...@@ -127,7 +131,7 @@ namespace Dune ...@@ -127,7 +131,7 @@ namespace Dune
MultiMesh () = default; MultiMesh () = default;
/// Return the number of grids handled by this MultiMesh /// Return the number of grids handled by this MultiMesh
std::size_t size() const std::size_t size () const
{ {
return grids_.size(); return grids_.size();
} }
...@@ -157,6 +161,11 @@ namespace Dune ...@@ -157,6 +161,11 @@ namespace Dune
[](int level, auto const& grid) { return std::max(level, grid->maxLevel()); }); [](int level, auto const& grid) { return std::max(level, grid->maxLevel()); });
} }
/// Return maximum level in the `idx`th grid
int maxLevel (std::size_t idx) const
{
return grids_[idx]->maxLevel();
}
/// Iterator to first entity of given codim on level /// Iterator to first entity of given codim on level
template <int codim, PartitionIteratorType PiType = All_Partition> template <int codim, PartitionIteratorType PiType = All_Partition>
...@@ -303,12 +312,23 @@ namespace Dune ...@@ -303,12 +312,23 @@ namespace Dune
/// Create Entity from EntitySeed /// Create Entity from EntitySeed
template <class EntitySeed> template <class EntitySeed>
typename Traits::template Codim<EntitySeed::codimension>::Entity typename Traits::template Codim<EntitySeed::codimension>::Entity
entity(const EntitySeed& seed) const entity (const EntitySeed& seed) const
{ {
std::size_t gridIdx = this->getRealImplementation(seed).gridIndex(); std::size_t gridIdx = this->getRealImplementation(seed).gridIndex();
return grids_[gridIdx]->entity(this->getRealImplementation(seed).hostEntitySeed()); return grids_[gridIdx]->entity(this->getRealImplementation(seed).hostEntitySeed());
} }
/// Create a MultiEntity from a MultiEntitySeed
template <int codim>
MultiEntity<HostGrid> entity (const MultiEntitySeed<codim, Self>& seed) const
{
assert(seed.isValid());
MultiEntity<HostGrid> multiEntity;
auto const& hostEntitySeeds = seed.hostEntitySeeds();
for (std::size_t i = 0; i < hostEntitySeeds.size(); ++i)
multiEntity.emplace_back(grids_[i]->entity(hostEntitySeeds[i]));
return multiEntity;
}
/** @name Grid Refinement Methods */ /** @name Grid Refinement Methods */
/** @{ */ /** @{ */
...@@ -320,6 +340,24 @@ namespace Dune ...@@ -320,6 +340,24 @@ namespace Dune
grid->globalRefine(refCount); grid->globalRefine(refCount);
} }
/// Mark all entities in a multiEntitity for refinement or coarsening
bool mark (int refCount, const MultiEntity<HostGrid>& entities)
{
bool b = false;
for (std::size_t i = 0; i < grids_.size(); ++i)
b = grids_[i]->mark(refCount, entities[i]) || b;
return b;
}
/// Return the marks of the the entities in a multiEntity
std::vector<int> getMark (const MultiEntity<HostGrid>& entities) const
{
std::vector<int> marks(grids_.size());
for (std::size_t i = 0; i < grids_.size(); ++i)
marks[i] = grids_[i]->getMark(entities[i]);
return marks;
}
/// Returns true, if at least one entity is marked for adaption in any of the /// Returns true, if at least one entity is marked for adaption in any of the
/// handled grids /// handled grids
bool preAdapt() bool preAdapt()
...@@ -344,29 +382,39 @@ namespace Dune ...@@ -344,29 +382,39 @@ namespace Dune
/** @} */ /** @} */
/** @name Grid Parallelization Methods */
/** @{ */
/// Size of the overlap on the leaf level /// Size of the overlap on the leaf level
unsigned int overlapSize (int codim) const unsigned int overlapSize (int codim) const
{ {
return 0u; // TODO: implement return std::accumulate(grids_.begin(), grids_.end(), 0u,
[codim](unsigned int overlap, auto const& grid) {
return std::max(overlap, grid->overlapSize(codim)); });
} }
/// Size of the ghost cell layer on the leaf level /// Size of the ghost cell layer on the leaf level
unsigned int ghostSize (int codim) const unsigned int ghostSize (int codim) const
{ {
return 0u; // TODO: implement return std::accumulate(grids_.begin(), grids_.end(), 0u,
[codim](unsigned int ghost, auto const& grid) {
return std::max(ghost, grid->ghostSize(codim)); });
} }
/// Size of the overlap on a given level /// Size of the overlap on a given level
unsigned int overlapSize (int level, int codim) const unsigned int overlapSize (int level, int codim) const
{ {
return 0u; // TODO: implement return std::accumulate(grids_.begin(), grids_.end(), 0u,
[level,codim](unsigned int overlap, auto const& grid) {
return std::max(overlap, grid->overlapSize(level,codim)); });
} }
/// Size of the ghost cell layer on a given level /// Size of the ghost cell layer on a given level
unsigned int ghostSize (int level, int codim) const unsigned int ghostSize (int level, int codim) const
{ {
return 0u; // TODO: implement return std::accumulate(grids_.begin(), grids_.end(), 0u,
[level,codim](unsigned int ghost, auto const& grid) {
return std::max(ghost, grid->ghostSize(level,codim)); });
} }
/// dummy collective communication /// dummy collective communication
...@@ -376,6 +424,22 @@ namespace Dune ...@@ -376,6 +424,22 @@ namespace Dune
return comm(0); return comm(0);
} }