PolyDEAL
 
Loading...
Searching...
No Matches
agglomeration_accessor.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) XXXX - YYYY by the polyDEAL authors
5//
6// This file is part of the polyDEAL library.
7//
8// Detailed license information governing the source code
9// can be found in LICENSE.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#ifndef agglomeration_accessor_h
15#define agglomeration_accessor_h
16
17#include <deal.II/base/config.h>
18
21
23
24#include <vector>
25
26using namespace dealii;
27
28
29// Forward declarations
30#ifndef DOXYGEN
31template <int, int>
33template <int, int>
35#endif
36
37
41template <int dim, int spacedim = dim>
43{
44public:
49 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>;
50
51
55 void
56 get_dof_indices(std::vector<types::global_dof_index> &) const;
57
64 unsigned int
65 n_faces() const;
66
70 unsigned int
72
77 neighbor(const unsigned int f) const;
78
83 unsigned int
84 neighbor_of_agglomerated_neighbor(const unsigned int f) const;
85
95 bool
96 at_boundary(const unsigned int f) const;
97
101 const std::vector<typename Triangulation<dim>::active_face_iterator> &
103
108 double
109 volume() const;
110
114 double
115 diameter() const;
116
122
128 const BoundingBox<dim> &
130
135 index() const;
136
145
150 unsigned int
152
153 /* Returns true if this polygon is owned by the current processor. On a serial
154 * Triangulation this returs always true, but may yield false for a
155 * parallel::distributed::Triangulation.
156 */
157 bool
159
165 CellId
166 id() const;
167
174
178 inline const std::vector<types::global_cell_index> &
179 children() const;
180
187 get_fe() const;
188
194 void
196
204
205private:
211
221
227 const CellId &cell_id,
229
234
235
240
245
250
255
260
265 bool
267
271 bool
273
277 void
279
283 void
285
290 get_slaves() const;
291
292 unsigned int
295 const;
296
297 template <int, int>
299};
300
301
302
303template <int dim, int spacedim>
304unsigned int
307{
308 unsigned int n_neighbors = 0;
309 for (const auto &f : cell->face_indices())
310 {
311 const auto &neighboring_cell = cell->neighbor(f);
312 if ((cell->face(f)->at_boundary()) ||
313 (neighboring_cell->is_active() &&
314 !handler->are_cells_agglomerated(cell, neighboring_cell)))
315 {
316 ++n_neighbors;
317 }
318 }
319 return n_neighbors;
320}
321
322
323
324template <int dim, int spacedim>
325unsigned int
327{
328 Assert(!handler->is_slave_cell(master_cell),
329 ExcMessage("You cannot pass a slave cell."));
330 return handler->number_of_agglomerated_faces[present_index];
331}
332
333
334
335template <int dim, int spacedim>
338{
339 if (!at_boundary(f))
340 {
341 if (master_cell->is_ghost())
342 {
343 // The following path is needed when the present function is called
344 // from neighbor_of_neighbor()
345
346 const unsigned int sender_rank = master_cell->subdomain_id();
347
348 const CellId &master_id_ghosted_neighbor =
349 handler->recv_ghosted_master_id.at(sender_rank)
350 .at(present_id)
351 .at(f);
352
353 // Use the id of the master cell to uniquely identify the neighboring
354 // agglomerate
355
356 return {master_cell,
357 master_id_ghosted_neighbor,
358 handler}; // dummy master?
359 }
360
361 const types::global_cell_index polytope_index =
362 handler->master2polygon.at(master_cell->active_cell_index());
363
364 // #ifdef AGGLO_DEBUG
365 // std::cout << "Poly index: " << polytope_index << std::endl;
366 // std::cout << "Face index " << f << std::endl;
367
368 // if (Utilities::MPI::this_mpi_process(handler->communicator) == 1)
369 // for (const auto &[key, value] :
370 // handler->polytope_cache.cell_face_at_boundary)
371 // {
372 // std::cout << "p.f = " << key.first << std::endl;
373 // std::cout << "p.s = " << key.second << std::endl;
374 // }
375 // #endif
376
377 const auto &neigh =
378 handler->polytope_cache.cell_face_at_boundary.at({polytope_index, f})
379 .second;
380
381
382 if (neigh->is_locally_owned())
383 {
385 *neigh, &(handler->agglo_dh));
386 return {cell_dh, handler};
387 }
388 else
389 {
390 // #ifdef AGGLO_DEBUG
391 // std::cout << "before calling ghosted_masteer_id" <<
392 // std::endl; std::cout << "present_id = " << present_id <<
393 // std::endl; std::cout << "che master cell? " <<
394 // master_cell << std::endl;
395
396 // if
397 // (Utilities::MPI::this_mpi_process(handler->communicator)
398 // == 1)
399 // for (const auto &[key, value] :
400 // handler->polytope_cache.ghosted_master_id)
401 // {
402 // std::cout << "poly_id = " << key.first <<
403 // std::endl; std::cout << "face_idx = " << key.second
404 // << std::endl;
405 // }
406
407 // #endif
408 // Get master_id from the neighboring ghost polytope. This uniquely
409 // identifies the neighboring polytope among all processors.
410 const CellId &master_id_neighbor =
411 handler->polytope_cache.ghosted_master_id.at({present_id, f});
412
413 // Use the id of the master cell to uniquely identify the neighboring
414 // agglomerate
415 return {neigh, master_id_neighbor, handler};
416 }
417 }
418 else
419 {
420 return {};
421 }
422}
423
424
425
426template <int dim, int spacedim>
427unsigned int
429 const unsigned int f) const
430{
431 // First, make sure it's not a boundary face.
432 if (!at_boundary(f))
433 {
434 const auto &neigh_polytope =
435 neighbor(f); // returns the neighboring master and id
436
437 AssertThrow(neigh_polytope.state() == IteratorState::valid,
438 ExcInternalError());
439
440 unsigned int n_faces_agglomerated_neighbor;
441
442 // if it is locally owned, retrieve the number of faces
443 if (neigh_polytope->is_locally_owned())
444 {
445 n_faces_agglomerated_neighbor = neigh_polytope->n_faces();
446 }
447 else
448 {
449 // The neighboring polytope is not locally owned. We need to get the
450 // number of its faces from the neighboring rank.
451
452 // First, retrieve the CellId of the neighboring polytope.
453 const CellId &master_id_neighbor = neigh_polytope->id();
454
455 // Then, get the neighboring rank
456 const unsigned int sender_rank = neigh_polytope->subdomain_id();
457
458 // From the neighboring rank, use the CellId of the neighboring
459 // polytope to get the number of its faces.
460 n_faces_agglomerated_neighbor =
461 handler->recv_n_faces.at(sender_rank).at(master_id_neighbor);
462 }
463
464
465 // Loop over all faces of neighboring agglomerate
466 for (unsigned int f_out = 0; f_out < n_faces_agglomerated_neighbor;
467 ++f_out)
468 {
469 // Check if same CellId
470 if (neigh_polytope->neighbor(f_out).state() == IteratorState::valid)
471 if (neigh_polytope->neighbor(f_out)->id() == present_id)
472 return f_out;
473 }
475 }
476 else
477 {
478 // Face is at boundary
480 }
481}
482
483// ------------------------------ inline functions -------------------------
484
485template <int dim, int spacedim>
488
489
490
491template <int dim, int spacedim>
495{
497 if (&(*handler->master_cells_container.end()) == std::addressof(cell))
498 {
499 present_index = handler->master_cells_container.size();
500 master_cell = *handler->master_cells_container.end();
501 present_id = CellId(); // invalid id (TODO)
503 }
504 else
505 {
506 present_index = handler->master2polygon.at(cell->active_cell_index());
507 master_cell = cell;
508 present_id = master_cell->id();
509 present_subdomain_id = master_cell->subdomain_id();
510 }
511}
512
513
514
515template <int dim, int spacedim>
518 const CellId &master_cell_id,
520{
521 Assert(neigh_cell->is_ghost(), ExcInternalError());
522 // neigh_cell is ghosted
523
525 master_cell = neigh_cell;
527 // neigh_cell is ghosted, use the CellId of that agglomerate
528 present_id = master_cell_id;
529 present_subdomain_id = master_cell->subdomain_id();
530}
531
532
533
534template <int dim, int spacedim>
535inline void
537 std::vector<types::global_dof_index> &dof_indices) const
538{
539 Assert(dof_indices.size() > 0,
540 ExcMessage(
541 "The vector of DoFs indices must be already properly resized."));
542 if (is_locally_owned())
543 {
544 // Forward the call to the master cell
545 typename DoFHandler<dim, spacedim>::cell_iterator master_cell_dh(
546 *master_cell, &(handler->agglo_dh));
547 master_cell_dh->get_dof_indices(dof_indices);
548 }
549 else
550 {
551 const std::vector<types::global_dof_index> &recv_dof_indices =
552 handler->recv_ghost_dofs.at(present_subdomain_id).at(present_id);
553
554 std::copy(recv_dof_indices.cbegin(),
555 recv_dof_indices.cend(),
556 dof_indices.begin());
557 }
558}
559
560
561
562template <int dim, int spacedim>
565{
566 auto agglomeration = get_slaves();
567 agglomeration.push_back(master_cell);
568 return agglomeration;
569}
570
571
572
573template <int dim, int spacedim>
574inline const std::vector<typename Triangulation<dim>::active_face_iterator> &
576{
577 return handler->polygon_boundary[master_cell];
578}
579
580
581
582template <int dim, int spacedim>
583inline double
585{
586 Assert(!handler->is_slave_cell(master_cell),
587 ExcMessage("The present function cannot be called for slave cells."));
588
589 if (handler->is_master_cell(master_cell))
590 {
591 // Get the bounding box associated with the master cell
592 const auto &bdary_pts =
593 handler->bboxes[present_index].get_boundary_points();
594 return (bdary_pts.second - bdary_pts.first).norm();
595 }
596 else
597 {
598 // Standard deal.II way to get the measure of a cell.
599 return master_cell->diameter();
600 }
601}
602
603
604
605template <int dim, int spacedim>
606inline const BoundingBox<dim> &
608{
609 if (is_locally_owned())
610 return handler->bboxes[present_index];
611 else
612 return handler->recv_ghosted_bbox.at(present_subdomain_id).at(present_id);
613}
614
615
616
617template <int dim, int spacedim>
618inline double
620{
621 Assert(!handler->is_slave_cell(master_cell),
622 ExcMessage("The present function cannot be called for slave cells."));
623
624 if (handler->is_master_cell(master_cell))
625 {
626 return handler->bboxes[present_index].volume();
627 }
628 else
629 {
630 return master_cell->measure();
631 }
632}
633
634
635
636template <int dim, int spacedim>
637inline void
639{
640 // Increment the present index and update the polytope
642
643 // Make sure not to query the CellId if it's past the last
644 if (present_index < handler->master_cells_container.size())
645 {
646 master_cell = handler->master_cells_container[present_index];
647 present_id = master_cell->id();
648 present_subdomain_id = master_cell->subdomain_id();
649 }
650}
651
652
653
654template <int dim, int spacedim>
655inline void
657{
658 // Decrement the present index and update the polytope
660 master_cell = handler->master_cells_container[present_index];
661 present_id = master_cell->id();
662}
663
664
665template <int dim, int spacedim>
666inline bool
672
673template <int dim, int spacedim>
674inline bool
676 const AgglomerationAccessor<dim, spacedim> &other) const
677{
678 return !(*this == other);
679}
680
681
682
683template <int dim, int spacedim>
689
690
691
692template <int dim, int spacedim>
695 const DoFHandler<dim, spacedim> &dof_handler) const
696{
697 // Forward the call to the master cell using the right DoFHandler.
698 return master_cell->as_dof_handler_iterator(dof_handler);
699}
700
701
702
703template <int dim, int spacedim>
704inline const typename AgglomerationAccessor<dim,
705 spacedim>::AgglomerationContainer &
707{
708 return handler->master2slaves.at(master_cell->active_cell_index());
709}
710
711
712
713template <int dim, int spacedim>
714inline unsigned int
716{
717 AssertThrow(get_agglomerate().size() > 0, ExcMessage("Empty agglomeration."));
718 return get_agglomerate().size();
719}
720
721
722
723template <int dim, int spacedim>
724unsigned int
726{
727 const auto &agglomeration = get_agglomerate();
728 unsigned int n_neighbors = 0;
729 for (const auto &cell : agglomeration)
730 n_neighbors += n_agglomerated_faces_per_cell(cell);
731 return n_neighbors;
732}
733
734
735
736template <int dim, int spacedim>
737inline bool
739{
740 if (master_cell->is_ghost())
741 {
742 const unsigned int sender_rank = master_cell->subdomain_id();
743 // #ifdef AGGLO_DEBUG
744 // const auto & map_recv =
745 // handler->recv_bdary_info.at(sender_rank).at(present_id);
746 // std::cout << "size of map " << map_recv.size() << std::endl;
747 // for (const auto &[face_idx, boundary_or_not] : map_recv)
748 // {
749 // // std::cout << "id: " << face_idx << std::endl;
750 // std::cout << "face: " << face_idx << std::endl;
751 // std::cout << "boundary or not: " << boundary_or_not <<
752 // std::endl;
753 // }
754
755 // std::cout << "il present_id e': " << present_id << "and size "
756 // << map_recv.size() << std::endl;
757 // #endif
758
759 return handler->recv_bdary_info.at(sender_rank).at(present_id).at(f);
760 }
761 else
762 {
763 Assert(!handler->is_slave_cell(master_cell),
764 ExcMessage(
765 "This function should not be called for a slave cell."));
766
767
769 *master_cell, &(handler->agglo_dh));
770 return handler->at_boundary(cell_dh, f);
771 }
772}
773
774
775
776template <int dim, int spacedim>
777inline bool
779{
780 return master_cell->is_locally_owned();
781}
782
783
784
785template <int dim, int spacedim>
786inline CellId
791
792
793
794template <int dim, int spacedim>
800
801template <int dim, int spacedim>
802inline const std::vector<types::global_cell_index> &
804{
805 Assert(!handler->parent_child_info.empty(), ExcInternalError());
806 return handler->parent_child_info.at(
807 {present_index, handler->present_extraction_level});
808}
809
810template <int dim, int spacedim>
811inline const FiniteElement<dim, spacedim> &
813{
815 master_cell_as_dof_handler_iterator =
816 master_cell->as_dof_handler_iterator(handler->agglo_dh);
817 return master_cell_as_dof_handler_iterator->get_fe();
818}
819
820template <int dim, int spacedim>
821inline void
823 const types::fe_index index) const
824{
825 Assert(!handler->is_slave_cell(master_cell),
826 ExcMessage("The present function cannot be called for slave cells."));
828 master_cell_as_dof_handler_iterator =
829 master_cell->as_dof_handler_iterator(handler->agglo_dh);
830 master_cell_as_dof_handler_iterator->set_active_fe_index(index);
831}
832
833template <int dim, int spacedim>
834inline types::fe_index
836{
838 master_cell_as_dof_handler_iterator =
839 master_cell->as_dof_handler_iterator(handler->agglo_dh);
840 return master_cell_as_dof_handler_iterator->active_fe_index();
841}
842
843#endif
const FiniteElement< dim, spacedim > & get_fe(const types::fe_index index=0) const
unsigned int n_agglomerated_faces() const
AgglomerationContainer get_agglomerate() const
types::global_cell_index index() const
~AgglomerationAccessor()=default
std::vector< typename Triangulation< dim, spacedim >::active_cell_iterator > AgglomerationContainer
unsigned int n_agglomerated_faces_per_cell(const typename Triangulation< dim, spacedim >::active_cell_iterator &cell) const
void set_active_fe_index(const types::fe_index index) const
unsigned int n_background_cells() const
unsigned int neighbor_of_agglomerated_neighbor(const unsigned int f) const
AgglomerationAccessor(const typename Triangulation< dim, spacedim >::active_cell_iterator &master_cell, const AgglomerationHandler< dim, spacedim > *ah)
const std::vector< typename Triangulation< dim >::active_face_iterator > & polytope_boundary() const
const AgglomerationIterator< dim, spacedim > neighbor(const unsigned int f) const
bool at_boundary(const unsigned int f) const
const BoundingBox< dim > & get_bounding_box() const
const std::vector< types::global_cell_index > & children() const
bool operator!=(const AgglomerationAccessor< dim, spacedim > &other) const
bool operator==(const AgglomerationAccessor< dim, spacedim > &other) const
const FiniteElement< dim, spacedim > & get_fe() const
AgglomerationHandler< dim, spacedim > * handler
DoFHandler< dim, spacedim >::active_cell_iterator as_dof_handler_iterator(const DoFHandler< dim, spacedim > &dof_handler) const
void get_dof_indices(std::vector< types::global_dof_index > &) const
types::subdomain_id subdomain_id() const
AgglomerationAccessor(const typename Triangulation< dim, spacedim >::active_cell_iterator &cell, const CellId &cell_id, const AgglomerationHandler< dim, spacedim > *ah)
types::fe_index active_fe_index() const
const AgglomerationContainer & get_slaves() const
Triangulation< dim, spacedim >::active_cell_iterator master_cell
unsigned int n_faces() const
typename AgglomerationAccessor< dim, spacedim >::AgglomerationContainer AgglomerationContainer
Point< 2 > second
#define Assert(cond, exc)
#define AssertThrow(cond, exc)
std::size_t size
constexpr unsigned int invalid_unsigned_int
constexpr types::subdomain_id invalid_subdomain_id
unsigned int subdomain_id
unsigned short int fe_index
unsigned int global_cell_index