Skip to content
Snippets Groups Projects
Commit 499eda34 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

update UniqueBorderPartition to support UGGrid

parent d7694d6a
No related branches found
No related tags found
No related merge requests found
...@@ -83,18 +83,20 @@ void ISTLCommunication<Basis> ...@@ -83,18 +83,20 @@ void ISTLCommunication<Basis>
auto const& gv = basis.gridView(); auto const& gv = basis.gridView();
// make disjoint partition of border entities // make disjoint partition of border entities
EntitySet borderEntities; using DataHandle = UniqueBorderPartition<Grid>;
using DataHandle = UniqueBorderPartitionDataHandle<Grid>; DataHandle borderEntities(gv.comm().rank(), gv.grid());
DataHandle handle(gv.comm().rank(), borderEntities, gv.grid().globalIdSet()); for (int i = 0; i < borderEntities.numIterations(); ++i) {
gv.communicate(handle, gv.communicate(borderEntities,
Dune::InterfaceType::InteriorBorder_InteriorBorder_Interface, Dune::InterfaceType::InteriorBorder_All_Interface,
Dune::CommunicationDirection::ForwardCommunication); Dune::CommunicationDirection::ForwardCommunication);
}
if (gv.overlapSize(0) + gv.ghostSize(0) == 0) if (gv.overlapSize(0) + gv.ghostSize(0) == 0)
// TODO(FM): Add support for this special case // TODO(FM): Add support for this special case
error_exit("Using grids with ghostSize(0) + overlapSize(0) == 0 is not supported\n"); error_exit("Using grids with ghostSize(0) + overlapSize(0) == 0 is not supported\n");
auto lv = basis.localView(); auto lv = basis.localView();
std::vector<bool> visited(basis.dimension(), false);
GlobalBasisIdSet<Basis> dofIdSet(basis); GlobalBasisIdSet<Basis> dofIdSet(basis);
pis.beginResize(); pis.beginResize();
...@@ -104,28 +106,34 @@ void ISTLCommunication<Basis> ...@@ -104,28 +106,34 @@ void ISTLCommunication<Basis>
dofIdSet.bind(e); dofIdSet.bind(e);
for (std::size_t i = 0; i < dofIdSet.size(); ++i) for (std::size_t i = 0; i < dofIdSet.size(); ++i)
{ {
LocalCommIdType localId = lv.index(i); LocalCommIdType localIndex = lv.index(i);
GlobalCommIdType globalId = dofIdSet.id(i); if (!visited[localIndex]) {
PType attribute = dofIdSet.partitionType(i); GlobalCommIdType globalId = dofIdSet.id(i);
switch (attribute) PType attribute = dofIdSet.partitionType(i);
{ switch (attribute)
case PType::InteriorEntity: {
pis.add(globalId, LI(localId, Attribute::owner, true)); case PType::InteriorEntity:
break; pis.add(globalId, LI(localIndex, Attribute::owner, true));
case PType::BorderEntity: break;
// mark border entity as owned iff it is part of the process's borderEntities set case PType::BorderEntity:
if (borderEntities.count(dofIdSet.entityId(i)) == 1) // mark border entity as owned iff it is part of the process's borderEntities set
pis.add(globalId, LI(localId, Attribute::owner, true)); if (borderEntities.contains(dofIdSet.entityId(i)))
else pis.add(globalId, LI(localIndex, Attribute::owner, true));
pis.add(globalId, LI(localId, Attribute::overlap, true)); else
break; pis.add(globalId, LI(localIndex, Attribute::overlap, true));
case PType::OverlapEntity: break;
case PType::FrontEntity: case PType::OverlapEntity:
pis.add(globalId, LI(localId, Attribute::overlap, true)); case PType::FrontEntity:
break; pis.add(globalId, LI(localIndex, Attribute::overlap, true));
case PType::GhostEntity: break;
pis.add(globalId, LI(localId, Attribute::copy, true)); case PType::GhostEntity:
break; pis.add(globalId, LI(localIndex, Attribute::copy, true));
break;
default:
error_exit("Unknown partition type.");
}
visited[localIndex] = true;
} }
} }
dofIdSet.unbind(); dofIdSet.unbind();
......
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
#include <dune/common/unused.hh> #include <dune/common/unused.hh>
#include <dune/grid/common/datahandleif.hh> #include <dune/grid/common/datahandleif.hh>
namespace Dune
{
// forward declaration
template <int dim> class UGGrid;
}
namespace AMDiS namespace AMDiS
{ {
/// \brief Determine for each border entity which processor owns it /// \brief Determine for each border entity which processor owns it
...@@ -18,8 +24,8 @@ namespace AMDiS ...@@ -18,8 +24,8 @@ namespace AMDiS
* be communicated. Here we assign the entity to the processor with the lowest rank. * be communicated. Here we assign the entity to the processor with the lowest rank.
**/ **/
template <class Grid> template <class Grid>
class UniqueBorderPartitionDataHandle class UniqueBorderPartition
: public Dune::CommDataHandleIF<UniqueBorderPartitionDataHandle<Grid>, int> : public Dune::CommDataHandleIF<UniqueBorderPartition<Grid>, int>
{ {
using IdSet = typename Grid::GlobalIdSet; using IdSet = typename Grid::GlobalIdSet;
using IdType = typename IdSet::IdType; using IdType = typename IdSet::IdType;
...@@ -32,22 +38,19 @@ namespace AMDiS ...@@ -32,22 +38,19 @@ namespace AMDiS
/// communicator. /// communicator.
/** /**
* \param rank The own processor rank * \param rank The own processor rank
* \param borderEntities A set of entity ids filled with all border entities
* owned by this processor after communication.
* \param idSet The id set of entity ids to store in borderEntities, * \param idSet The id set of entity ids to store in borderEntities,
* typically the grid globalIdSet. * typically the grid globalIdSet.
* *
* NOTE: Since idSet is stored by reference it must not go out of scope * NOTE: Since idSet is stored by reference it must not go out of scope
* until all calls to \ref gather and \ref scatter are finished. * until all calls to \ref gather and \ref scatter are finished.
**/ **/
UniqueBorderPartitionDataHandle(int rank, EntitySet& borderEntities, IdSet const& idSet) UniqueBorderPartition(int rank, Grid const& grid)
: myrank_(rank) : myrank_(rank)
, borderEntities_(&borderEntities) , idSet_(grid.globalIdSet())
, idSet_(idSet)
{} {}
// Communicate all entities except for grid elements // Communicate all entities
bool contains(int /*dim*/, int codim) const { return codim != 0; } bool contains(int /*dim*/, int /*codim*/) const { return true; }
// communicate exactly one integer, the rank // communicate exactly one integer, the rank
bool fixedSize(int /*dim*/, int /*codim*/) const { return true; } bool fixedSize(int /*dim*/, int /*codim*/) const { return true; }
...@@ -60,27 +63,197 @@ namespace AMDiS ...@@ -60,27 +63,197 @@ namespace AMDiS
void gather(MessageBuffer& buff, Entity const& e) const void gather(MessageBuffer& buff, Entity const& e) const
{ {
buff.write(myrank_); buff.write(myrank_);
// insert all border entities
borderEntities_->insert(idSet_.id(e));
} }
template <class MessageBuffer, class Entity> template <class MessageBuffer, class Entity>
void scatter(MessageBuffer& buff, Entity const& e, std::size_t n) void scatter(MessageBuffer& buff, Entity const& e, std::size_t n)
{
scatterImpl(buff, e, n, int_t<Entity::codimension>{});
}
/// Returns whether id is owned by this rank
bool contains(IdType const& id) const
{
return notOwner_.count(id) == 0;
}
/// Number of iterations to perform the communication in order to collect all neighboring entities
int numIterations() const
{
return 1;
}
private:
template <class MessageBuffer, class Entity, int cd>
void scatterImpl(MessageBuffer& buff, Entity const& e, std::size_t n, int_t<cd>)
{
DUNE_UNUSED_PARAMETER(n); // n == 1
assert(n == 1);
int rank = 0;
buff.read(rank);
// insert only border entities that are owned by other processors, i.e. rank > myrank
// Those entities are not owned by this rank.
if (rank > myrank_)
notOwner_.insert(idSet_.id(e));
}
template <class MessageBuffer, class Entity>
void scatterImpl(MessageBuffer& buff, Entity const& e, std::size_t n, int_t<0>)
{
DUNE_UNUSED_PARAMETER(n); // n == 1
assert(n == 1);
int rank = 0;
buff.read(rank);
// insert only border entities that are owned by other processors, i.e. rank > myrank
// Those entities are not owned by this rank.
if (rank > myrank_) {
for (int codim = 1; codim <= Grid::dimension; ++codim) {
for (int i = 0; i < int(e.subEntities(codim)); ++i) {
notOwner_.insert(idSet_.subId(e, i, codim));
}
}
}
}
private:
int myrank_;
EntitySet notOwner_;
IdSet const& idSet_;
};
/// Specialization for UGGrid that can not communicate over edges.
template <int dim>
class UniqueBorderPartition<Dune::UGGrid<dim>>
: public Dune::CommDataHandleIF<UniqueBorderPartition<Dune::UGGrid<dim>>, int>
{
using Grid = Dune::UGGrid<dim>;
using IdSet = typename Grid::LocalIdSet;
using IdType = typename IdSet::IdType;
public:
using EntitySet = std::set<IdType>;
public:
/// \brief Construct a UniqueBorderPartition DataHandle to be used in a GridView
/// communicator.
/**
* \param rank The own processor rank
* \param idSet The id set of entity ids to store in borderEntities,
* typically the grid globalIdSet.
*
* NOTE: Since idSet is stored by reference it must not go out of scope
* until all calls to \ref gather and \ref scatter are finished.
**/
UniqueBorderPartition(int rank, Grid const& grid)
: myrank_(rank)
, idSet_(grid.localIdSet())
{}
// Communicate all entities
bool contains(int /*dim*/, int codim) const { return true; }
// see size()
bool fixedSize(int /*dim*/, int codim) const { return codim != 0; }
// for codim=0 elements communicate data for all subEntities, otherwise communicate just the owner rank
template <class Entity>
std::size_t size(Entity const& e) const
{
if (Entity::codimension != 0)
return 1;
std::size_t s = 0;
for (int codim = 1; codim <= Grid::dimension; ++codim)
s += e.subEntities(codim);
return s;
}
template <class MessageBuffer, class Entity>
void gather(MessageBuffer& buff, Entity const& e) const
{
gatherImpl(buff, e, int_t<Entity::codimension>{});
}
template <class MessageBuffer, class Entity>
void scatter(MessageBuffer& buff, Entity const& e, std::size_t n)
{
scatterImpl(buff, e, n, int_t<Entity::codimension>{});
}
/// Returns whether id is in EntitySet
bool contains(IdType const& id) const
{
return entityToRank_[id] == myrank_;
}
/// Number of iterations to perform the communication in order to collect all neighboring entities
int numIterations() const
{
return Grid::dimension;
}
private:
template <class MessageBuffer, class Entity, int cd>
void gatherImpl(MessageBuffer& buff, Entity const& e, int_t<cd>) const
{
int& rank = entityToRank_[idSet_.id(e)];
rank = std::max(rank, myrank_);
buff.write(rank);
}
template <class MessageBuffer, class Entity>
void gatherImpl(MessageBuffer& buff, Entity const& e, int_t<0>) const
{
// maybe use global unique numbering (?)
for (int codim = 1; codim <= Grid::dimension; ++codim) {
for (int i = 0; i < int(e.subEntities(codim)); ++i) {
int& rank = entityToRank_[idSet_.subId(e, i, codim)];
rank = std::max(rank, myrank_);
buff.write(rank);
}
}
}
template <class MessageBuffer, class Entity, int cd>
void scatterImpl(MessageBuffer& buff, Entity const& e, std::size_t n, int_t<cd>)
{ {
DUNE_UNUSED_PARAMETER(n); // n == 1 DUNE_UNUSED_PARAMETER(n); // n == 1
assert(n == 1); assert(n == 1);
int rank = 0; int rank = 0;
buff.read(rank); buff.read(rank);
// remove all border entities with rank < myrank_
if (rank < myrank_) int& storedRank = entityToRank_[idSet_.id(e)];
borderEntities_->erase(idSet_.id(e)); storedRank = std::max(rank, storedRank);
}
template <class MessageBuffer, class Entity>
void scatterImpl(MessageBuffer& buff, Entity const& e, std::size_t n, int_t<0>)
{
std::size_t j = 0;
for (int codim = 1; codim <= Grid::dimension; ++codim) {
for (int i = 0; i < int(e.subEntities(codim)); ++i, ++j) {
assert(j < n);
int rank = 0;
buff.read(rank);
int& storedRank = entityToRank_[idSet_.subId(e, i, codim)];
storedRank = std::max(rank, storedRank);
}
}
} }
private: private:
int myrank_; int myrank_;
EntitySet* borderEntities_; mutable std::map<IdType, int> entityToRank_;
IdSet const& idSet_; IdSet const& idSet_;
}; };
} // end namespace AMDiS } // end namespace AMDiS
...@@ -11,17 +11,12 @@ template <class GridView> ...@@ -11,17 +11,12 @@ template <class GridView>
void test(GridView const& gv) void test(GridView const& gv)
{ {
using Grid = typename GridView::Grid; using Grid = typename GridView::Grid;
using DataHandle = UniqueBorderPartitionDataHandle<Grid>; using DataHandle = UniqueBorderPartition<Grid>;
using EntitySet = typename DataHandle::EntitySet; DataHandle borderEntities(gv.comm().rank(), gv.grid());
EntitySet borderEntities; gv.communicate(borderEntities,
Dune::InterfaceType::InteriorBorder_All_Interface,
DataHandle handle(gv.comm().rank(), borderEntities, gv.grid().globalIdSet());
gv.communicate(handle,
Dune::InterfaceType::InteriorBorder_InteriorBorder_Interface,
Dune::CommunicationDirection::ForwardCommunication); Dune::CommunicationDirection::ForwardCommunication);
msg("#borderEntities = {}", borderEntities.size());
} }
int main(int argc, char** argv) int main(int argc, char** argv)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment