20 #ifndef LIBMESH_PARALLEL_GHOST_SYNC_H
21 #define LIBMESH_PARALLEL_GHOST_SYNC_H
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"
60 template <
typename Iterator,
64 const Iterator & range_begin,
65 const Iterator & range_end,
66 LocationMap<DofObjType> * location_map,
82 template <
typename Iterator,
85 const Iterator & range_begin,
86 const Iterator & range_end,
96 template <
typename Iterator,
97 typename DofObjectCheckFunctor,
100 const Iterator & range_begin,
101 const Iterator & range_end,
102 const DofObjectCheckFunctor & dofobj_check,
119 template <
typename Iterator,
120 typename SyncFunctor>
122 const Iterator & range_begin,
123 const Iterator & range_end,
156 template <
typename ElemCheckFunctor,
157 typename NodeCheckFunctor,
158 typename SyncFunctor>
160 const MeshBase::const_element_iterator & range_begin,
161 const MeshBase::const_element_iterator & range_end,
162 const ElemCheckFunctor & elem_check,
163 const NodeCheckFunctor & node_check,
203 template <
typename ElemCheckFunctor,
204 typename NodeCheckFunctor,
205 typename SyncFunctor>
207 const MeshBase::const_element_iterator & range_begin,
208 const MeshBase::const_element_iterator & range_end,
209 const ElemCheckFunctor & elem_check,
210 const NodeCheckFunctor & node_check,
231 template <
typename Iterator,
233 typename SyncFunctor>
235 const Iterator & range_begin,
236 const Iterator & range_end,
241 libmesh_parallel_only(comm);
245 bool need_map_update = (range_begin != range_end && location_map.
empty());
246 comm.max(need_map_update);
251 std::vector<dof_id_type>
252 ghost_objects_from_proc(comm.size(), 0);
254 for (Iterator it = range_begin; it != range_end; ++it)
256 DofObjType * obj = *it;
260 ghost_objects_from_proc[obj_procid]++;
264 std::map<processor_id_type, std::vector<Point>>
267 std::map<processor_id_type, std::vector<dof_id_type>>
273 if (p != comm.rank() && ghost_objects_from_proc[p])
275 requested_objs_pt[p].reserve(ghost_objects_from_proc[p]);
276 requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
279 for (Iterator it = range_begin; it != range_end; ++it)
281 DofObjType * obj = *it;
283 if (obj_procid == comm.rank() ||
288 requested_objs_pt[obj_procid].push_back(p);
289 requested_objs_id[obj_procid].push_back(obj->id());
292 auto gather_functor =
293 [&location_map, &sync]
295 std::vector<typename SyncFunctor::datum> &
data)
298 std::size_t query_size = pts.
size();
299 std::vector<dof_id_type> query_id(query_size);
300 for (std::size_t i=0; i != query_size; ++i)
305 DofObjType * obj = location_map.
find(pt);
312 query_id[i] = obj->id();
316 sync.gather_data(query_id,
data);
319 auto action_functor =
320 [&sync, &requested_objs_id]
322 const std::vector<typename SyncFunctor::datum> &
data)
325 sync.act_on_data(requested_objs_id[pid],
data);
329 typename SyncFunctor::datum * ex =
nullptr;
330 pull_parallel_vector_data
331 (comm, requested_objs_pt, gather_functor, action_functor, ex);
336 template <
typename Iterator,
337 typename SyncFunctor>
339 const Iterator & range_begin,
340 const Iterator & range_end,
346 template <
typename Iterator,
347 typename DofObjectCheckFunctor,
348 typename SyncFunctor>
350 const Iterator & range_begin,
351 const Iterator & range_end,
352 const DofObjectCheckFunctor & dofobj_check,
356 libmesh_parallel_only(comm);
359 std::vector<dof_id_type>
360 ghost_objects_from_proc(comm.size(), 0);
362 for (Iterator it = range_begin; it != range_end; ++it)
369 if (!dofobj_check(*it))
374 ghost_objects_from_proc[obj_procid]++;
378 std::map<processor_id_type, std::vector<dof_id_type>>
384 if (p != comm.rank() && ghost_objects_from_proc[p])
385 requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
387 for (Iterator it = range_begin; it != range_end; ++it)
391 if (!dofobj_check(*it))
395 if (obj_procid == comm.rank() ||
399 requested_objs_id[obj_procid].push_back(obj->
id());
402 auto gather_functor =
405 std::vector<typename SyncFunctor::datum> &
data)
407 sync.gather_data(ids,
data);
410 auto action_functor =
413 const std::vector<typename SyncFunctor::datum> &
data)
416 sync.act_on_data(ids,
data);
420 typename SyncFunctor::datum * ex =
nullptr;
421 pull_parallel_vector_data
422 (comm, requested_objs_id, gather_functor, action_functor, ex);
428 #ifdef LIBMESH_ENABLE_AMR
429 template <
typename Iterator,
430 typename SyncFunctor>
432 const Iterator & range_begin,
433 const Iterator & range_end,
436 const Communicator & comm (
mesh.comm());
439 libmesh_parallel_only(comm);
442 std::vector<dof_id_type>
443 ghost_objects_from_proc(comm.size(), 0);
445 for (Iterator it = range_begin; it != range_end; ++it)
449 if (obj_procid == comm.rank() ||
453 if (!parent || !elem->
active())
456 ghost_objects_from_proc[obj_procid]++;
460 std::map<processor_id_type, std::vector<dof_id_type>>
462 std::map<processor_id_type, std::vector<std::pair<dof_id_type,unsigned char>>>
463 requested_objs_parent_id_child_num;
468 if (p != comm.rank() && ghost_objects_from_proc[p])
470 requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
471 requested_objs_parent_id_child_num[p].reserve(ghost_objects_from_proc[p]);
474 for (Iterator it = range_begin; it != range_end; ++it)
478 if (obj_procid == comm.rank() ||
482 if (!parent || !elem->
active())
485 requested_objs_id[obj_procid].push_back(elem->
id());
486 requested_objs_parent_id_child_num[obj_procid].push_back
489 cast_int<unsigned char>
493 auto gather_functor =
496 const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num,
497 std::vector<typename SyncFunctor::datum> &
data)
500 std::size_t query_size = parent_id_child_num.size();
501 std::vector<dof_id_type> query_id(query_size);
502 for (std::size_t i=0; i != query_size; ++i)
504 Elem & parent =
mesh.elem_ref(parent_id_child_num[i].first);
506 Elem * child = parent.
child_ptr(parent_id_child_num[i].second);
509 query_id[i] = child->id();
513 sync.gather_data(query_id,
data);
516 auto action_functor =
517 [&sync, &requested_objs_id]
519 const std::vector<std::pair<dof_id_type, unsigned char>> &,
520 const std::vector<typename SyncFunctor::datum> &
data)
523 sync.act_on_data(requested_objs_id[pid],
data);
527 typename SyncFunctor::datum * ex =
nullptr;
528 pull_parallel_vector_data
529 (comm, requested_objs_parent_id_child_num, gather_functor,
533 template <
typename Iterator,
534 typename SyncFunctor>
541 #endif // LIBMESH_ENABLE_AMR
545 template <
typename ElemCheckFunctor,
546 typename NodeCheckFunctor,
547 typename SyncFunctor>
551 const ElemCheckFunctor & elem_check,
552 const NodeCheckFunctor & node_check,
555 const Communicator & comm (
mesh.comm());
558 std::vector<dof_id_type>
559 ghost_objects_from_proc(comm.size(), 0);
561 for (
const auto & elem :
as_range(range_begin, range_end))
565 if (!elem_check(elem))
571 (proc_id == comm.rank() ||
574 if (elem->active() && i_have_elem)
577 for (
auto n : elem->node_index_range())
579 if (!node_check(elem, n))
583 elem->node_ref(n).processor_id();
585 if (i_have_elem && (node_pid == comm.rank()))
590 libmesh_assert_not_equal_to
592 ghost_objects_from_proc[node_pid]++;
599 ghost_objects_from_proc[request_pid]++;
607 std::map<processor_id_type, std::vector<std::pair<dof_id_type, unsigned char>>>
608 requested_objs_elem_id_node_num;
613 if (p != comm.rank() && ghost_objects_from_proc[p])
615 requested_objs_elem_id_node_num[p].reserve(ghost_objects_from_proc[p]);
618 for (
const auto & elem :
as_range(range_begin, range_end))
622 if (!elem_check(elem))
628 (proc_id == comm.rank() ||
631 if (elem->active() && i_have_elem)
636 for (
auto n : elem->node_index_range())
638 if (!node_check(elem, n))
641 const Node & node = elem->node_ref(n);
644 if (i_have_elem && (node_pid == comm.rank()))
649 libmesh_assert_not_equal_to
651 requested_objs_elem_id_node_num[node_pid].push_back
654 cast_int<unsigned char>(n)));
661 requested_objs_elem_id_node_num[request_pid].push_back
664 cast_int<unsigned char>(n)));
669 auto gather_functor =
672 const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
673 std::vector<typename SyncFunctor::datum> &
data)
676 std::size_t request_size = elem_id_node_num.size();
677 std::vector<dof_id_type> query_id(request_size);
678 for (std::size_t i=0; i != request_size; ++i)
683 const Elem * elem =
mesh.query_elem_ptr(elem_id_node_num[i].first);
687 const unsigned int n = elem_id_node_num[i].second;
688 libmesh_assert_less (n, elem->
n_nodes());
696 query_id[i] = node.
id();
703 sync.gather_data(query_id,
data);
706 bool data_changed =
false;
708 auto action_functor =
709 [&sync, &
mesh, &requested_objs_elem_id_node_num, &data_changed]
711 const std::vector<std::pair<dof_id_type, unsigned char>> &,
712 const std::vector<typename SyncFunctor::datum> &
data)
714 const auto & elem_id_node_num =
715 requested_objs_elem_id_node_num[pid];
717 const std::size_t data_size =
data.size();
719 libmesh_assert_equal_to(elem_id_node_num.size(), data_size);
721 std::vector<dof_id_type> requested_objs_id(
data.size());
725 const Elem & elem =
mesh.elem_ref(elem_id_node_num[i].first);
726 const Node & node = elem.
node_ref(elem_id_node_num[i].second);
727 requested_objs_id[i] = node.
id();
734 if (sync.act_on_data(requested_objs_id,
data))
739 typename SyncFunctor::datum * ex =
nullptr;
740 pull_parallel_vector_data
741 (comm, requested_objs_elem_id_node_num, gather_functor,
744 comm.max(data_changed);
751 template <
typename ElemCheckFunctor,
752 typename NodeCheckFunctor,
753 typename SyncFunctor>
757 const ElemCheckFunctor & elem_check,
758 const NodeCheckFunctor & node_check,
762 libmesh_parallel_only(
mesh.comm());
764 bool need_sync =
false;
770 (
mesh, range_begin, range_end, elem_check, node_check,
796 void gather_data (
const std::vector<dof_id_type> & ids, std::vector<datum> &
data)
const;
800 void act_on_data (
const std::vector<dof_id_type> & ids,
const std::vector<datum> &
data)
const;
808 #endif // LIBMESH_PARALLEL_GHOST_SYNC_H