libMesh
Namespaces | Classes | Typedefs | Functions
libMesh::Parallel Namespace Reference

Namespaces

 Utils
 

Classes

class  BinSorter
 Perform a parallel sort using a bin-sort method. More...
 
class  Histogram
 Defines a histogram to be used in parallel in conjunction with a BinSorter. More...
 
class  Packing< const Elem * >
 
class  Packing< const Node * >
 
class  Packing< Elem * >
 
class  Packing< Node * >
 
class  Packing< std::basic_string< T > >
 
class  Sort
 The parallel sorting method is templated on the type of data which is to be sorted. More...
 
struct  SyncEverything
 

Typedefs

typedef std::pair< Hilbert::HilbertIndices, unique_id_typeDofObjectKey
 

Functions

template<typename Iterator , typename DofObjType , typename SyncFunctor >
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 active ghost elements uniquely identified by their centroids' xyz location. More...
 
template<typename Iterator , typename SyncFunctor >
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. More...
 
template<typename Iterator , typename DofObjectCheckFunctor , typename SyncFunctor >
void sync_dofobject_data_by_id (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, const DofObjectCheckFunctor &dofobj_check, SyncFunctor &sync)
 Request data about a range of ghost dofobjects uniquely identified by their id. More...
 
template<typename Iterator , typename SyncFunctor >
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 they are. More...
 
template<typename ElemCheckFunctor , typename NodeCheckFunctor , typename SyncFunctor >
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, assuming a single synchronization pass is necessary. More...
 
template<typename ElemCheckFunctor , typename NodeCheckFunctor , typename SyncFunctor >
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, iterating until data is completely in sync and futher synchronization passes cause no changes. More...
 
template<typename Iterator , typename DofObjType , typename SyncFunctor >
void sync_dofobject_data_by_xyz (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, LocationMap< DofObjType > &location_map, SyncFunctor &sync)
 

Typedef Documentation

◆ DofObjectKey

typedef Hilbert::HilbertIndices libMesh::Parallel::DofObjectKey

Definition at line 77 of file parallel_hilbert.h.

Function Documentation

◆ sync_dofobject_data_by_id() [1/2]

template<typename Iterator , typename DofObjectCheckFunctor , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_id ( const Communicator &  comm,
const Iterator &  range_begin,
const Iterator &  range_end,
const DofObjectCheckFunctor &  dofobj_check,
SyncFunctor &  sync 
)

Request data about a range of ghost dofobjects uniquely identified by their id.

Elements within the range can be excluded from the request by returning false from dofobj_check(dof_object)

Definition at line 349 of file parallel_ghost_sync.h.

354 {
355  // This function must be run on all processors at once
356  libmesh_parallel_only(comm);
357 
358  // Count the objects to ask each processor about
359  std::vector<dof_id_type>
360  ghost_objects_from_proc(comm.size(), 0);
361 
362  for (Iterator it = range_begin; it != range_end; ++it)
363  {
364  DofObject * obj = *it;
365  libmesh_assert (obj);
366 
367  // We may want to pass Elem* or Node* to the check function, not
368  // just DofObject*
369  if (!dofobj_check(*it))
370  continue;
371 
372  processor_id_type obj_procid = obj->processor_id();
373  if (obj_procid != DofObject::invalid_processor_id)
374  ghost_objects_from_proc[obj_procid]++;
375  }
376 
377  // Request sets to send to each processor
378  std::map<processor_id_type, std::vector<dof_id_type>>
379  requested_objs_id;
380 
381  // We know how many objects live on each processor, so reserve()
382  // space for each.
383  for (auto p : IntRange<processor_id_type>(0, comm.size()))
384  if (p != comm.rank() && ghost_objects_from_proc[p])
385  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
386 
387  for (Iterator it = range_begin; it != range_end; ++it)
388  {
389  DofObject * obj = *it;
390 
391  if (!dofobj_check(*it))
392  continue;
393 
394  processor_id_type obj_procid = obj->processor_id();
395  if (obj_procid == comm.rank() ||
396  obj_procid == DofObject::invalid_processor_id)
397  continue;
398 
399  requested_objs_id[obj_procid].push_back(obj->id());
400  }
401 
402  auto gather_functor =
403  [&sync]
404  (processor_id_type, const std::vector<dof_id_type> & ids,
405  std::vector<typename SyncFunctor::datum> & data)
406  {
407  sync.gather_data(ids, data);
408  };
409 
410  auto action_functor =
411  [&sync]
412  (processor_id_type, const std::vector<dof_id_type> & ids,
413  const std::vector<typename SyncFunctor::datum> & data)
414  {
415  // Let the user process the results
416  sync.act_on_data(ids, data);
417  };
418 
419  // Trade requests with other processors
420  typename SyncFunctor::datum * ex = nullptr;
421  pull_parallel_vector_data
422  (comm, requested_objs_id, gather_functor, action_functor, ex);
423 }

References data, libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), and libMesh::DofObject::processor_id().

◆ sync_dofobject_data_by_id() [2/2]

template<typename Iterator , typename SyncFunctor >
void libMesh::Parallel::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.

Fulfill requests with sync.gather_data(const std::vector<dof_id_type> & ids, std::vector<sync::datum> & data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<dof_id_type> & ids, std::vector<sync::datum> & data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 338 of file parallel_ghost_sync.h.

342 {
343  sync_dofobject_data_by_id(comm, range_begin, range_end, SyncEverything(), sync);
344 }

Referenced by libMesh::Partitioner::_find_global_index_by_pid_map(), libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshRefinement::make_flags_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), libMesh::FEMSystem::mesh_position_set(), libMesh::LaplaceMeshSmoother::smooth(), and libMesh::MeshRefinement::uniformly_coarsen().

◆ sync_dofobject_data_by_xyz() [1/2]

template<typename Iterator , typename DofObjType , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_xyz ( const Communicator &  comm,
const Iterator &  range_begin,
const Iterator &  range_end,
LocationMap< DofObjType > &  location_map,
SyncFunctor &  sync 
)

Definition at line 234 of file parallel_ghost_sync.h.

239 {
240  // This function must be run on all processors at once
241  libmesh_parallel_only(comm);
242 
243  // We need a valid location_map
244 #ifdef DEBUG
245  bool need_map_update = (range_begin != range_end && location_map.empty());
246  comm.max(need_map_update);
247  libmesh_assert(!need_map_update);
248 #endif
249 
250  // Count the objects to ask each processor about
251  std::vector<dof_id_type>
252  ghost_objects_from_proc(comm.size(), 0);
253 
254  for (Iterator it = range_begin; it != range_end; ++it)
255  {
256  DofObjType * obj = *it;
257  libmesh_assert (obj);
258  processor_id_type obj_procid = obj->processor_id();
259  if (obj_procid != DofObject::invalid_processor_id)
260  ghost_objects_from_proc[obj_procid]++;
261  }
262 
263  // Request sets to send to each processor
264  std::map<processor_id_type, std::vector<Point>>
265  requested_objs_pt;
266  // Corresponding ids to keep track of
267  std::map<processor_id_type, std::vector<dof_id_type>>
268  requested_objs_id;
269 
270  // We know how many objects live on each processor, so reserve()
271  // space for each.
272  for (auto p : IntRange<processor_id_type>(0, comm.size()))
273  if (p != comm.rank() && ghost_objects_from_proc[p])
274  {
275  requested_objs_pt[p].reserve(ghost_objects_from_proc[p]);
276  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
277  }
278 
279  for (Iterator it = range_begin; it != range_end; ++it)
280  {
281  DofObjType * obj = *it;
282  processor_id_type obj_procid = obj->processor_id();
283  if (obj_procid == comm.rank() ||
284  obj_procid == DofObject::invalid_processor_id)
285  continue;
286 
287  Point p = location_map.point_of(*obj);
288  requested_objs_pt[obj_procid].push_back(p);
289  requested_objs_id[obj_procid].push_back(obj->id());
290  }
291 
292  auto gather_functor =
293  [&location_map, &sync]
294  (processor_id_type /*pid*/, const std::vector<Point> & pts,
295  std::vector<typename SyncFunctor::datum> & data)
296  {
297  // Find the local id of each requested object
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)
301  {
302  Point pt = pts[i];
303 
304  // Look for this object in the multimap
305  DofObjType * obj = location_map.find(pt);
306 
307  // We'd better find every object we're asked for
308  libmesh_assert (obj);
309 
310  // Return the object's correct processor id,
311  // and our (correct if it's local) id for it.
312  query_id[i] = obj->id();
313  }
314 
315  // Gather whatever data the user wants
316  sync.gather_data(query_id, data);
317  };
318 
319  auto action_functor =
320  [&sync, &requested_objs_id]
321  (processor_id_type pid, const std::vector<Point> &,
322  const std::vector<typename SyncFunctor::datum> & data)
323  {
324  // Let the user process the results
325  sync.act_on_data(requested_objs_id[pid], data);
326  };
327 
328  // Trade requests with other processors
329  typename SyncFunctor::datum * ex = nullptr;
330  pull_parallel_vector_data
331  (comm, requested_objs_pt, gather_functor, action_functor, ex);
332 }

References data, libMesh::LocationMap< T >::empty(), libMesh::LocationMap< T >::find(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::LocationMap< T >::point_of(), and libMesh::TypeVector< T >::size().

◆ sync_dofobject_data_by_xyz() [2/2]

template<typename Iterator , typename DofObjType , typename SyncFunctor >
void libMesh::Parallel::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 active ghost elements uniquely identified by their centroids' xyz location.

Fulfill requests with sync.gather_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type. The user-provided location_map will be used and left unchanged if it is provided, or filled and cleared if it is empty.

◆ sync_element_data_by_parent_id()

template<typename Iterator , typename SyncFunctor >
void libMesh::Parallel::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 they are.

Fulfill requests with sync.gather_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 431 of file parallel_ghost_sync.h.

435 {
436  const Communicator & comm (mesh.comm());
437 
438  // This function must be run on all processors at once
439  libmesh_parallel_only(comm);
440 
441  // Count the objects to ask each processor about
442  std::vector<dof_id_type>
443  ghost_objects_from_proc(comm.size(), 0);
444 
445  for (Iterator it = range_begin; it != range_end; ++it)
446  {
447  Elem * elem = *it;
448  processor_id_type obj_procid = elem->processor_id();
449  if (obj_procid == comm.rank() ||
450  obj_procid == DofObject::invalid_processor_id)
451  continue;
452  const Elem * parent = elem->parent();
453  if (!parent || !elem->active())
454  continue;
455 
456  ghost_objects_from_proc[obj_procid]++;
457  }
458 
459  // Request sets to send to each processor
460  std::map<processor_id_type, std::vector<dof_id_type>>
461  requested_objs_id;
462  std::map<processor_id_type, std::vector<std::pair<dof_id_type,unsigned char>>>
463  requested_objs_parent_id_child_num;
464 
465  // We know how many objects live on each processor, so reserve()
466  // space for each.
467  for (auto p : IntRange<processor_id_type>(0, comm.size()))
468  if (p != comm.rank() && ghost_objects_from_proc[p])
469  {
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]);
472  }
473 
474  for (Iterator it = range_begin; it != range_end; ++it)
475  {
476  Elem * elem = *it;
477  processor_id_type obj_procid = elem->processor_id();
478  if (obj_procid == comm.rank() ||
479  obj_procid == DofObject::invalid_processor_id)
480  continue;
481  const Elem * parent = elem->parent();
482  if (!parent || !elem->active())
483  continue;
484 
485  requested_objs_id[obj_procid].push_back(elem->id());
486  requested_objs_parent_id_child_num[obj_procid].push_back
487  (std::make_pair
488  (parent->id(),
489  cast_int<unsigned char>
490  (parent->which_child_am_i(elem))));
491  }
492 
493  auto gather_functor =
494  [&mesh, &sync]
496  const std::vector<std::pair<dof_id_type, unsigned char>> & parent_id_child_num,
497  std::vector<typename SyncFunctor::datum> & data)
498  {
499  // Find the id of each requested element
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)
503  {
504  Elem & parent = mesh.elem_ref(parent_id_child_num[i].first);
505  libmesh_assert(parent.has_children());
506  Elem * child = parent.child_ptr(parent_id_child_num[i].second);
507  libmesh_assert(child);
508  libmesh_assert(child->active());
509  query_id[i] = child->id();
510  }
511 
512  // Gather whatever data the user wants
513  sync.gather_data(query_id, data);
514  };
515 
516  auto action_functor =
517  [&sync, &requested_objs_id]
518  (processor_id_type pid,
519  const std::vector<std::pair<dof_id_type, unsigned char>> &,
520  const std::vector<typename SyncFunctor::datum> & data)
521  {
522  // Let the user process the results
523  sync.act_on_data(requested_objs_id[pid], data);
524  };
525 
526  // Trade requests with other processors
527  typename SyncFunctor::datum * ex = nullptr;
528  pull_parallel_vector_data
529  (comm, requested_objs_parent_id_child_num, gather_functor,
530  action_functor, ex);
531 }

References libMesh::Elem::active(), libMesh::Elem::child_ptr(), data, libMesh::Elem::has_children(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), mesh, libMesh::Elem::parent(), libMesh::DofObject::processor_id(), and libMesh::Elem::which_child_am_i().

Referenced by libMesh::MeshCommunication::make_elems_parallel_consistent().

◆ sync_node_data_by_element_id()

template<typename ElemCheckFunctor , typename NodeCheckFunctor , typename SyncFunctor >
void libMesh::Parallel::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, iterating until data is completely in sync and futher synchronization passes cause no changes.

Imagine a vertex surrounded by triangles, each on a different processor, with a ghosting policy that include only face neighbors and not point neighbors. Then the only way for authoritative information to trickle out from that vertex is by being passed along, one neighbor at a time, to processors who mostly don't even see the node's true owner!

Data for all nodes connected to elements in the given range of element iterators will be requested.

Elements can be further excluded from the request by returning false from element_check(elem)

Nodes can be further excluded from the request by returning false from node_check(elem, local_node_num)

Fulfill requests with sync.gather_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data), by resizing and setting the values of the data vector. Respond to fulfillment with bool sync.act_on_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data) and return true iff the response changed any data.

The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 754 of file parallel_ghost_sync.h.

760 {
761  // This function must be run on all processors at once
762  libmesh_parallel_only(mesh.comm());
763 
764  bool need_sync = false;
765 
766  do
767  {
768  need_sync =
770  (mesh, range_begin, range_end, elem_check, node_check,
771  sync);
772  } while (need_sync);
773 }

References mesh, and sync_node_data_by_element_id_once().

Referenced by libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), libMesh::MeshCommunication::make_node_ids_parallel_consistent(), and libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent().

◆ sync_node_data_by_element_id_once()

template<typename ElemCheckFunctor , typename NodeCheckFunctor , typename SyncFunctor >
bool libMesh::Parallel::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, assuming a single synchronization pass is necessary.

Data for all nodes connected to elements in the given range of element iterators will be requested.

Elements can be further excluded from the request by returning false from element_check(elem)

Nodes can be further excluded from the request by returning false from node_check(elem, local_node_num)

Fulfill requests with sync.gather_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data), by resizing and setting the values of the data vector. Respond to fulfillment with bool sync.act_on_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data) and return true iff the response changed any data.

The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

This method returns true iff the sync pass changed any data on any processor.

Definition at line 548 of file parallel_ghost_sync.h.

554 {
555  const Communicator & comm (mesh.comm());
556 
557  // Count the objects to ask each processor about
558  std::vector<dof_id_type>
559  ghost_objects_from_proc(comm.size(), 0);
560 
561  for (const auto & elem : as_range(range_begin, range_end))
562  {
563  libmesh_assert (elem);
564 
565  if (!elem_check(elem))
566  continue;
567 
568  const processor_id_type proc_id = elem->processor_id();
569 
570  bool i_have_elem =
571  (proc_id == comm.rank() ||
572  proc_id == DofObject::invalid_processor_id);
573 
574  if (elem->active() && i_have_elem)
575  continue;
576 
577  for (auto n : elem->node_index_range())
578  {
579  if (!node_check(elem, n))
580  continue;
581 
582  const processor_id_type node_pid =
583  elem->node_ref(n).processor_id();
584 
585  if (i_have_elem && (node_pid == comm.rank()))
586  continue;
587 
588  if (i_have_elem)
589  {
590  libmesh_assert_not_equal_to
591  (node_pid, DofObject::invalid_processor_id);
592  ghost_objects_from_proc[node_pid]++;
593  }
594  else
595  {
596  const processor_id_type request_pid =
597  (node_pid == DofObject::invalid_processor_id) ?
598  proc_id : node_pid;
599  ghost_objects_from_proc[request_pid]++;
600  }
601  }
602  }
603 
604  // Now repeat that iteration, filling request sets this time.
605 
606  // Request sets to send to each processor
607  std::map<processor_id_type, std::vector<std::pair<dof_id_type, unsigned char>>>
608  requested_objs_elem_id_node_num;
609 
610  // We know how many objects live on each processor, so reserve()
611  // space for each.
612  for (auto p : IntRange<processor_id_type>(0, comm.size()))
613  if (p != comm.rank() && ghost_objects_from_proc[p])
614  {
615  requested_objs_elem_id_node_num[p].reserve(ghost_objects_from_proc[p]);
616  }
617 
618  for (const auto & elem : as_range(range_begin, range_end))
619  {
620  libmesh_assert (elem);
621 
622  if (!elem_check(elem))
623  continue;
624 
625  const processor_id_type proc_id = elem->processor_id();
626 
627  bool i_have_elem =
628  (proc_id == comm.rank() ||
629  proc_id == DofObject::invalid_processor_id);
630 
631  if (elem->active() && i_have_elem)
632  continue;
633 
634  const dof_id_type elem_id = elem->id();
635 
636  for (auto n : elem->node_index_range())
637  {
638  if (!node_check(elem, n))
639  continue;
640 
641  const Node & node = elem->node_ref(n);
642  const processor_id_type node_pid = node.processor_id();
643 
644  if (i_have_elem && (node_pid == comm.rank()))
645  continue;
646 
647  if (i_have_elem)
648  {
649  libmesh_assert_not_equal_to
650  (node_pid, DofObject::invalid_processor_id);
651  requested_objs_elem_id_node_num[node_pid].push_back
652  (std::make_pair
653  (elem_id,
654  cast_int<unsigned char>(n)));
655  }
656  else
657  {
658  const processor_id_type request_pid =
659  (node_pid == DofObject::invalid_processor_id) ?
660  proc_id : node_pid;
661  requested_objs_elem_id_node_num[request_pid].push_back
662  (std::make_pair
663  (elem_id,
664  cast_int<unsigned char>(n)));
665  }
666  }
667  }
668 
669  auto gather_functor =
670  [&mesh, &sync]
672  const std::vector<std::pair<dof_id_type, unsigned char>> & elem_id_node_num,
673  std::vector<typename SyncFunctor::datum> & data)
674  {
675  // Find the id of each requested element
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)
679  {
680  // We might now get queries about remote elements, in which
681  // case we'll have to ignore them and wait for the query
682  // answer to filter to the querier via another source.
683  const Elem * elem = mesh.query_elem_ptr(elem_id_node_num[i].first);
684 
685  if (elem)
686  {
687  const unsigned int n = elem_id_node_num[i].second;
688  libmesh_assert_less (n, elem->n_nodes());
689 
690  const Node & node = elem->node_ref(n);
691 
692  // This isn't a safe assertion in the case where we're
693  // syncing processor ids
694  // libmesh_assert_equal_to (node->processor_id(), comm.rank());
695 
696  query_id[i] = node.id();
697  }
698  else
699  query_id[i] = DofObject::invalid_id;
700  }
701 
702  // Gather whatever data the user wants
703  sync.gather_data(query_id, data);
704  };
705 
706  bool data_changed = false;
707 
708  auto action_functor =
709  [&sync, &mesh, &requested_objs_elem_id_node_num, &data_changed]
710  (processor_id_type pid,
711  const std::vector<std::pair<dof_id_type, unsigned char>> &,
712  const std::vector<typename SyncFunctor::datum> & data)
713  {
714  const auto & elem_id_node_num =
715  requested_objs_elem_id_node_num[pid];
716 
717  const std::size_t data_size = data.size();
718 
719  libmesh_assert_equal_to(elem_id_node_num.size(), data_size);
720 
721  std::vector<dof_id_type> requested_objs_id(data.size());
722 
723  for (auto i : IntRange<std::size_t>(0,data_size))
724  {
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();
728  }
729 
730  // Let the user process the results. If any of the results
731  // were different than what the user expected, then we may
732  // need to sync again just in case this processor has to
733  // pass on the changes to yet another processor.
734  if (sync.act_on_data(requested_objs_id, data))
735  data_changed = true;
736  };
737 
738  // Trade requests with other processors
739  typename SyncFunctor::datum * ex = nullptr;
740  pull_parallel_vector_data
741  (comm, requested_objs_elem_id_node_num, gather_functor,
742  action_functor, ex);
743 
744  comm.max(data_changed);
745 
746  return data_changed;
747 }

References libMesh::as_range(), data, libMesh::DofObject::id(), libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), mesh, libMesh::Elem::n_nodes(), libMesh::Elem::node_ref(), and libMesh::DofObject::processor_id().

Referenced by libMesh::MeshCommunication::make_new_node_proc_ids_parallel_consistent(), and sync_node_data_by_element_id().

libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::Parallel::sync_dofobject_data_by_id
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, const DofObjectCheckFunctor &dofobj_check, SyncFunctor &sync)
Request data about a range of ghost dofobjects uniquely identified by their id.
Definition: parallel_ghost_sync.h:349
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
libMesh::as_range
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
data
IterBase * data
Ideally this private member data should have protected access.
Definition: variant_filter_iterator.h:337
libMesh::Parallel::sync_node_data_by_element_id_once
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,...
Definition: parallel_ghost_sync.h:548