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"
66template <
typename Iterator,
70 const Iterator & range_begin,
71 const Iterator & range_end,
72 LocationMap<DofObjType> & location_map,
88template <
typename Iterator,
91 const Iterator & range_begin,
92 const Iterator & range_end,
102template <
typename Iterator,
103 typename DofObjectCheckFunctor,
104 typename SyncFunctor>
106 const Iterator & range_begin,
107 const Iterator & range_end,
108 const DofObjectCheckFunctor & dofobj_check,
125template <
typename Iterator,
126 typename SyncFunctor>
128 const Iterator & range_begin,
129 const Iterator & range_end,
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,
209template <
typename ElemCheckFunctor,
210 typename NodeCheckFunctor,
211 typename SyncFunctor>
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,
237template <
typename Iterator,
239 typename SyncFunctor>
241 const Iterator & range_begin,
242 const Iterator & range_end,
247 libmesh_parallel_only(comm);
251 bool need_map_update = (range_begin != range_end && location_map.
empty());
252 comm.
max(need_map_update);
257 std::map<processor_id_type, dof_id_type>
258 ghost_objects_from_proc;
260 for (Iterator it = range_begin; it != range_end; ++it)
262 DofObjType * obj = *it;
266 ghost_objects_from_proc[obj_procid]++;
270 std::map<processor_id_type, std::vector<Point>>
273 std::map<processor_id_type, std::vector<dof_id_type>>
278 for (
auto pair : ghost_objects_from_proc)
281 if (p != comm.
rank())
283 requested_objs_pt[p].reserve(pair.second);
284 requested_objs_id[p].reserve(pair.second);
288 for (Iterator it = range_begin; it != range_end; ++it)
290 DofObjType * obj = *it;
292 if (obj_procid == comm.
rank() ||
297 requested_objs_pt[obj_procid].push_back(p);
298 requested_objs_id[obj_procid].push_back(obj->id());
302 requested_objs_pt_inv;
303 for (
auto & pair : requested_objs_pt)
304 requested_objs_pt_inv[&pair.second] = pair.first;
306 auto gather_functor =
307 [&location_map, &sync]
309 std::vector<typename SyncFunctor::datum> & data)
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)
319 DofObjType * obj = location_map.
find(pt);
326 query_id[i] = obj->id();
330 sync.gather_data(query_id, data);
333 auto action_functor =
334 [&sync, &requested_objs_id,
335 &requested_objs_pt_inv]
337 const std::vector<typename SyncFunctor::datum> & data)
341 requested_objs_pt_inv[&point_request];
344 sync.act_on_data(requested_objs_id[query_pid], data);
348 typename SyncFunctor::datum * ex =
nullptr;
350 (comm, requested_objs_pt, gather_functor, action_functor, ex);
355template <
typename Iterator,
356 typename SyncFunctor>
358 const Iterator & range_begin,
359 const Iterator & range_end,
365template <
typename Iterator,
366 typename DofObjectCheckFunctor,
367 typename SyncFunctor>
369 const Iterator & range_begin,
370 const Iterator & range_end,
371 const DofObjectCheckFunctor & dofobj_check,
375 libmesh_parallel_only(comm);
378 std::map<processor_id_type, dof_id_type>
379 ghost_objects_from_proc;
381 for (Iterator it = range_begin; it != range_end; ++it)
388 if (!dofobj_check(*it))
393 ghost_objects_from_proc[obj_procid]++;
397 std::map<processor_id_type, std::vector<dof_id_type>>
402 for (
auto pair : ghost_objects_from_proc)
405 if (p != comm.
rank())
406 requested_objs_id[p].reserve(pair.second);
409 for (Iterator it = range_begin; it != range_end; ++it)
413 if (!dofobj_check(*it))
417 if (obj_procid == comm.
rank() ||
421 requested_objs_id[obj_procid].push_back(obj->
id());
424 auto gather_functor =
427 std::vector<typename SyncFunctor::datum> & data)
429 sync.gather_data(ids, data);
432 auto action_functor =
435 const std::vector<typename SyncFunctor::datum> & data)
438 sync.act_on_data(ids, data);
442 typename SyncFunctor::datum * ex =
nullptr;
444 (comm, requested_objs_id, gather_functor, action_functor, ex);
450#ifdef LIBMESH_ENABLE_AMR
451template <
typename Iterator,
452 typename SyncFunctor>
454 const Iterator & range_begin,
455 const Iterator & range_end,
461 libmesh_parallel_only(comm);
464 std::map<processor_id_type, dof_id_type>
465 ghost_objects_from_proc;
467 for (Iterator it = range_begin; it != range_end; ++it)
471 if (obj_procid == comm.
rank() ||
475 if (!parent || !elem->
active())
478 ghost_objects_from_proc[obj_procid]++;
482 std::map<processor_id_type, std::vector<dof_id_type>>
484 std::map<processor_id_type, std::vector<std::pair<dof_id_type,unsigned char>>>
485 requested_objs_parent_id_child_num;
489 for (
auto pair : ghost_objects_from_proc)
492 if (p != comm.
rank())
494 requested_objs_id[p].reserve(pair.second);
495 requested_objs_parent_id_child_num[p].reserve(pair.second);
499 for (Iterator it = range_begin; it != range_end; ++it)
503 if (obj_procid == comm.
rank() ||
507 if (!parent || !elem->
active())
510 requested_objs_id[obj_procid].push_back(elem->
id());
511 requested_objs_parent_id_child_num[obj_procid].emplace_back
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;
520 auto gather_functor =
523 const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num,
524 std::vector<typename SyncFunctor::datum> & data)
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)
531 Elem & parent =
mesh.elem_ref(parent_id_child_num[i].first);
533 Elem * child = parent.
child_ptr(parent_id_child_num[i].second);
536 query_id[i] = child->
id();
540 sync.gather_data(query_id, data);
543 auto action_functor =
544 [&sync, &requested_objs_id,
545 &requested_objs_parent_id_child_num_inv]
547 const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num_request,
548 const std::vector<typename SyncFunctor::datum> & data)
552 requested_objs_parent_id_child_num_inv[&parent_id_child_num_request];
555 sync.act_on_data(requested_objs_id[query_pid], data);
559 typename SyncFunctor::datum * ex =
nullptr;
561 (comm, requested_objs_parent_id_child_num, gather_functor,
565template <
typename Iterator,
566 typename SyncFunctor>
577template <
typename ElemCheckFunctor,
578 typename NodeCheckFunctor,
579 typename SyncFunctor>
583 const ElemCheckFunctor & elem_check,
584 const NodeCheckFunctor & node_check,
590 std::map<processor_id_type, dof_id_type>
591 ghost_objects_from_proc;
593 for (
const auto & elem :
as_range(range_begin, range_end))
597 if (!elem_check(elem))
603 (proc_id == comm.
rank() ||
606 if (elem->active() && i_have_elem)
609 for (
auto n : elem->node_index_range())
611 if (!node_check(elem, n))
615 elem->node_ref(n).processor_id();
617 if (i_have_elem && (node_pid == comm.
rank()))
622 libmesh_assert_not_equal_to
624 ghost_objects_from_proc[node_pid]++;
631 ghost_objects_from_proc[request_pid]++;
639 std::map<processor_id_type, std::vector<std::pair<dof_id_type, unsigned char>>>
640 requested_objs_elem_id_node_num;
644 for (
auto pair : ghost_objects_from_proc)
647 if (p != comm.
rank())
648 requested_objs_elem_id_node_num[p].reserve(ghost_objects_from_proc[p]);
651 for (
const auto & elem :
as_range(range_begin, range_end))
655 if (!elem_check(elem))
661 (proc_id == comm.
rank() ||
664 if (elem->active() && i_have_elem)
669 for (
auto n : elem->node_index_range())
671 if (!node_check(elem, n))
674 const Node & node = elem->node_ref(n);
677 if (i_have_elem && (node_pid == comm.
rank()))
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));
692 requested_objs_elem_id_node_num[request_pid].emplace_back
693 (elem_id,cast_int<unsigned char>(n));
698 auto gather_functor =
701 const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
702 std::vector<typename SyncFunctor::datum> & data)
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)
712 const Elem * elem =
mesh.query_elem_ptr(elem_id_node_num[i].first);
716 const unsigned int n = elem_id_node_num[i].second;
717 libmesh_assert_less (n, elem->
n_nodes());
725 query_id[i] = node.
id();
732 sync.gather_data(query_id, data);
735 bool data_changed =
false;
737 auto action_functor =
738 [&sync, &
mesh, &data_changed]
740 const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
741 const std::vector<typename SyncFunctor::datum> & data)
743 const std::size_t data_size = data.size();
745 libmesh_assert_equal_to(elem_id_node_num.size(), data_size);
747 std::vector<dof_id_type> requested_objs_id(data.size());
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();
760 if (sync.act_on_data(requested_objs_id, data))
765 typename SyncFunctor::datum * ex =
nullptr;
767 (comm, requested_objs_elem_id_node_num, gather_functor,
770 comm.
max(data_changed);
777template <
typename ElemCheckFunctor,
778 typename NodeCheckFunctor,
779 typename SyncFunctor>
783 const ElemCheckFunctor & elem_check,
784 const NodeCheckFunctor & node_check,
788 libmesh_parallel_only(
mesh.comm());
790 bool need_sync =
false;
796 (
mesh, range_begin, range_end, elem_check, node_check,
822 void gather_data (
const std::vector<dof_id_type> & ids, std::vector<datum> & data)
const;
826 void act_on_data (
const std::vector<dof_id_type> & ids,
const std::vector<datum> & data)
const;
847 void gather_data (
const std::vector<dof_id_type> & ids, std::vector<datum> & data)
const;
851 void act_on_data (
const std::vector<dof_id_type> & ids,
const std::vector<datum> & data)
const;
873 void gather_data(
const std::vector<dof_id_type> & ids, std::vector<datum> & data)
const;
877 void act_on_data(
const std::vector<dof_id_type> & ids,
const std::vector<datum> & data)
const;
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...
processor_id_type processor_id() const
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
This is the base class from which all geometric element types are derived.
const Node & node_ref(const unsigned int i) const
bool has_children() const
virtual unsigned int n_nodes() const =0
const Elem * parent() const
const Elem * child_ptr(unsigned int i) const
unsigned int which_child_am_i(const Elem *e) const
The IntRange templated class is intended to make it easy to loop over integers which are indices of a...
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.
A Node is like a Point, but with more information.
A Point defines a location in LIBMESH_DIM dimensional Real space.
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.
The definition of the const_element_iterator struct.
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