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>
13struct PartitionHelper {
14 static constexpr int dim = Grid::dimension;
15 using IdType =
typename Grid::IdType;
16 using ConnectivityType = std::unordered_set<int>;
17 using LinksType = std::vector<int>;
19 typename Grid::LeafIterator::Implementation::HostGridLeafIterator;
21 PartitionHelper(
const Grid& grid) : grid_(grid) {}
25 if constexpr (dim == 2) {
26 leafBegin_ = grid().getHostGrid().finite_faces_begin();
27 leafEnd_ = grid().getHostGrid().finite_faces_end();
28 }
else if constexpr (dim == 3) {
29 leafBegin_ = grid().getHostGrid().finite_cells_begin();
30 leafEnd_ = grid().getHostGrid().finite_cells_end();
33 if (grid().comm().size() == 1)
return;
39 template <
class Entity>
40 bool contains(PartitionIteratorType pitype,
const Entity& e)
const {
41 return contains(pitype, partition(e));
44 bool contains(PartitionIteratorType pitype,
int partitionType)
const {
45 if (partitionType == -1)
return false;
51 case Interior_Partition:
52 return partitionType == 0;
54 case InteriorBorder_Partition:
55 case Overlap_Partition:
56 case OverlapFront_Partition:
57 return partitionType != 2;
60 return partitionType == 2;
65 template <
class Entity>
66 PartitionType partitionType(
const Entity& e)
const {
67 return partitionType(partition(e));
70 PartitionType partitionType(
int partition)
const {
71 if (partition == 0)
return InteriorEntity;
80 void updatePartitions() { computePartitions(); }
83 const LinksType& links()
const {
return links_; }
85 auto& comm()
const {
return grid().comm(); }
88 template <
class Entity>
89 ConnectivityType connectivity(
const Entity& e)
const {
90 if constexpr (Entity::dimension == dim)
91 return e.impl().hostEntity()->info().connectivity;
94 return interfaceConnectivity_.at(e.impl().id());
95 }
catch (std::out_of_range&) {
96 return ConnectivityType();
101 template <
class Entity>
102 int rank(
const Entity& e)
const {
103 if constexpr (Entity::dimension == dim)
104 return e.impl().hostEntity()->info().rank;
106 return grid().asIntersection(e).inside().impl().hostEntity()->info().rank;
109 const LeafIterator& leafInteriorBegin()
const {
return leafBegin_; }
111 const LeafIterator& leafInteriorEnd()
const {
return leafEnd_; }
115 template <
class Entity>
116 int partition(
const Entity& e)
const {
117 static constexpr int cd = Entity::codimension;
118 if (grid().comm().size() == 1)
return 0;
120 if constexpr (Entity::dimension == dim) {
121 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
122 return e.impl().hostEntity()->info().partition;
124 auto entry = partition_[cd - 1].find(e.impl().id());
125 if (entry != partition_[cd - 1].end())
return entry->second;
128 auto entry = interfacePartition_[cd].find(e.impl().id());
129 if (entry != interfacePartition_[cd].end())
return entry->second;
135 DUNE_THROW(InvalidStateException,
"Partition not set yet!");
140 template <
class Entity>
141 void setPartition(
const Entity& e,
int partition) {
142 if constexpr (Entity::dimension == dim) {
143 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
144 e.impl().hostEntity()->info().partition = partition;
146 partition_[Entity::codimension - 1][e.impl().id()] = partition;
148 interfacePartition_[Entity::codimension][e.impl().id()] = partition;
152 template <
class Entity>
153 void addConnectivity(
const Entity& e,
int rank) {
154 if constexpr (Entity::dimension == dim)
155 e.impl().hostEntity()->info().connectivity.insert(rank);
157 interfaceConnectivity_[e.impl().id()].insert(rank);
159 if (partition(e) == 0)
160 if (std::find(links_.begin(), links_.end(), rank) == links_.end())
161 links_.push_back(rank);
165 template <
class Entity>
166 void clearConnectivity(
const Entity& e) {
167 if constexpr (Entity::dimension == dim)
168 e.impl().hostEntity()->info().connectivity.clear();
170 interfaceConnectivity_[e.impl().id()].clear();
176 int rank = grid().comm().rank();
177 int size = grid().comm().size();
180 if constexpr (dim == 2)
181 N = grid().getHostGrid().number_of_faces();
183 N = grid().getHostGrid().number_of_cells();
186 forEntityDim<dim>([
this, &i, &rank, &size, &N](
const auto& fc) {
187 auto getRank = [&size, &N](std::size_t i) {
return i * size / N; };
191 if (r == rank && getRank(i - 1) == rank - 1) this->leafBegin_ = fc;
194 if (r == rank + 1 && getRank(i - 1) == rank) this->leafEnd_ = fc;
196 auto e = grid().entity(fc);
197 e.impl().hostEntity()->info().rank = r;
203 void computePartitions() {
206 for (
int i = 0; i <= dim; ++i) partition_[i].clear();
209 forEntityDim<dim>([
this](
const auto& fc) {
210 const auto e = grid().entity(fc);
211 if (rank(e) == grid().comm().rank())
216 clearConnectivity(e);
220 forEntityDim<dim - 1>([
this](
const auto& fc) {
221 const auto e = grid().entity(fc);
222 const auto is = grid().asIntersection(e);
224 const auto& inside = is.inside();
225 const auto& outside = is.outside();
226 int pIn = partition(inside);
227 int pOut = partition(outside);
230 if ((pIn == 0 && pOut != 0) or (pIn != 0 && pOut == 0)) {
231 setPartition(pIn == 0 ? outside : inside, 2);
232 addConnectivity(inside, rank(outside));
233 addConnectivity(outside, rank(inside));
240 computeInterfacePartitions();
243 forEntityDim<dim - 1>([
this](
const auto& fc) {
244 const auto e = grid().entity(fc);
245 const auto is = grid().asIntersection(e);
247 int pIn = partition(is.inside());
250 int pOut = partition(is.outside());
253 if (pIn == 0 && pOut == 0) setPartition(e, 0);
256 else if ((pIn == 0 && pOut == 2) or (pIn == 2 && pOut == 0))
260 else if (pIn == 2 || pOut == 2)
268 if (pIn == 0) setPartition(e, 0);
281 if constexpr (dim == 3) {
282 forEntityDim<1>([
this](
const auto& fc) {
283 const auto edge = grid().entity(fc);
284 std::size_t count = 0, interior = 0, ghost = 0;
285 for (
const auto e : incidentElements(edge)) {
287 if (partition(e) == 0) interior++;
288 if (partition(e) == 2) ghost++;
292 if (interior == count) setPartition(edge, 0);
295 else if (interior > 0 and ghost > 0)
296 setPartition(edge, 1);
299 else if (interior == 0 and ghost > 0)
300 setPartition(edge, 2);
304 setPartition(edge, -1);
309 forEntityDim<0>([
this](
const auto& fc) {
310 const auto v = grid().entity(fc);
311 std::size_t count = 0, interior = 0, ghost = 0;
312 for (
const auto e : incidentElements(v)) {
314 if (partition(e) == 0) interior++;
315 if (partition(e) == 2) ghost++;
319 if (interior == count) setPartition(v, 0);
322 else if (interior > 0 and ghost > 0)
326 else if (interior == 0 and ghost > 0)
337 void computeInterfacePartitions() {
338 static constexpr int idim = dim - 1;
340 for (
int i = 0; i <= idim; ++i) interfacePartition_[i].clear();
343 forEntityDim<idim>([
this](
const auto& fc) {
344 if (!grid().isInterface(grid().entity(fc)))
return;
346 const auto e = grid().interfaceGrid().entity(fc);
347 const auto is = grid().asIntersection(e);
349 clearConnectivity(e);
351 if (rank(e) == grid().comm().rank()) {
356 if (rank(is.outside()) != grid().comm().rank())
357 addConnectivity(e, rank(is.outside()));
364 if (rank(is.outside()) == grid().comm().rank())
365 if (partition(e) == -1) {
367 addConnectivity(e, rank(is.inside()));
372 forEntityDim<idim - 1>([
this](
const auto& fc) {
373 if (!grid().isInterface(grid().entity(fc)))
return;
376 const auto e = grid().interfaceGrid().entity(fc);
378 std::size_t count = 0, interior = 0, other = 0;
379 for (
const auto& incident : incidentInterfaceElements(e)) {
381 if (partition(incident) == 0) interior++;
382 if (partition(incident) != 0) other++;
386 if (interior > 0 and other > 0)
387 for (
const auto& incident : incidentInterfaceElements(e))
388 if (partition(incident) == -1) {
389 setPartition(incident, 2);
392 auto intersection = grid().asIntersection(incident);
393 if (partition(intersection.inside()) == -1)
394 setPartition(intersection.inside(), 2);
395 if (intersection.neighbor())
396 if (partition(intersection.outside()) == -1)
397 setPartition(intersection.outside(), 2);
402 forEntityDim<idim - 1>([
this](
const auto& fc) {
403 if (!grid().isInterface(grid().entity(fc)))
return;
406 const auto e = grid().interfaceGrid().entity(fc);
408 std::size_t count = 0, interior = 0, ghost = 0;
409 std::unordered_set<int> connectivity;
410 for (
const auto& incident : incidentInterfaceElements(e)) {
412 if (partition(incident) == 0) interior++;
413 if (partition(incident) == 2) ghost++;
414 connectivity.insert(rank(incident));
418 if (interior == count) setPartition(e, 0);
421 else if (interior > 0 and ghost > 0) {
424 for (
const auto& incident : incidentInterfaceElements(e))
425 for (
auto r : connectivity)
426 if (r != rank(incident)) addConnectivity(incident, r);
439 if constexpr (dim == 3) {
440 forEntityDim<idim - 2>([
this](
const auto& fc) {
441 if (!grid().isInterface(grid().entity(fc)))
return;
443 const auto v = grid().interfaceGrid().entity(fc);
445 std::size_t count = 0, interior = 0, ghost = 0;
446 for (
const auto& incident : incidentInterfaceElements(v)) {
448 if (partition(incident) == 0) interior++;
449 if (partition(incident) == 2) ghost++;
453 if (interior == count) setPartition(v, 0);
456 else if (interior > 0 and ghost > 0)
471 template <
int edim,
class F>
472 void forEntityDim(
const F& f) {
473 if constexpr (edim == dim) {
474 if constexpr (dim == 2)
475 for (
auto fc = grid().getHostGrid().finite_faces_begin();
476 fc != grid().getHostGrid().finite_faces_end(); ++fc)
479 if constexpr (dim == 3)
480 for (
auto fc = grid().getHostGrid().finite_cells_begin();
481 fc != grid().getHostGrid().finite_cells_end(); ++fc)
485 if constexpr (edim == 0)
486 for (
auto fc = grid().getHostGrid().finite_vertices_begin();
487 fc != grid().getHostGrid().finite_vertices_end(); ++fc)
490 if constexpr (edim == 1)
491 for (
auto fc = grid().getHostGrid().finite_edges_begin();
492 fc != grid().getHostGrid().finite_edges_end(); ++fc)
495 if constexpr (dim == 3 && edim == 2)
496 for (
auto fc = grid().getHostGrid().finite_facets_begin();
497 fc != grid().getHostGrid().finite_facets_end(); ++fc)
501 const Grid& grid()
const {
return grid_; }
503 std::array<double, 2> xbounds_;
504 std::array<std::unordered_map<IdType, int>, dim - 1> partition_;
505 std::array<std::unordered_map<IdType, int>, dim> interfacePartition_;
506 std::unordered_map<IdType, ConnectivityType> interfaceConnectivity_;
507 LeafIterator leafBegin_, leafEnd_;