3#ifndef DUNE_MMESH_MISC_PARTITIONHELPER_HH
4#define DUNE_MMESH_MISC_PARTITIONHELPER_HH
6#include <dune/grid/common/partitionset.hh>
7#include <dune/mmesh/grid/rangegenerators.hh>
16 static constexpr int dim = Grid::dimension;
17 using IdType =
typename Grid::IdType;
18 using ConnectivityType = std::unordered_set<int>;
19 using LinksType = std::vector<int>;
20 using LeafIterator =
typename Grid::LeafIterator::Implementation::HostGridLeafIterator;
22 PartitionHelper(
const Grid& grid) : grid_(grid) {}
27 if constexpr (dim == 2)
29 leafBegin_ = grid().getHostGrid().finite_faces_begin();
30 leafEnd_ = grid().getHostGrid().finite_faces_end();
32 else if constexpr (dim == 3)
34 leafBegin_ = grid().getHostGrid().finite_cells_begin();
35 leafEnd_ = grid().getHostGrid().finite_cells_end();
38 if (grid().comm().size() == 1)
45 template <
class Entity>
46 bool contains(PartitionIteratorType pitype,
const Entity& e)
const
48 return contains(pitype, partition(e));
51 bool contains(PartitionIteratorType pitype,
int partitionType)
const
53 if (partitionType == -1)
61 case Interior_Partition:
62 return partitionType == 0;
64 case InteriorBorder_Partition:
65 case Overlap_Partition:
66 case OverlapFront_Partition:
67 return partitionType != 2;
70 return partitionType == 2;
75 template <
class Entity>
76 PartitionType partitionType(
const Entity& e)
const
78 return partitionType( partition(e) );
81 PartitionType partitionType(
int partition)
const
84 return InteriorEntity;
93 void updatePartitions()
99 const LinksType& links ()
const
106 return grid().comm();
110 template <
class Entity>
111 ConnectivityType connectivity(
const Entity &e)
const
113 if constexpr (Entity::dimension == dim)
114 return e.impl().hostEntity()->info().connectivity;
117 return interfaceConnectivity_.at(e.impl().id());
118 }
catch (std::out_of_range&) {
119 return ConnectivityType();
124 template <
class Entity>
125 int rank(
const Entity &e)
const
127 if constexpr (Entity::dimension == dim)
128 return e.impl().hostEntity()->info().rank;
130 return grid().asIntersection(e).inside().impl().hostEntity()->info().rank;
133 const LeafIterator& leafInteriorBegin()
const
138 const LeafIterator& leafInteriorEnd()
const
146 template <
class Entity>
147 int partition(
const Entity& e)
const
149 static constexpr int cd = Entity::codimension;
150 if (grid().comm().size() == 1)
153 if constexpr (Entity::dimension == dim)
155 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
156 return e.impl().hostEntity()->info().partition;
159 auto entry = partition_[cd-1].find(e.impl().id());
160 if (entry != partition_[cd-1].end())
161 return entry->second;
166 auto entry = interfacePartition_[cd].find(e.impl().id());
167 if (entry != interfacePartition_[cd].end())
168 return entry->second;
174 DUNE_THROW(InvalidStateException,
"Partition not set yet!");
179 template <
class Entity>
180 void setPartition(
const Entity& e,
int partition)
182 if constexpr (Entity::dimension == dim)
184 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
185 e.impl().hostEntity()->info().partition = partition;
187 partition_[Entity::codimension-1][e.impl().id()] = partition;
190 interfacePartition_[Entity::codimension][e.impl().id()] = partition;
194 template <
class Entity>
195 void addConnectivity(
const Entity &e,
int rank)
197 if constexpr (Entity::dimension == dim)
198 e.impl().hostEntity()->info().connectivity.insert(rank);
200 interfaceConnectivity_[e.impl().id()].insert(rank);
202 if (partition(e) == 0)
203 if (std::find(links_.begin(), links_.end(), rank) == links_.end())
204 links_.push_back(rank);
208 template <
class Entity>
209 void clearConnectivity(
const Entity &e)
211 if constexpr (Entity::dimension == dim)
212 e.impl().hostEntity()->info().connectivity.clear();
214 interfaceConnectivity_[e.impl().id()].clear();
220 int rank = grid().comm().rank();
221 int size = grid().comm().size();
224 if constexpr (dim == 2)
225 N = grid().getHostGrid().number_of_faces();
227 N = grid().getHostGrid().number_of_cells();
230 forEntityDim<dim>([
this, &i, &rank, &size, &N](
const auto& fc)
232 auto getRank = [&size, &N](std::size_t i){
return i * size / N; };
236 if (r == rank && getRank(i-1) == rank-1)
237 this->leafBegin_ = fc;
240 if (r == rank+1 && getRank(i-1) == rank)
243 auto e = grid().entity(fc);
244 e.impl().hostEntity()->info().rank = r;
250 void computePartitions()
254 for (
int i = 0; i <= dim; ++i)
255 partition_[i].clear();
258 forEntityDim<dim>([
this](
const auto& fc){
259 const auto e = grid().entity(fc);
260 if (rank(e) == grid().comm().rank())
265 clearConnectivity(e);
269 forEntityDim<dim-1>([
this](
const auto& fc){
270 const auto e = grid().entity(fc);
271 const auto is = grid().asIntersection( e );
274 const auto& inside = is.inside();
275 const auto& outside = is.outside();
276 int pIn = partition( inside );
277 int pOut = partition( outside );
280 if ((pIn == 0 && pOut != 0) or (pIn != 0 && pOut == 0))
282 setPartition(pIn == 0 ? outside : inside, 2);
283 addConnectivity(inside, rank(outside));
284 addConnectivity(outside, rank(inside));
290 computeInterfacePartitions();
293 forEntityDim<dim-1>([
this](
const auto& fc){
294 const auto e = grid().entity(fc);
295 const auto is = grid().asIntersection( e );
297 int pIn = partition( is.inside() );
301 int pOut = partition( is.outside() );
304 if (pIn == 0 && pOut == 0)
308 else if ((pIn == 0 && pOut == 2) or (pIn == 2 && pOut == 0))
312 else if (pIn == 2 || pOut == 2)
336 if constexpr (dim == 3)
338 forEntityDim<1>([
this](
const auto& fc){
339 const auto edge = grid().entity(fc);
340 std::size_t count = 0, interior = 0, ghost = 0;
341 for (
const auto e : incidentElements(edge))
344 if (partition(e) == 0) interior++;
345 if (partition(e) == 2) ghost++;
349 if (interior == count)
350 setPartition(edge, 0);
353 else if (interior > 0 and ghost > 0)
354 setPartition(edge, 1);
357 else if (interior == 0 and ghost > 0)
358 setPartition(edge, 2);
362 setPartition(edge, -1);
367 forEntityDim<0>([
this](
const auto& fc){
368 const auto v = grid().entity(fc);
369 std::size_t count = 0, interior = 0, ghost = 0;
370 for (
const auto e : incidentElements(v))
373 if (partition(e) == 0) interior++;
374 if (partition(e) == 2) ghost++;
378 if (interior == count)
382 else if (interior > 0 and ghost > 0)
386 else if (interior == 0 and ghost > 0)
397 void computeInterfacePartitions()
399 static constexpr int idim = dim-1;
401 for (
int i = 0; i <= idim; ++i)
402 interfacePartition_[i].clear();
405 forEntityDim<idim>([
this](
const auto& fc){
406 if (!grid().isInterface( grid().entity(fc) ))
409 const auto e = grid().interfaceGrid().entity(fc);
410 const auto is = grid().asIntersection(e);
412 clearConnectivity(e);
414 if (rank(e) == grid().comm().rank())
420 if (rank(is.outside()) != grid().comm().rank())
421 addConnectivity(e, rank(is.outside()));
428 if (rank(is.outside()) == grid().comm().rank())
429 if (partition(e) == -1)
432 addConnectivity(e, rank(is.inside()));
437 forEntityDim<idim-1>([
this](
const auto& fc){
438 if (!grid().isInterface( grid().entity(fc) ))
442 const auto e = grid().interfaceGrid().entity(fc);
444 std::size_t count = 0, interior = 0, other = 0;
445 for (
const auto& incident : incidentInterfaceElements(e))
448 if (partition(incident) == 0) interior++;
449 if (partition(incident) != 0) other++;
453 if (interior > 0 and other > 0)
454 for (
const auto& incident : incidentInterfaceElements(e))
455 if (partition(incident) == -1)
457 setPartition(incident, 2);
460 auto intersection = grid().asIntersection(incident);
461 if (partition(intersection.inside()) == -1)
462 setPartition(intersection.inside(), 2);
463 if (intersection.neighbor())
464 if (partition(intersection.outside()) == -1)
465 setPartition(intersection.outside(), 2);
470 forEntityDim<idim-1>([
this](
const auto& fc){
471 if (!grid().isInterface( grid().entity(fc) ))
475 const auto e = grid().interfaceGrid().entity(fc);
477 std::size_t count = 0, interior = 0, ghost = 0;
478 std::unordered_set<int> connectivity;
479 for (
const auto& incident : incidentInterfaceElements(e))
482 if (partition(incident) == 0) interior++;
483 if (partition(incident) == 2) ghost++;
484 connectivity.insert( rank(incident) );
488 if (interior == count)
492 else if (interior > 0 and ghost > 0)
496 for (
const auto& incident : incidentInterfaceElements(e))
497 for (
auto r : connectivity)
498 if (r != rank(incident))
499 addConnectivity(incident, r);
512 if constexpr (dim == 3)
514 forEntityDim<idim-2>([
this](
const auto& fc){
515 if (!grid().isInterface( grid().entity(fc) ))
518 const auto v = grid().interfaceGrid().entity(fc);
520 std::size_t count = 0, interior = 0, ghost = 0;
521 for (
const auto& incident : incidentInterfaceElements(v))
524 if (partition(incident) == 0) interior++;
525 if (partition(incident) == 2) ghost++;
529 if (interior == count)
533 else if (interior > 0 and ghost > 0)
548 template <
int edim,
class F>
549 void forEntityDim(
const F& f)
551 if constexpr (edim == dim)
553 if constexpr (dim == 2)
554 for (
auto fc = grid().getHostGrid().finite_faces_begin(); fc != grid().getHostGrid().finite_faces_end(); ++fc)
557 if constexpr (dim == 3)
558 for (
auto fc = grid().getHostGrid().finite_cells_begin(); fc != grid().getHostGrid().finite_cells_end(); ++fc)
562 if constexpr (edim == 0)
563 for (
auto fc = grid().getHostGrid().finite_vertices_begin(); fc != grid().getHostGrid().finite_vertices_end(); ++fc)
566 if constexpr (edim == 1)
567 for (
auto fc = grid().getHostGrid().finite_edges_begin(); fc != grid().getHostGrid().finite_edges_end(); ++fc)
570 if constexpr (dim == 3 && edim == 2)
571 for (
auto fc = grid().getHostGrid().finite_facets_begin(); fc != grid().getHostGrid().finite_facets_end(); ++fc)
575 const Grid& grid()
const {
return grid_; }
577 std::array<double, 2> xbounds_;
578 std::array<std::unordered_map<IdType, int>, dim-1> partition_;
579 std::array<std::unordered_map<IdType, int>, dim> interfacePartition_;
580 std::unordered_map<IdType, ConnectivityType> interfaceConnectivity_;
581 LeafIterator leafBegin_, leafEnd_;