Loading [MathJax]/extensions/tex2jax.js

dune-mmesh (1.4)

partitionhelper.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_MMESH_MISC_PARTITIONHELPER_HH
4#define DUNE_MMESH_MISC_PARTITIONHELPER_HH
5
6#include <dune/grid/common/partitionset.hh>
7#include <dune/mmesh/grid/rangegenerators.hh>
8
9namespace Dune
10{
11
12// PartitionHelper
13template <class Grid>
14struct PartitionHelper
15{
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;
21
22 PartitionHelper(const Grid& grid) : grid_(grid) {}
23
24 void distribute()
25 {
26 // Initialize leafBegin_ and leafEnd_
27 if constexpr (dim == 2)
28 {
29 leafBegin_ = grid().getHostGrid().finite_faces_begin();
30 leafEnd_ = grid().getHostGrid().finite_faces_end();
31 }
32 else if constexpr (dim == 3)
33 {
34 leafBegin_ = grid().getHostGrid().finite_cells_begin();
35 leafEnd_ = grid().getHostGrid().finite_cells_end();
36 }
37
38 if (grid().comm().size() == 1)
39 return;
40
41 setRanks();
42 computePartitions();
43 }
44
45 template <class Entity>
46 bool contains(PartitionIteratorType pitype, const Entity& e) const
47 {
48 return contains(pitype, partition(e));
49 }
50
51 bool contains(PartitionIteratorType pitype, int partitionType) const
52 {
53 if (partitionType == -1)
54 return false;
55
56 switch( pitype )
57 {
58 case All_Partition:
59 return true;
60
61 case Interior_Partition:
62 return partitionType == 0;
63
64 case InteriorBorder_Partition:
65 case Overlap_Partition:
66 case OverlapFront_Partition:
67 return partitionType != 2;
68
69 case Ghost_Partition:
70 return partitionType == 2;
71 }
72 return false;
73 }
74
75 template <class Entity>
76 PartitionType partitionType(const Entity& e) const
77 {
78 return partitionType( partition(e) );
79 }
80
81 PartitionType partitionType(int partition) const
82 {
83 if (partition == 0)
84 return InteriorEntity;
85
86 if (partition == 1)
87 return BorderEntity;
88
89 else
90 return GhostEntity;
91 }
92
93 void updatePartitions()
94 {
95 computePartitions();
96 }
97
99 const LinksType& links () const
100 {
101 return links_;
102 }
103
104 auto& comm() const
105 {
106 return grid().comm();
107 }
108
110 template <class Entity>
111 ConnectivityType connectivity(const Entity &e) const
112 {
113 if constexpr (Entity::dimension == dim)
114 return e.impl().hostEntity()->info().connectivity;
115 else
116 try {
117 return interfaceConnectivity_.at(e.impl().id());
118 } catch (std::out_of_range&) {
119 return ConnectivityType();
120 }
121 }
122
124 template <class Entity>
125 int rank(const Entity &e) const
126 {
127 if constexpr (Entity::dimension == dim)
128 return e.impl().hostEntity()->info().rank;
129 else
130 return grid().asIntersection(e).inside().impl().hostEntity()->info().rank;
131 }
132
133 const LeafIterator& leafInteriorBegin() const
134 {
135 return leafBegin_;
136 }
137
138 const LeafIterator& leafInteriorEnd() const
139 {
140 return leafEnd_;
141 }
142
143private:
144
146 template <class Entity>
147 int partition(const Entity& e) const
148 {
149 static constexpr int cd = Entity::codimension;
150 if (grid().comm().size() == 1)
151 return 0; // interior
152
153 if constexpr (Entity::dimension == dim)
154 {
155 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
156 return e.impl().hostEntity()->info().partition;
157 else
158 {
159 auto entry = partition_[cd-1].find(e.impl().id());
160 if (entry != partition_[cd-1].end())
161 return entry->second;
162 }
163 }
164 else
165 {
166 auto entry = interfacePartition_[cd].find(e.impl().id());
167 if (entry != interfacePartition_[cd].end())
168 return entry->second;
169
170 // handle empty interface
171 return -1;
172 }
173
174 DUNE_THROW(InvalidStateException, "Partition not set yet!");
175 return 0;
176 }
177
179 template <class Entity>
180 void setPartition(const Entity& e, int partition)
181 {
182 if constexpr (Entity::dimension == dim)
183 {
184 if constexpr (Entity::codimension == 0 || Entity::codimension == dim)
185 e.impl().hostEntity()->info().partition = partition;
186 else
187 partition_[Entity::codimension-1][e.impl().id()] = partition;
188 }
189 else
190 interfacePartition_[Entity::codimension][e.impl().id()] = partition;
191 }
192
194 template <class Entity>
195 void addConnectivity(const Entity &e, int rank)
196 {
197 if constexpr (Entity::dimension == dim)
198 e.impl().hostEntity()->info().connectivity.insert(rank);
199 else
200 interfaceConnectivity_[e.impl().id()].insert(rank);
201
202 if (partition(e) == 0)
203 if (std::find(links_.begin(), links_.end(), rank) == links_.end())
204 links_.push_back(rank);
205 }
206
208 template <class Entity>
209 void clearConnectivity(const Entity &e)
210 {
211 if constexpr (Entity::dimension == dim)
212 e.impl().hostEntity()->info().connectivity.clear();
213 else
214 interfaceConnectivity_[e.impl().id()].clear();
215 }
216
218 void setRanks()
219 {
220 int rank = grid().comm().rank();
221 int size = grid().comm().size();
222
223 std::size_t N;
224 if constexpr (dim == 2)
225 N = grid().getHostGrid().number_of_faces();
226 else
227 N = grid().getHostGrid().number_of_cells();
228
229 std::size_t i = 0;
230 forEntityDim<dim>([this, &i, &rank, &size, &N](const auto& fc)
231 {
232 auto getRank = [&size, &N](std::size_t i){ return i * size / N; };
233 int r = getRank(i);
234
235 // store begin iterator
236 if (r == rank && getRank(i-1) == rank-1)
237 this->leafBegin_ = fc;
238
239 // store end iterator
240 if (r == rank+1 && getRank(i-1) == rank)
241 this->leafEnd_ = fc;
242
243 auto e = grid().entity(fc);
244 e.impl().hostEntity()->info().rank = r;
245 i++;
246 });
247 }
248
250 void computePartitions()
251 {
252 links_.clear();
253
254 for (int i = 0; i <= dim; ++i)
255 partition_[i].clear();
256
257 // Set interior elements
258 forEntityDim<dim>([this](const auto& fc){
259 const auto e = grid().entity(fc);
260 if (rank(e) == grid().comm().rank())
261 setPartition(e, 0); // interior
262 else
263 setPartition(e, -1); // none
264
265 clearConnectivity(e);
266 });
267
268 // Set ghosts
269 forEntityDim<dim-1>([this](const auto& fc){
270 const auto e = grid().entity(fc);
271 const auto is = grid().asIntersection( e );
272 if (is.neighbor())
273 {
274 const auto& inside = is.inside();
275 const auto& outside = is.outside();
276 int pIn = partition( inside );
277 int pOut = partition( outside );
278
279 // border
280 if ((pIn == 0 && pOut != 0) or (pIn != 0 && pOut == 0))
281 {
282 setPartition(pIn == 0 ? outside : inside, 2); // ghost
283 addConnectivity(inside, rank(outside));
284 addConnectivity(outside, rank(inside));
285 }
286 }
287 });
288
289 // Compute interface partitions based on Codim 0 entities, this might add further ghost elements to the bulk
290 computeInterfacePartitions();
291
292 // Set facets
293 forEntityDim<dim-1>([this](const auto& fc){
294 const auto e = grid().entity(fc);
295 const auto is = grid().asIntersection( e );
296
297 int pIn = partition( is.inside() );
298
299 if (is.neighbor())
300 {
301 int pOut = partition( is.outside() );
302
303 // interior
304 if (pIn == 0 && pOut == 0)
305 setPartition(e, 0);
306
307 // border
308 else if ((pIn == 0 && pOut == 2) or (pIn == 2 && pOut == 0))
309 setPartition(e, 1);
310
311 // ghost
312 else if (pIn == 2 || pOut == 2)
313 setPartition(e, 2);
314
315 // none
316 else
317 setPartition(e, -1);
318 }
319 else
320 {
321 // interior
322 if (pIn == 0)
323 setPartition(e, 0);
324
325 // ghost
326 else if (pIn == 2)
327 setPartition(e, 2);
328
329 // none
330 else
331 setPartition(e, -1);
332 }
333 });
334
335 // Codim 2 in 3D
336 if constexpr (dim == 3)
337 {
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))
342 {
343 count++;
344 if (partition(e) == 0) interior++;
345 if (partition(e) == 2) ghost++;
346 }
347
348 // interior
349 if (interior == count)
350 setPartition(edge, 0);
351
352 // border
353 else if (interior > 0 and ghost > 0)
354 setPartition(edge, 1);
355
356 // ghost
357 else if (interior == 0 and ghost > 0)
358 setPartition(edge, 2);
359
360 // none
361 else
362 setPartition(edge, -1);
363 });
364 }
365
366 // Set vertices
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))
371 {
372 count++;
373 if (partition(e) == 0) interior++;
374 if (partition(e) == 2) ghost++;
375 }
376
377 // interior
378 if (interior == count)
379 setPartition(v, 0);
380
381 // border
382 else if (interior > 0 and ghost > 0)
383 setPartition(v, 1);
384
385 // ghost
386 else if (interior == 0 and ghost > 0)
387 setPartition(v, 2);
388
389 // none
390 else
391 setPartition(v, -1);
392 });
393 }
394
395public:
397 void computeInterfacePartitions()
398 {
399 static constexpr int idim = dim-1;
400
401 for (int i = 0; i <= idim; ++i)
402 interfacePartition_[i].clear();
403
404 // Set interior elements
405 forEntityDim<idim>([this](const auto& fc){
406 if (!grid().isInterface( grid().entity(fc) ))
407 return;
408
409 const auto e = grid().interfaceGrid().entity(fc);
410 const auto is = grid().asIntersection(e);
411
412 clearConnectivity(e);
413
414 if (rank(e) == grid().comm().rank())
415 {
416 setPartition(e, 0); // interior
417
418 // add connectivity to this entity being ghost on outside rank
419 if (is.neighbor())
420 if (rank(is.outside()) != grid().comm().rank())
421 addConnectivity(e, rank(is.outside()));
422 }
423 else
424 setPartition(e, -1); // none
425
426 // if outside bulk entity is interior, the interface element is at least ghost
427 if (is.neighbor())
428 if (rank(is.outside()) == grid().comm().rank())
429 if (partition(e) == -1)
430 {
431 setPartition(e, 2); // ghost
432 addConnectivity(e, rank(is.inside()));
433 }
434 });
435
436 // Set ghosts
437 forEntityDim<idim-1>([this](const auto& fc){
438 if (!grid().isInterface( grid().entity(fc) ))
439 return;
440
441 // convert to interface vertex
442 const auto e = grid().interfaceGrid().entity(fc);
443
444 std::size_t count = 0, interior = 0, other = 0;
445 for (const auto& incident : incidentInterfaceElements(e))
446 {
447 count++;
448 if (partition(incident) == 0) interior++;
449 if (partition(incident) != 0) other++;
450 }
451
452 // if we find both interior and other entities we set none to ghost
453 if (interior > 0 and other > 0)
454 for (const auto& incident : incidentInterfaceElements(e))
455 if (partition(incident) == -1)
456 {
457 setPartition(incident, 2); // ghost
458
459 // make sure that both adjacent bulk entities are at least ghost
460 auto intersection = grid().asIntersection(incident);
461 if (partition(intersection.inside()) == -1)
462 setPartition(intersection.inside(), 2); // ghost
463 if (intersection.neighbor())
464 if (partition(intersection.outside()) == -1)
465 setPartition(intersection.outside(), 2); // ghost
466 }
467 });
468
469 // Set facets
470 forEntityDim<idim-1>([this](const auto& fc){
471 if (!grid().isInterface( grid().entity(fc) ))
472 return;
473
474 // convert to interface vertex
475 const auto e = grid().interfaceGrid().entity(fc);
476
477 std::size_t count = 0, interior = 0, ghost = 0;
478 std::unordered_set<int> connectivity;
479 for (const auto& incident : incidentInterfaceElements(e))
480 {
481 count++;
482 if (partition(incident) == 0) interior++;
483 if (partition(incident) == 2) ghost++;
484 connectivity.insert( rank(incident) );
485 }
486
487 // interior
488 if (interior == count)
489 setPartition(e, 0);
490
491 // border
492 else if (interior > 0 and ghost > 0)
493 {
494 setPartition(e, 1);
495
496 for (const auto& incident : incidentInterfaceElements(e))
497 for (auto r : connectivity)
498 if (r != rank(incident))
499 addConnectivity(incident, r);
500 }
501
502 // ghost
503 else if (ghost > 0)
504 setPartition(e, 2);
505
506 // none
507 else
508 setPartition(e, -1);
509 });
510
511 // Set vertices in 3d
512 if constexpr (dim == 3)
513 {
514 forEntityDim<idim-2>([this](const auto& fc){
515 if (!grid().isInterface( grid().entity(fc) ))
516 return;
517
518 const auto v = grid().interfaceGrid().entity(fc);
519
520 std::size_t count = 0, interior = 0, ghost = 0;
521 for (const auto& incident : incidentInterfaceElements(v))
522 {
523 count++;
524 if (partition(incident) == 0) interior++;
525 if (partition(incident) == 2) ghost++;
526 }
527
528 // interior
529 if (interior == count)
530 setPartition(v, 0);
531
532 // border
533 else if (interior > 0 and ghost > 0)
534 setPartition(v, 1);
535
536 // ghost
537 else if (ghost > 0)
538 setPartition(v, 2);
539
540 // none
541 else
542 setPartition(v, -1);
543 });
544 }
545 }
546
547private:
548 template <int edim, class F>
549 void forEntityDim(const F& f)
550 {
551 if constexpr (edim == dim)
552 {
553 if constexpr (dim == 2)
554 for (auto fc = grid().getHostGrid().finite_faces_begin(); fc != grid().getHostGrid().finite_faces_end(); ++fc)
555 f( fc );
556
557 if constexpr (dim == 3)
558 for (auto fc = grid().getHostGrid().finite_cells_begin(); fc != grid().getHostGrid().finite_cells_end(); ++fc)
559 f( fc );
560 }
561
562 if constexpr (edim == 0)
563 for (auto fc = grid().getHostGrid().finite_vertices_begin(); fc != grid().getHostGrid().finite_vertices_end(); ++fc)
564 f( fc );
565
566 if constexpr (edim == 1)
567 for (auto fc = grid().getHostGrid().finite_edges_begin(); fc != grid().getHostGrid().finite_edges_end(); ++fc)
568 f( *fc );
569
570 if constexpr (dim == 3 && edim == 2)
571 for (auto fc = grid().getHostGrid().finite_facets_begin(); fc != grid().getHostGrid().finite_facets_end(); ++fc)
572 f( *fc );
573 }
574
575 const Grid& grid() const { return grid_; }
576
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_;
582 LinksType links_;
583 const Grid& grid_;
584};
585
586} // end namespace Dune
587
588#endif
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 6, 22:49, 2025)