libMesh
Loading...
Searching...
No Matches
parallel_ghost_sync.h
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
20#ifndef LIBMESH_PARALLEL_GHOST_SYNC_H
21#define LIBMESH_PARALLEL_GHOST_SYNC_H
22
23// libMesh includes
24#include "libmesh/elem.h"
25#include "libmesh/int_range.h"
26#include "libmesh/location_maps.h"
27#include "libmesh/mesh_base.h"
28#include "libmesh/parallel_algebra.h"
29
30// TIMPI includes
31#include "timpi/communicator.h"
32#include "timpi/parallel_sync.h"
33
34// C++ includes
35#include <map> // FIXME - pid > comm.size() breaks with unordered_map
36#include <vector>
37
38
39namespace libMesh
40{
41
42
43
44//--------------------------------------------------------------------------
45namespace Parallel {
46
47//------------------------------------------------------------------------
66template <typename Iterator,
67 typename DofObjType,
68 typename SyncFunctor>
69void sync_dofobject_data_by_xyz(const Communicator & comm,
70 const Iterator & range_begin,
71 const Iterator & range_end,
72 LocationMap<DofObjType> & location_map,
73 SyncFunctor & sync);
74
75//------------------------------------------------------------------------
88template <typename Iterator,
89 typename SyncFunctor>
90void sync_dofobject_data_by_id(const Communicator & comm,
91 const Iterator & range_begin,
92 const Iterator & range_end,
93 SyncFunctor & sync);
94
102template <typename Iterator,
103 typename DofObjectCheckFunctor,
104 typename SyncFunctor>
105void sync_dofobject_data_by_id(const Communicator & comm,
106 const Iterator & range_begin,
107 const Iterator & range_end,
108 const DofObjectCheckFunctor & dofobj_check,
109 SyncFunctor & sync);
110
111//------------------------------------------------------------------------
125template <typename Iterator,
126 typename SyncFunctor>
128 const Iterator & range_begin,
129 const Iterator & range_end,
130 SyncFunctor & sync);
131
132//------------------------------------------------------------------------
162template <typename ElemCheckFunctor,
163 typename NodeCheckFunctor,
164 typename SyncFunctor>
166 const MeshBase::const_element_iterator & range_begin,
167 const MeshBase::const_element_iterator & range_end,
168 const ElemCheckFunctor & elem_check,
169 const NodeCheckFunctor & node_check,
170 SyncFunctor & sync);
171
172
173
174//------------------------------------------------------------------------
209template <typename ElemCheckFunctor,
210 typename NodeCheckFunctor,
211 typename SyncFunctor>
212void sync_node_data_by_element_id(MeshBase & mesh,
213 const MeshBase::const_element_iterator & range_begin,
214 const MeshBase::const_element_iterator & range_end,
215 const ElemCheckFunctor & elem_check,
216 const NodeCheckFunctor & node_check,
217 SyncFunctor & sync);
218
219
220//------------------------------------------------------------------------
221// Parallel members
222
223
224// "Check" Functor to perform sync operations with no exclusions
226{
228
229 bool operator() (const DofObject *) const { return true; }
230
231 bool operator() (const Elem *, unsigned int) const
232 { return true; }
233};
234
235
236
237template <typename Iterator,
238 typename DofObjType,
239 typename SyncFunctor>
241 const Iterator & range_begin,
242 const Iterator & range_end,
243 LocationMap<DofObjType> & location_map,
244 SyncFunctor & sync)
245{
246 // This function must be run on all processors at once
247 libmesh_parallel_only(comm);
248
249 // We need a valid location_map
250#ifdef DEBUG
251 bool need_map_update = (range_begin != range_end && location_map.empty());
252 comm.max(need_map_update);
253 libmesh_assert(!need_map_update);
254#endif
255
256 // Count the objects to ask each processor about
257 std::map<processor_id_type, dof_id_type>
258 ghost_objects_from_proc;
259
260 for (Iterator it = range_begin; it != range_end; ++it)
261 {
262 DofObjType * obj = *it;
263 libmesh_assert (obj);
264 processor_id_type obj_procid = obj->processor_id();
265 if (obj_procid != DofObject::invalid_processor_id)
266 ghost_objects_from_proc[obj_procid]++;
267 }
268
269 // Request sets to send to each processor
270 std::map<processor_id_type, std::vector<Point>>
271 requested_objs_pt;
272 // Corresponding ids to keep track of
273 std::map<processor_id_type, std::vector<dof_id_type>>
274 requested_objs_id;
275
276 // We know how many objects live on each processor, so reserve()
277 // space for each.
278 for (auto pair : ghost_objects_from_proc)
279 {
280 const processor_id_type p = pair.first;
281 if (p != comm.rank())
282 {
283 requested_objs_pt[p].reserve(pair.second);
284 requested_objs_id[p].reserve(pair.second);
285 }
286 }
287
288 for (Iterator it = range_begin; it != range_end; ++it)
289 {
290 DofObjType * obj = *it;
291 processor_id_type obj_procid = obj->processor_id();
292 if (obj_procid == comm.rank() ||
294 continue;
295
296 Point p = location_map.point_of(*obj);
297 requested_objs_pt[obj_procid].push_back(p);
298 requested_objs_id[obj_procid].push_back(obj->id());
299 }
300
301 std::map<const std::vector<Point> *, processor_id_type>
302 requested_objs_pt_inv;
303 for (auto & pair : requested_objs_pt)
304 requested_objs_pt_inv[&pair.second] = pair.first;
305
306 auto gather_functor =
307 [&location_map, &sync]
308 (processor_id_type /*pid*/, const std::vector<Point> & pts,
309 std::vector<typename SyncFunctor::datum> & data)
310 {
311 // Find the local id of each requested object
312 std::size_t query_size = pts.size();
313 std::vector<dof_id_type> query_id(query_size);
314 for (std::size_t i=0; i != query_size; ++i)
315 {
316 Point pt = pts[i];
317
318 // Look for this object in the multimap
319 DofObjType * obj = location_map.find(pt);
320
321 // We'd better find every object we're asked for
322 libmesh_assert (obj);
323
324 // Return the object's correct processor id,
325 // and our (correct if it's local) id for it.
326 query_id[i] = obj->id();
327 }
328
329 // Gather whatever data the user wants
330 sync.gather_data(query_id, data);
331 };
332
333 auto action_functor =
334 [&sync, &requested_objs_id,
335 &requested_objs_pt_inv]
336 (processor_id_type /* pid */, const std::vector<Point> & point_request,
337 const std::vector<typename SyncFunctor::datum> & data)
338 {
339 // With splits working on more pids than ranks, query_pid may not equal pid
340 const processor_id_type query_pid =
341 requested_objs_pt_inv[&point_request];
342
343 // Let the user process the results
344 sync.act_on_data(requested_objs_id[query_pid], data);
345 };
346
347 // Trade requests with other processors
348 typename SyncFunctor::datum * ex = nullptr;
350 (comm, requested_objs_pt, gather_functor, action_functor, ex);
351}
352
353
354
355template <typename Iterator,
356 typename SyncFunctor>
358 const Iterator & range_begin,
359 const Iterator & range_end,
360 SyncFunctor & sync)
361{
362 sync_dofobject_data_by_id(comm, range_begin, range_end, SyncEverything(), sync);
363}
364
365template <typename Iterator,
366 typename DofObjectCheckFunctor,
367 typename SyncFunctor>
369 const Iterator & range_begin,
370 const Iterator & range_end,
371 const DofObjectCheckFunctor & dofobj_check,
372 SyncFunctor & sync)
373{
374 // This function must be run on all processors at once
375 libmesh_parallel_only(comm);
376
377 // Count the objects to ask each processor about
378 std::map<processor_id_type, dof_id_type>
379 ghost_objects_from_proc;
380
381 for (Iterator it = range_begin; it != range_end; ++it)
382 {
383 const DofObject * obj = *it;
384 libmesh_assert (obj);
385
386 // We may want to pass Elem* or Node* to the check function, not
387 // just DofObject*
388 if (!dofobj_check(*it))
389 continue;
390
391 processor_id_type obj_procid = obj->processor_id();
392 if (obj_procid != DofObject::invalid_processor_id)
393 ghost_objects_from_proc[obj_procid]++;
394 }
395
396 // Request sets to send to each processor
397 std::map<processor_id_type, std::vector<dof_id_type>>
398 requested_objs_id;
399
400 // We know how many objects live on each processor, so reserve()
401 // space for each.
402 for (auto pair : ghost_objects_from_proc)
403 {
404 const processor_id_type p = pair.first;
405 if (p != comm.rank())
406 requested_objs_id[p].reserve(pair.second);
407 }
408
409 for (Iterator it = range_begin; it != range_end; ++it)
410 {
411 const DofObject * obj = *it;
412
413 if (!dofobj_check(*it))
414 continue;
415
416 processor_id_type obj_procid = obj->processor_id();
417 if (obj_procid == comm.rank() ||
419 continue;
420
421 requested_objs_id[obj_procid].push_back(obj->id());
422 }
423
424 auto gather_functor =
425 [&sync]
426 (processor_id_type, const std::vector<dof_id_type> & ids,
427 std::vector<typename SyncFunctor::datum> & data)
428 {
429 sync.gather_data(ids, data);
430 };
431
432 auto action_functor =
433 [&sync]
434 (processor_id_type, const std::vector<dof_id_type> & ids,
435 const std::vector<typename SyncFunctor::datum> & data)
436 {
437 // Let the user process the results
438 sync.act_on_data(ids, data);
439 };
440
441 // Trade requests with other processors
442 typename SyncFunctor::datum * ex = nullptr;
444 (comm, requested_objs_id, gather_functor, action_functor, ex);
445}
446
447
448
449// If there's no refined elements, there's nothing to sync
450#ifdef LIBMESH_ENABLE_AMR
451template <typename Iterator,
452 typename SyncFunctor>
454 const Iterator & range_begin,
455 const Iterator & range_end,
456 SyncFunctor & sync)
457{
458 const Communicator & comm (mesh.comm());
459
460 // This function must be run on all processors at once
461 libmesh_parallel_only(comm);
462
463 // Count the objects to ask each processor about
464 std::map<processor_id_type, dof_id_type>
465 ghost_objects_from_proc;
466
467 for (Iterator it = range_begin; it != range_end; ++it)
468 {
469 Elem * elem = *it;
470 processor_id_type obj_procid = elem->processor_id();
471 if (obj_procid == comm.rank() ||
473 continue;
474 const Elem * parent = elem->parent();
475 if (!parent || !elem->active())
476 continue;
477
478 ghost_objects_from_proc[obj_procid]++;
479 }
480
481 // Request sets to send to each processor
482 std::map<processor_id_type, std::vector<dof_id_type>>
483 requested_objs_id;
484 std::map<processor_id_type, std::vector<std::pair<dof_id_type,unsigned char>>>
485 requested_objs_parent_id_child_num;
486
487 // We know how many objects live on each processor, so reserve()
488 // space for each.
489 for (auto pair : ghost_objects_from_proc)
490 {
491 const processor_id_type p = pair.first;
492 if (p != comm.rank())
493 {
494 requested_objs_id[p].reserve(pair.second);
495 requested_objs_parent_id_child_num[p].reserve(pair.second);
496 }
497 }
498
499 for (Iterator it = range_begin; it != range_end; ++it)
500 {
501 Elem * elem = *it;
502 processor_id_type obj_procid = elem->processor_id();
503 if (obj_procid == comm.rank() ||
505 continue;
506 const Elem * parent = elem->parent();
507 if (!parent || !elem->active())
508 continue;
509
510 requested_objs_id[obj_procid].push_back(elem->id());
511 requested_objs_parent_id_child_num[obj_procid].emplace_back
512 (parent->id(), cast_int<unsigned char>(parent->which_child_am_i(elem)));
513 }
514
515 std::map<const std::vector<std::pair<dof_id_type,unsigned char>> *, processor_id_type>
516 requested_objs_parent_id_child_num_inv;
517 for (auto & pair : requested_objs_parent_id_child_num)
518 requested_objs_parent_id_child_num_inv[&pair.second] = pair.first;
519
520 auto gather_functor =
521 [&mesh, &sync]
523 const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num,
524 std::vector<typename SyncFunctor::datum> & data)
525 {
526 // Find the id of each requested element
527 std::size_t query_size = parent_id_child_num.size();
528 std::vector<dof_id_type> query_id(query_size);
529 for (std::size_t i=0; i != query_size; ++i)
530 {
531 Elem & parent = mesh.elem_ref(parent_id_child_num[i].first);
533 Elem * child = parent.child_ptr(parent_id_child_num[i].second);
534 libmesh_assert(child);
535 libmesh_assert(child->active());
536 query_id[i] = child->id();
537 }
538
539 // Gather whatever data the user wants
540 sync.gather_data(query_id, data);
541 };
542
543 auto action_functor =
544 [&sync, &requested_objs_id,
545 &requested_objs_parent_id_child_num_inv]
546 (processor_id_type /* pid */,
547 const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num_request,
548 const std::vector<typename SyncFunctor::datum> & data)
549 {
550 // With splits working on more pids than ranks, query_pid may not equal pid
551 const processor_id_type query_pid =
552 requested_objs_parent_id_child_num_inv[&parent_id_child_num_request];
553
554 // Let the user process the results
555 sync.act_on_data(requested_objs_id[query_pid], data);
556 };
557
558 // Trade requests with other processors
559 typename SyncFunctor::datum * ex = nullptr;
561 (comm, requested_objs_parent_id_child_num, gather_functor,
562 action_functor, ex);
563}
564#else
565template <typename Iterator,
566 typename SyncFunctor>
568 const Iterator &,
569 const Iterator &,
570 SyncFunctor &)
571{
572}
573#endif // LIBMESH_ENABLE_AMR
574
575
576
577template <typename ElemCheckFunctor,
578 typename NodeCheckFunctor,
579 typename SyncFunctor>
581 const MeshBase::const_element_iterator & range_begin,
582 const MeshBase::const_element_iterator & range_end,
583 const ElemCheckFunctor & elem_check,
584 const NodeCheckFunctor & node_check,
585 SyncFunctor & sync)
586{
587 const Communicator & comm (mesh.comm());
588
589 // Count the objects to ask each processor about
590 std::map<processor_id_type, dof_id_type>
591 ghost_objects_from_proc;
592
593 for (const auto & elem : as_range(range_begin, range_end))
594 {
595 libmesh_assert (elem);
596
597 if (!elem_check(elem))
598 continue;
599
600 const processor_id_type proc_id = elem->processor_id();
601
602 bool i_have_elem =
603 (proc_id == comm.rank() ||
605
606 if (elem->active() && i_have_elem)
607 continue;
608
609 for (auto n : elem->node_index_range())
610 {
611 if (!node_check(elem, n))
612 continue;
613
614 const processor_id_type node_pid =
615 elem->node_ref(n).processor_id();
616
617 if (i_have_elem && (node_pid == comm.rank()))
618 continue;
619
620 if (i_have_elem)
621 {
622 libmesh_assert_not_equal_to
624 ghost_objects_from_proc[node_pid]++;
625 }
626 else
627 {
628 const processor_id_type request_pid =
629 (node_pid == DofObject::invalid_processor_id) ?
630 proc_id : node_pid;
631 ghost_objects_from_proc[request_pid]++;
632 }
633 }
634 }
635
636 // Now repeat that iteration, filling request sets this time.
637
638 // Request sets to send to each processor
639 std::map<processor_id_type, std::vector<std::pair<dof_id_type, unsigned char>>>
640 requested_objs_elem_id_node_num;
641
642 // We know how many objects live on each processor, so reserve()
643 // space for each.
644 for (auto pair : ghost_objects_from_proc)
645 {
646 const processor_id_type p = pair.first;
647 if (p != comm.rank())
648 requested_objs_elem_id_node_num[p].reserve(ghost_objects_from_proc[p]);
649 }
650
651 for (const auto & elem : as_range(range_begin, range_end))
652 {
653 libmesh_assert (elem);
654
655 if (!elem_check(elem))
656 continue;
657
658 const processor_id_type proc_id = elem->processor_id();
659
660 bool i_have_elem =
661 (proc_id == comm.rank() ||
663
664 if (elem->active() && i_have_elem)
665 continue;
666
667 const dof_id_type elem_id = elem->id();
668
669 for (auto n : elem->node_index_range())
670 {
671 if (!node_check(elem, n))
672 continue;
673
674 const Node & node = elem->node_ref(n);
675 const processor_id_type node_pid = node.processor_id();
676
677 if (i_have_elem && (node_pid == comm.rank()))
678 continue;
679
680 if (i_have_elem)
681 {
682 libmesh_assert_not_equal_to
684 requested_objs_elem_id_node_num[node_pid].emplace_back
685 (elem_id, cast_int<unsigned char>(n));
686 }
687 else
688 {
689 const processor_id_type request_pid =
690 (node_pid == DofObject::invalid_processor_id) ?
691 proc_id : node_pid;
692 requested_objs_elem_id_node_num[request_pid].emplace_back
693 (elem_id,cast_int<unsigned char>(n));
694 }
695 }
696 }
697
698 auto gather_functor =
699 [&mesh, &sync]
701 const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
702 std::vector<typename SyncFunctor::datum> & data)
703 {
704 // Find the id of each requested element
705 std::size_t request_size = elem_id_node_num.size();
706 std::vector<dof_id_type> query_id(request_size);
707 for (std::size_t i=0; i != request_size; ++i)
708 {
709 // We might now get queries about remote elements, in which
710 // case we'll have to ignore them and wait for the query
711 // answer to filter to the querier via another source.
712 const Elem * elem = mesh.query_elem_ptr(elem_id_node_num[i].first);
713
714 if (elem)
715 {
716 const unsigned int n = elem_id_node_num[i].second;
717 libmesh_assert_less (n, elem->n_nodes());
718
719 const Node & node = elem->node_ref(n);
720
721 // This isn't a safe assertion in the case where we're
722 // syncing processor ids
723 // libmesh_assert_equal_to (node->processor_id(), comm.rank());
724
725 query_id[i] = node.id();
726 }
727 else
728 query_id[i] = DofObject::invalid_id;
729 }
730
731 // Gather whatever data the user wants
732 sync.gather_data(query_id, data);
733 };
734
735 bool data_changed = false;
736
737 auto action_functor =
738 [&sync, &mesh, &data_changed]
739 (processor_id_type /* pid */,
740 const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
741 const std::vector<typename SyncFunctor::datum> & data)
742 {
743 const std::size_t data_size = data.size();
744
745 libmesh_assert_equal_to(elem_id_node_num.size(), data_size);
746
747 std::vector<dof_id_type> requested_objs_id(data.size());
748
749 for (auto i : IntRange<std::size_t>(0,data_size))
750 {
751 const Elem & elem = mesh.elem_ref(elem_id_node_num[i].first);
752 const Node & node = elem.node_ref(elem_id_node_num[i].second);
753 requested_objs_id[i] = node.id();
754 }
755
756 // Let the user process the results. If any of the results
757 // were different than what the user expected, then we may
758 // need to sync again just in case this processor has to
759 // pass on the changes to yet another processor.
760 if (sync.act_on_data(requested_objs_id, data))
761 data_changed = true;
762 };
763
764 // Trade requests with other processors
765 typename SyncFunctor::datum * ex = nullptr;
767 (comm, requested_objs_elem_id_node_num, gather_functor,
768 action_functor, ex);
769
770 comm.max(data_changed);
771
772 return data_changed;
773}
774
775
776
777template <typename ElemCheckFunctor,
778 typename NodeCheckFunctor,
779 typename SyncFunctor>
781 const MeshBase::const_element_iterator & range_begin,
782 const MeshBase::const_element_iterator & range_end,
783 const ElemCheckFunctor & elem_check,
784 const NodeCheckFunctor & node_check,
785 SyncFunctor & sync)
786{
787 // This function must be run on all processors at once
788 libmesh_parallel_only(mesh.comm());
789
790 bool need_sync = false;
791
792 do
793 {
794 need_sync =
796 (mesh, range_begin, range_end, elem_check, node_check,
797 sync);
798 } while (need_sync);
799}
800
801
802}
803
804
805
806// This struct can be created and passed to the
807// Parallel::sync_dofobject_data_by_id() function.
809{
810 // The constructor. You need a reference to the mesh where you will
811 // be setting/getting nodal positions.
812 explicit
814
815 // The datum typedef is required of this functor, so that the
816 // Parallel::sync_dofobject_data_by_id() function can create e.g.
817 // std::vector<datum>.
818 typedef Point datum;
819
820 // First required interface. This function must fill up the data vector for the
821 // ids specified in the ids vector.
822 void gather_data (const std::vector<dof_id_type> & ids, std::vector<datum> & data) const;
823
824 // Second required interface. This function must do something with the data in
825 // the data vector for the ids in the ids vector.
826 void act_on_data (const std::vector<dof_id_type> & ids, const std::vector<datum> & data) const;
827
829};
830
831// This struct can be created and passed to the
832// Parallel::sync_dofobject_data_by_id() function.
834{
835 // The constructor. You need a reference to the mesh where you will
836 // be setting/getting element subdomain IDs.
837 explicit
839
840 // The datum typedef is required of this functor, so that the
841 // Parallel::sync_dofobject_data_by_id() function can create e.g.
842 // std::vector<datum>.
844
845 // First required interface. This function must fill up the data vector for the
846 // ids specified in the ids vector.
847 void gather_data (const std::vector<dof_id_type> & ids, std::vector<datum> & data) const;
848
849 // Second required interface. This function must do something with the data in
850 // the data vector for the ids in the ids vector.
851 void act_on_data (const std::vector<dof_id_type> & ids, const std::vector<datum> & data) const;
852
854};
855
856// This struct can be created and passed to the
857// Parallel::sync_dofobject_data_by_id() function
858// for sync element integers.
860{
861 // The constructor. You need a reference to the mesh where you will
862 // be setting/getting element integers and an existing element integer name.
863 explicit
864 SyncElementIntegers(MeshBase & m, const std::string & integer_name);
865
866 // The datum typedef is required of this functor, so that the
867 // Parallel::sync_dofobject_data_by_id() function can create e.g.
868 // std::vector<datum>.
870
871 // First required interface. This function must fill up the data vector for the
872 // ids specified in the ids vector.
873 void gather_data(const std::vector<dof_id_type> & ids, std::vector<datum> & data) const;
874
875 // Second required interface. This function must do something with the data in
876 // the data vector for the ids in the ids vector.
877 void act_on_data(const std::vector<dof_id_type> & ids, const std::vector<datum> & data) const;
878
880 unsigned int ind;
881};
882
883} // namespace libMesh
884
885#endif // LIBMESH_PARALLEL_GHOST_SYNC_H
void max(const T &r, T &o, Request &req) const
processor_id_type rank() const
The DofObject defines an abstract base class for objects that have degrees of freedom associated with...
Definition dof_object.h:55
processor_id_type processor_id() const
Definition dof_object.h:881
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition dof_object.h:473
dof_id_type id() const
Definition dof_object.h:819
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition dof_object.h:484
This is the base class from which all geometric element types are derived.
Definition elem.h:96
bool active() const
Definition elem.h:2958
const Node & node_ref(const unsigned int i) const
Definition elem.h:2538
bool has_children() const
Definition elem.h:2996
virtual unsigned int n_nodes() const =0
const Elem * parent() const
Definition elem.h:3047
const Elem * child_ptr(unsigned int i) const
Definition elem.h:3180
unsigned int which_child_am_i(const Elem *e) const
Definition elem.h:3209
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
Definition int_range.h:54
Data structures that enable location-based lookups The key is a hash of the Point location.
Point point_of(const T &) const
T * find(const Point &, const Real tol=TOLERANCE)
This is the MeshBase class.
Definition mesh_base.h:81
A Node is like a Point, but with more information.
Definition node.h:55
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
MeshBase & mesh
void pull_parallel_vector_data(const Communicator &comm, const MapToVectors &queries, GatherFunctor &gather_data, const ActionFunctor &act_on_data, const datum *example)
uint8_t processor_id_type
void sync_element_data_by_parent_id(MeshBase &mesh, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost elements uniquely identified by their parent id and which child t...
bool sync_node_data_by_element_id_once(MeshBase &mesh, const MeshBase::const_element_iterator &range_begin, const MeshBase::const_element_iterator &range_end, const ElemCheckFunctor &elem_check, const NodeCheckFunctor &node_check, SyncFunctor &sync)
Synchronize data about a range of ghost nodes uniquely identified by an element id and local node id,...
void sync_node_data_by_element_id(MeshBase &mesh, const MeshBase::const_element_iterator &range_begin, const MeshBase::const_element_iterator &range_end, const ElemCheckFunctor &elem_check, const NodeCheckFunctor &node_check, SyncFunctor &sync)
Synchronize data about a range of ghost nodes uniquely identified by an element id and local node id,...
void sync_dofobject_data_by_xyz(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, LocationMap< DofObjType > &location_map, SyncFunctor &sync)
Request data about a range of ghost nodes uniquely identified by their xyz location or a range of act...
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
The libMesh namespace provides an interface to certain functionality in the library.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67
The definition of the const_element_iterator struct.
Definition mesh_base.h:2556
bool operator()(const DofObject *) const
void act_on_data(const std::vector< dof_id_type > &ids, const std::vector< datum > &data) const
void gather_data(const std::vector< dof_id_type > &ids, std::vector< datum > &data) const
void act_on_data(const std::vector< dof_id_type > &ids, const std::vector< datum > &data) const
void gather_data(const std::vector< dof_id_type > &ids, std::vector< datum > &data) const
void act_on_data(const std::vector< dof_id_type > &ids, const std::vector< datum > &data) const
void gather_data(const std::vector< dof_id_type > &ids, std::vector< datum > &data) const