libMesh
parallel_elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 // C++ includes
21 
22 // Local includes
23 #include "libmesh/boundary_info.h"
24 #include "libmesh/distributed_mesh.h"
25 #include "libmesh/elem.h"
26 #include "libmesh/mesh_base.h"
27 #include "libmesh/parallel_elem.h"
28 #include "libmesh/parallel_mesh.h"
29 #include "libmesh/remote_elem.h"
30 
31 // Helper functions in anonymous namespace
32 
33 namespace
34 {
35 using namespace libMesh;
36 
37 #ifdef LIBMESH_ENABLE_UNIQUE_ID
38 static const unsigned int header_size = 12;
39 #else
40 static const unsigned int header_size = 11;
41 #endif
42 
43 #ifndef NDEBUG
44 // Currently this constant is only used for debugging.
45 static const largest_id_type elem_magic_header = 987654321;
46 #endif
47 }
48 
49 
50 namespace libMesh
51 {
52 
53 namespace Parallel
54 {
55 
56 template <>
57 unsigned int
58 Packing<const Elem *>::packed_size (std::vector<largest_id_type>::const_iterator in)
59 {
60 #ifndef NDEBUG
61  const largest_id_type packed_header = *in++;
62  libmesh_assert_equal_to (packed_header, elem_magic_header);
63 #endif
64 
65  // int 0: level
66  const unsigned int level =
67  cast_int<unsigned int>(*in);
68 
69  // int 4: element type
70  const int typeint = cast_int<int>(*(in+4));
71  libmesh_assert_greater_equal (typeint, 0);
72  libmesh_assert_less (typeint, INVALID_ELEM);
73  const ElemType type =
74  cast_int<ElemType>(typeint);
75 
76  const unsigned int n_nodes =
78 
79  const unsigned int n_sides =
81 
82  const unsigned int n_edges =
84 
85  const unsigned int pre_indexing_size =
86  header_size + n_nodes + n_sides*2;
87 
88  const unsigned int indexing_size =
89  DofObject::unpackable_indexing_size(in+pre_indexing_size);
90 
91  unsigned int total_packed_bc_data = 0;
92  if (level == 0)
93  {
94  for (unsigned int s = 0; s != n_sides; ++s)
95  {
96  const int n_bcs = cast_int<int>
97  (*(in + pre_indexing_size + indexing_size +
98  total_packed_bc_data++));
99  libmesh_assert_greater_equal (n_bcs, 0);
100  total_packed_bc_data += n_bcs;
101  }
102 
103  for (unsigned int e = 0; e != n_edges; ++e)
104  {
105  const int n_bcs = cast_int<int>
106  (*(in + pre_indexing_size + indexing_size +
107  total_packed_bc_data++));
108  libmesh_assert_greater_equal (n_bcs, 0);
109  total_packed_bc_data += n_bcs;
110  }
111 
112  for (unsigned short sf=0; sf != 2; ++sf)
113  {
114  const int n_bcs = cast_int<int>
115  (*(in + pre_indexing_size + indexing_size +
116  total_packed_bc_data++));
117  libmesh_assert_greater_equal (n_bcs, 0);
118  total_packed_bc_data += n_bcs;
119  }
120  }
121 
122  return
123 #ifndef NDEBUG
124  1 + // Account for magic header
125 #endif
126  pre_indexing_size + indexing_size + total_packed_bc_data;
127 }
128 
129 
130 
131 template <>
132 unsigned int
133 Packing<const Elem *>::packed_size (std::vector<largest_id_type>::iterator in)
134 {
135  return packed_size(std::vector<largest_id_type>::const_iterator(in));
136 }
137 
138 
139 
140 template <>
141 unsigned int
143  const MeshBase * mesh)
144 {
145  unsigned int total_packed_bcs = 0;
146  const unsigned short n_sides = elem->n_sides();
147 
148  if (elem->level() == 0)
149  {
150  total_packed_bcs += n_sides;
151  for (unsigned short s = 0; s != n_sides; ++s)
152  total_packed_bcs +=
154 
155  const unsigned short n_edges = elem->n_edges();
156  total_packed_bcs += n_edges;
157  for (unsigned short e = 0; e != n_edges; ++e)
158  total_packed_bcs +=
160 
161  total_packed_bcs += 2; // shellfaces
162  for (unsigned short sf=0; sf != 2; ++sf)
163  total_packed_bcs +=
165  }
166 
167  return
168 #ifndef NDEBUG
169  1 + // add an int for the magic header when testing
170 #endif
171  header_size + elem->n_nodes() + n_sides*2 +
172  elem->packed_indexing_size() + total_packed_bcs;
173 }
174 
175 
176 
177 template <>
178 unsigned int
180  const DistributedMesh * mesh)
181 {
182  return packable_size(elem, static_cast<const MeshBase *>(mesh));
183 }
184 
185 
186 
187 template <>
188 unsigned int
190  const ParallelMesh * mesh)
191 {
192  return packable_size(elem, static_cast<const MeshBase *>(mesh));
193 }
194 
195 
196 
197 template <>
198 void
199 Packing<const Elem *>::pack (const Elem * const & elem,
200  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
201  const MeshBase * mesh)
202 {
203  libmesh_assert(elem);
204 
205 #ifndef NDEBUG
206  *data_out++ = elem_magic_header;
207 #endif
208 
209 #ifdef LIBMESH_ENABLE_AMR
210  *data_out++ = (static_cast<largest_id_type>(elem->level()));
211  *data_out++ = (static_cast<largest_id_type>(elem->p_level()));
212 
213  // Encode both the refinement flag and whether the element has
214  // children together. This coding is unambiguous because our
215  // refinement state encoding starts at 0 and ends at
216  // INVALID_REFINEMENTSTATE
217  largest_id_type refinement_info =
218  static_cast<largest_id_type>(elem->refinement_flag());
219  if (elem->has_children())
220  refinement_info +=
221  static_cast<largest_id_type>(Elem::INVALID_REFINEMENTSTATE) + 1;
222  *data_out++ = (refinement_info);
223 
224  *data_out++ = (static_cast<largest_id_type>(elem->p_refinement_flag()));
225 #else
226  *data_out++ = (0);
227  *data_out++ = (0);
228  *data_out++ = (0);
229  *data_out++ = (0);
230 #endif
231  *data_out++ = (static_cast<largest_id_type>(elem->type()));
232  *data_out++ = (elem->processor_id());
233  *data_out++ = (elem->subdomain_id());
234  *data_out++ = (elem->id());
235 
236 #ifdef LIBMESH_ENABLE_UNIQUE_ID
237  if (elem->valid_unique_id())
238  *data_out++ = (static_cast<largest_id_type>(elem->unique_id()));
239  else
240  // OK to send invalid unique id, we must not own this DOF
241  *data_out++ = (static_cast<largest_id_type>(DofObject::invalid_unique_id));
242 #endif
243 
244 #ifdef LIBMESH_ENABLE_AMR
245  // use parent_ID of invalid_id to indicate a level 0 element
246  if (elem->level() == 0)
247  {
248  *data_out++ =(DofObject::invalid_id);
249  *data_out++ =(DofObject::invalid_id);
250  }
251  else
252  {
253  *data_out++ =(elem->parent()->id());
254  *data_out++ =(elem->parent()->which_child_am_i(elem));
255  }
256 #else
257  *data_out++ = (DofObject::invalid_id);
258  *data_out++ = (DofObject::invalid_id);
259 #endif
260 
261  if ((elem->dim() < LIBMESH_DIM) &&
262  elem->interior_parent())
263  *data_out++ =(elem->interior_parent()->id());
264  else
265  *data_out++ =(DofObject::invalid_id);
266 
267  for (const Node & node : elem->node_ref_range())
268  *data_out++ = node.id();
269 
270  // Add the id of and the side for any return link from each neighbor
271  for (auto neigh : elem->neighbor_ptr_range())
272  {
273  if (neigh)
274  {
275  *data_out++ = (neigh->id());
276  if (neigh == remote_elem)
277  *data_out++ = (DofObject::invalid_id);
278  else
279  *data_out++ = neigh->which_neighbor_am_i(elem);
280  }
281  else
282  {
283  *data_out++ = (DofObject::invalid_id);
284  *data_out++ = (DofObject::invalid_id);
285  }
286  }
287 
288  // Add any DofObject indices
289  elem->pack_indexing(data_out);
290 
291  // If this is a coarse element,
292  // Add any element side boundary condition ids
293  if (elem->level() == 0)
294  {
295  std::vector<boundary_id_type> bcs;
296  for (auto s : elem->side_index_range())
297  {
298  mesh->get_boundary_info().boundary_ids(elem, s, bcs);
299 
300  *data_out++ =(bcs.size());
301 
302  for (const auto & bid : bcs)
303  *data_out++ = bid;
304  }
305 
306  for (auto e : elem->edge_index_range())
307  {
308  mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
309 
310  *data_out++ =(bcs.size());
311 
312  for (const auto & bid : bcs)
313  *data_out++ = bid;
314  }
315 
316  for (unsigned short sf=0; sf != 2; ++sf)
317  {
319 
320  *data_out++ =(bcs.size());
321 
322  for (const auto & bid : bcs)
323  *data_out++ = bid;
324  }
325  }
326 }
327 
328 
329 
330 template <>
331 void
332 Packing<const Elem *>::pack (const Elem * const & elem,
333  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
334  const DistributedMesh * mesh)
335 {
336  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
337 }
338 
339 
340 
341 template <>
342 void
343 Packing<const Elem *>::pack (const Elem * const & elem,
344  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
345  const ParallelMesh * mesh)
346 {
347  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
348 }
349 
350 
351 
352 // FIXME - this needs serious work to be 64-bit compatible
353 template <>
354 Elem *
355 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
356  MeshBase * mesh)
357 {
358 #ifndef NDEBUG
359  const std::vector<largest_id_type>::const_iterator original_in = in;
360 
361  const largest_id_type incoming_header = *in++;
362  libmesh_assert_equal_to (incoming_header, elem_magic_header);
363 #endif
364 
365  // int 0: level
366  const unsigned int level =
367  cast_int<unsigned int>(*in++);
368 
369 #ifdef LIBMESH_ENABLE_AMR
370  // int 1: p level
371  const unsigned int p_level =
372  cast_int<unsigned int>(*in++);
373 
374  // int 2: refinement flag and encoded has_children
375  const int rflag = cast_int<int>(*in++);
376  const int invalid_rflag =
377  cast_int<int>(Elem::INVALID_REFINEMENTSTATE);
378  libmesh_assert_greater_equal (rflag, 0);
379 
380  libmesh_assert_less (rflag, invalid_rflag*2+1);
381 
382  const bool has_children = (rflag > invalid_rflag);
383 
384  const Elem::RefinementState refinement_flag = has_children ?
385  cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
386  cast_int<Elem::RefinementState>(rflag);
387 
388  // int 3: p refinement flag
389  const int pflag = cast_int<int>(*in++);
390  libmesh_assert_greater_equal (pflag, 0);
391  libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
392  const Elem::RefinementState p_refinement_flag =
393  cast_int<Elem::RefinementState>(pflag);
394 #else
395  in += 3;
396 #endif // LIBMESH_ENABLE_AMR
397 
398  // int 4: element type
399  const int typeint = cast_int<int>(*in++);
400  libmesh_assert_greater_equal (typeint, 0);
401  libmesh_assert_less (typeint, INVALID_ELEM);
402  const ElemType type =
403  cast_int<ElemType>(typeint);
404 
405  const unsigned int n_nodes =
407 
408  // int 5: processor id
409  const processor_id_type processor_id =
410  cast_int<processor_id_type>(*in++);
411  libmesh_assert (processor_id < mesh->n_processors() ||
412  processor_id == DofObject::invalid_processor_id);
413 
414  // int 6: subdomain id
415  const subdomain_id_type subdomain_id =
416  cast_int<subdomain_id_type>(*in++);
417 
418  // int 7: dof object id
419  const dof_id_type id =
420  cast_int<dof_id_type>(*in++);
421  libmesh_assert_not_equal_to (id, DofObject::invalid_id);
422 
423 #ifdef LIBMESH_ENABLE_UNIQUE_ID
424  // int 8: dof object unique id
425  const unique_id_type unique_id =
426  cast_int<unique_id_type>(*in++);
427 #endif
428 
429 #ifdef LIBMESH_ENABLE_AMR
430  // int 9: parent dof object id.
431  // Note: If level==0, then (*in) == invalid_id. In
432  // this case, the equality check in cast_int<unsigned>(*in) will
433  // never succeed. Therefore, we should only attempt the more
434  // rigorous cast verification in cases where level != 0.
435  const dof_id_type parent_id =
436  (level == 0)
437  ? static_cast<dof_id_type>(*in++)
438  : cast_int<dof_id_type>(*in++);
439  libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
440  libmesh_assert (level != 0 || parent_id == DofObject::invalid_id);
441 
442  // int 10: local child id
443  // Note: If level==0, then which_child_am_i is not valid, so don't
444  // do the more rigorous cast verification.
445  const unsigned int which_child_am_i =
446  (level == 0)
447  ? static_cast<unsigned int>(*in++)
448  : cast_int<unsigned int>(*in++);
449 #else
450  in += 2;
451 #endif // LIBMESH_ENABLE_AMR
452 
453  const dof_id_type interior_parent_id =
454  static_cast<dof_id_type>(*in++);
455 
456  // Make sure we don't miscount above when adding the "magic" header
457  // plus the real data header
458  libmesh_assert_equal_to (in - original_in, header_size + 1);
459 
460  Elem * elem = mesh->query_elem_ptr(id);
461 
462  // if we already have this element, make sure its
463  // properties match, and update any missing neighbor
464  // links, but then go on
465  if (elem)
466  {
467  libmesh_assert_equal_to (elem->level(), level);
468  libmesh_assert_equal_to (elem->id(), id);
469  //#ifdef LIBMESH_ENABLE_UNIQUE_ID
470  // No check for unique id sanity
471  //#endif
472  libmesh_assert_equal_to (elem->processor_id(), processor_id);
473  libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
474  libmesh_assert_equal_to (elem->type(), type);
475  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
476 
477 #ifndef NDEBUG
478  // All our nodes should be correct
479  for (unsigned int i=0; i != n_nodes; ++i)
480  libmesh_assert(elem->node_id(i) ==
481  cast_int<dof_id_type>(*in++));
482 #else
483  in += n_nodes;
484 #endif
485 
486 #ifdef LIBMESH_ENABLE_AMR
487  libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
488  libmesh_assert_equal_to (elem->has_children(), has_children);
489 
490 #ifdef DEBUG
491  if (elem->active())
492  {
493  libmesh_assert_equal_to (elem->p_level(), p_level);
494  libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);
495  }
496 #endif
497 
498  libmesh_assert (!level || elem->parent() != nullptr);
499  libmesh_assert (!level || elem->parent()->id() == parent_id);
500  libmesh_assert (!level || elem->parent()->child_ptr(which_child_am_i) == elem);
501 #endif
502  // Our interior_parent link should be "close to" correct - we
503  // may have to update it, but we can check for some
504  // inconsistencies.
505  {
506  // If the sending processor sees no interior_parent here, we'd
507  // better agree.
508  if (interior_parent_id == DofObject::invalid_id)
509  {
510  if (elem->dim() < LIBMESH_DIM)
511  libmesh_assert (!(elem->interior_parent()));
512  }
513 
514  // If the sending processor has a remote_elem interior_parent,
515  // then all we know is that we'd better have *some*
516  // interior_parent
517  else if (interior_parent_id == remote_elem->id())
518  {
520  }
521  else
522  {
523  Elem * ip = mesh->query_elem_ptr(interior_parent_id);
524 
525  // The sending processor sees an interior parent here, so
526  // if we don't have that interior element, then we'd
527  // better have a remote_elem signifying that fact.
528  if (!ip)
529  libmesh_assert_equal_to (elem->interior_parent(), remote_elem);
530  else
531  {
532  // The sending processor has an interior_parent here,
533  // and we have that element, but that does *NOT* mean
534  // we're already linking to it. Perhaps we initially
535  // received elem from a processor on which the
536  // interior_parent link was remote?
537  libmesh_assert(elem->interior_parent() == ip ||
538  elem->interior_parent() == remote_elem);
539 
540  // If the link was originally remote, update it
541  if (elem->interior_parent() == remote_elem)
542  {
543  elem->set_interior_parent(ip);
544  }
545  }
546  }
547  }
548 
549  // Our neighbor links should be "close to" correct - we may have
550  // to update a remote_elem link, and we can check for possible
551  // inconsistencies along the way.
552  //
553  // For subactive elements, we don't bother keeping neighbor
554  // links in good shape, so there's nothing we need to set or can
555  // safely assert here.
556  if (!elem->subactive())
557  for (auto n : elem->side_index_range())
558  {
559  const dof_id_type neighbor_id =
560  cast_int<dof_id_type>(*in++);
561 
562  const dof_id_type neighbor_side =
563  cast_int<dof_id_type>(*in++);
564 
565  // If the sending processor sees a domain boundary here,
566  // we'd better agree.
567  if (neighbor_id == DofObject::invalid_id)
568  {
569  libmesh_assert (!(elem->neighbor_ptr(n)));
570  continue;
571  }
572 
573  // If the sending processor has a remote_elem neighbor here,
574  // then all we know is that we'd better *not* have a domain
575  // boundary.
576  if (neighbor_id == remote_elem->id())
577  {
578  libmesh_assert(elem->neighbor_ptr(n));
579  continue;
580  }
581 
582  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
583 
584  // The sending processor sees a neighbor here, so if we
585  // don't have that neighboring element, then we'd better
586  // have a remote_elem signifying that fact.
587  if (!neigh)
588  {
589  libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
590  continue;
591  }
592 
593  // The sending processor has a neighbor here, and we have
594  // that element, but that does *NOT* mean we're already
595  // linking to it. Perhaps we initially received both elem
596  // and neigh from processors on which their mutual link was
597  // remote?
598  libmesh_assert(elem->neighbor_ptr(n) == neigh ||
599  elem->neighbor_ptr(n) == remote_elem);
600 
601  // If the link was originally remote, we should update it,
602  // and make sure the appropriate parts of its family link
603  // back to us.
604  if (elem->neighbor_ptr(n) == remote_elem)
605  {
606  elem->set_neighbor(n, neigh);
607 
608  elem->make_links_to_me_local(n, neighbor_side);
609  }
610  else
611  libmesh_assert(neigh->level() < elem->level() ||
612  neigh->neighbor_ptr(neighbor_side) == elem);
613  }
614 
615  // Our p level and refinement flags should be "close to" correct
616  // if we're not an active element - we might have a p level
617  // increased or decreased by changes in remote_elem children.
618  //
619  // But if we have remote_elem children, then we shouldn't be
620  // doing a projection on this inactive element on this
621  // processor, so we won't need correct p settings. Couldn't
622  // hurt to update, though.
623 #ifdef LIBMESH_ENABLE_AMR
624  if (elem->processor_id() != mesh->processor_id())
625  {
626  elem->hack_p_level(p_level);
627  elem->set_p_refinement_flag(p_refinement_flag);
628  }
629 #endif // LIBMESH_ENABLE_AMR
630 
631  // FIXME: We should add some debug mode tests to ensure that the
632  // encoded indexing and boundary conditions are consistent.
633  }
634  else
635  {
636  // We don't already have the element, so we need to create it.
637 
638  // Find the parent if necessary
639  Elem * parent = nullptr;
640 #ifdef LIBMESH_ENABLE_AMR
641  // Find a child element's parent
642  if (level > 0)
643  {
644  // Note that we must be very careful to construct the send
645  // connectivity so that parents are encountered before
646  // children. If we get here and can't find the parent that
647  // is a fatal error.
648  parent = mesh->elem_ptr(parent_id);
649  }
650  // Or assert that the sending processor sees no parent
651  else
652  libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
653 #else
654  // No non-level-0 elements without AMR
655  libmesh_assert_equal_to (level, 0);
656 #endif
657 
658  elem = Elem::build(type,parent).release();
659  libmesh_assert (elem);
660 
661 #ifdef LIBMESH_ENABLE_AMR
662  if (level != 0)
663  {
664  // Since this is a newly created element, the parent must
665  // have previously thought of this child as a remote element.
666  libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
667 
668  parent->add_child(elem, which_child_am_i);
669  }
670 
671  // Assign the refinement flags and levels
672  elem->set_p_level(p_level);
673  elem->set_refinement_flag(refinement_flag);
674  elem->set_p_refinement_flag(p_refinement_flag);
675  libmesh_assert_equal_to (elem->level(), level);
676 
677  // If this element should have children, assign remote_elem to
678  // all of them for now, for consistency. Later unpacked
679  // elements may overwrite that.
680  if (has_children)
681  {
682  const unsigned int nc = elem->n_children();
683  for (unsigned int c=0; c != nc; ++c)
684  elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
685  }
686 
687 #endif // LIBMESH_ENABLE_AMR
688 
689  // Assign the IDs
690  elem->subdomain_id() = subdomain_id;
691  elem->processor_id() = processor_id;
692  elem->set_id() = id;
693 #ifdef LIBMESH_ENABLE_UNIQUE_ID
694  elem->set_unique_id() = unique_id;
695 #endif
696 
697  // Assign the connectivity
698  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
699 
700  for (unsigned int n=0; n != n_nodes; n++)
701  elem->set_node(n) =
702  mesh->node_ptr
703  (cast_int<dof_id_type>(*in++));
704 
705  // Set interior_parent if found
706  {
707  // We may be unpacking an element that was a ghost element on the
708  // sender, in which case the element's interior_parent may not be
709  // known by the packed element. We'll have to set such
710  // interior_parents to remote_elem ourselves and wait for a
711  // later packed element to give us better information.
712  if (interior_parent_id == remote_elem->id())
713  {
714  elem->set_interior_parent
715  (const_cast<RemoteElem *>(remote_elem));
716  }
717  else if (interior_parent_id != DofObject::invalid_id)
718  {
719  // If we don't have the interior parent element, then it's
720  // a remote_elem until we get it.
721  Elem * ip = mesh->query_elem_ptr(interior_parent_id);
722  if (!ip )
723  elem->set_interior_parent
724  (const_cast<RemoteElem *>(remote_elem));
725  else
726  elem->set_interior_parent(ip);
727  }
728  }
729 
730  for (auto n : elem->side_index_range())
731  {
732  const dof_id_type neighbor_id =
733  cast_int<dof_id_type>(*in++);
734 
735  const dof_id_type neighbor_side =
736  cast_int<dof_id_type>(*in++);
737 
738  if (neighbor_id == DofObject::invalid_id)
739  continue;
740 
741  // We may be unpacking an element that was a ghost element on the
742  // sender, in which case the element's neighbors may not all be
743  // known by the packed element. We'll have to set such
744  // neighbors to remote_elem ourselves and wait for a later
745  // packed element to give us better information.
746  if (neighbor_id == remote_elem->id())
747  {
748  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
749  continue;
750  }
751 
752  // If we don't have the neighbor element, then it's a
753  // remote_elem until we get it.
754  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
755  if (!neigh)
756  {
757  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
758  continue;
759  }
760 
761  // If we have the neighbor element, then link to it, and
762  // make sure any appropriate parts of its family link back
763  // to us.
764  elem->set_neighbor(n, neigh);
765 
766  elem->make_links_to_me_local(n, neighbor_side);
767  }
768 
769  elem->unpack_indexing(in);
770  }
771 
772  in += elem->packed_indexing_size();
773 
774  // If this is a coarse element,
775  // add any element side or edge boundary condition ids
776  if (level == 0)
777  {
778  for (auto s : elem->side_index_range())
779  {
780  const boundary_id_type num_bcs =
781  cast_int<boundary_id_type>(*in++);
782 
783  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
785  (elem, s, cast_int<boundary_id_type>(*in++));
786  }
787 
788  for (auto e : elem->edge_index_range())
789  {
790  const boundary_id_type num_bcs =
791  cast_int<boundary_id_type>(*in++);
792 
793  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
795  (elem, e, cast_int<boundary_id_type>(*in++));
796  }
797 
798  for (unsigned short sf=0; sf != 2; ++sf)
799  {
800  const boundary_id_type num_bcs =
801  cast_int<boundary_id_type>(*in++);
802 
803  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
805  (elem, sf, cast_int<boundary_id_type>(*in++));
806  }
807  }
808 
809  // Return the new element
810  return elem;
811 }
812 
813 
814 
815 template <>
816 Elem *
817 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
819 {
820  return unpack(in, static_cast<MeshBase*>(mesh));
821 }
822 
823 
824 
825 template <>
826 Elem *
827 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
828  ParallelMesh * mesh)
829 {
830  return unpack(in, static_cast<MeshBase*>(mesh));
831 }
832 
833 } // namespace Parallel
834 
835 } // namespace libMesh
libMesh::ParallelMesh
Definition: parallel_mesh.h:34
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::BoundaryInfo::boundary_ids
std::vector< boundary_id_type > boundary_ids(const Node *node) const
Definition: boundary_info.C:985
libMesh::Elem::child_ptr
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:2567
libMesh::Elem::n_edges
virtual unsigned int n_edges() const =0
libMesh::Elem::set_p_refinement_flag
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:2638
libMesh::Parallel::Packing< const Elem * >::packable_size
static unsigned int packable_size(const Elem *const &object, const Context *context)
libMesh::unique_id_type
uint8_t unique_id_type
Definition: id_types.h:86
libMesh::MeshBase::get_boundary_info
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:132
libMesh::Elem::set_interior_parent
void set_interior_parent(Elem *p)
Sets the pointer to the element's interior_parent.
Definition: elem.C:801
libMesh::DofObject::unpack_indexing
void unpack_indexing(std::vector< largest_id_type >::const_iterator begin)
A method for creating our index buffer from packed data - basically with our current implementation w...
Definition: dof_object.C:589
libMesh::DofObject::unpackable_indexing_size
static unsigned int unpackable_indexing_size(std::vector< largest_id_type >::const_iterator begin)
If we have indices packed into an buffer for communications, how much of that buffer applies to this ...
Definition: dof_object.C:569
libMesh::Elem::level
unsigned int level() const
Definition: elem.h:2478
libMesh::Elem::n_nodes
virtual unsigned int n_nodes() const =0
libMesh::Elem::edge_index_range
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2179
libMesh::BoundaryInfo::shellface_boundary_ids
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
Definition: boundary_info.C:1133
libMesh::BoundaryInfo::edge_boundary_ids
std::vector< boundary_id_type > edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
Definition: boundary_info.C:1018
libMesh::DofObject::set_id
dof_id_type & set_id()
Definition: dof_object.h:776
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::Elem::set_p_level
void set_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element.
Definition: elem_refinement.C:41
libMesh::Elem::dim
virtual unsigned short dim() const =0
libMesh::Elem::add_child
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
Definition: elem.C:1384
libMesh::Elem::set_neighbor
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2105
libMesh::Elem::p_level
unsigned int p_level() const
Definition: elem.h:2512
libMesh::Elem::neighbor_ptr_range
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:2917
libMesh::Elem::RefinementState
RefinementState
Enumeration of possible element refinement states.
Definition: elem.h:1169
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::node_ptr
virtual const Node * node_ptr(const dof_id_type i) const =0
libMesh::DofObject::set_unique_id
unique_id_type & set_unique_id()
Definition: dof_object.h:797
libMesh::Parallel::Packing< const Elem * >::packed_size
static unsigned int packed_size(BufferIter iter)
libMesh::DofObject::valid_unique_id
bool valid_unique_id() const
Definition: dof_object.h:817
libMesh::largest_id_type
uint64_t largest_id_type
Definition: id_types.h:148
libMesh::boundary_id_type
int8_t boundary_id_type
Definition: id_types.h:51
libMesh::Parallel::Packing< Elem * >::unpack
static Elem * unpack(BufferIter in, Context *ctx)
libMesh::DofObject::processor_id
processor_id_type processor_id() const
Definition: dof_object.h:829
libMesh::MeshBase::elem_ptr
virtual const Elem * elem_ptr(const dof_id_type i) const =0
libMesh::Elem::active
bool active() const
Definition: elem.h:2345
libMesh::MeshBase::query_elem_ptr
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
libMesh::DofObject::packed_indexing_size
unsigned int packed_indexing_size() const
If we pack our indices into an buffer for communications, how many ints do we need?
Definition: dof_object.C:554
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::DofObject::invalid_unique_id
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:426
libMesh::Elem::subactive
bool subactive() const
Definition: elem.h:2363
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
libMesh::Elem::node_ref_range
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2152
libMesh::Elem::p_refinement_flag
RefinementState p_refinement_flag() const
Definition: elem.h:2630
libMesh::Elem::type_to_n_edges_map
static const unsigned int type_to_n_edges_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of edges on the element...
Definition: elem.h:656
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
libMesh::DofObject::invalid_id
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:421
libMesh::Elem::type_to_n_sides_map
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of sides on the element...
Definition: elem.h:607
libMesh::processor_id_type
uint8_t processor_id_type
Definition: id_types.h:104
libMesh::Parallel::Packing< const Elem * >::pack
static void pack(const Elem *const &object, OutputIter data_out, const Context *context)
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::BoundaryInfo::n_boundary_ids
std::size_t n_boundary_ids() const
Definition: boundary_info.h:360
n_nodes
const dof_id_type n_nodes
Definition: tecplot_io.C:68
libMesh::DofObject::unique_id
unique_id_type unique_id() const
Definition: dof_object.h:784
libMesh::DofObject::pack_indexing
void pack_indexing(std::back_insert_iterator< std::vector< largest_id_type >> target) const
A method for creating packed data from our index buffer - basically a copy with prepended size with o...
Definition: dof_object.C:636
libMesh::Elem::set_node
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2059
libMesh::Elem::make_links_to_me_local
void make_links_to_me_local(unsigned int n, unsigned int neighbor_side)
Resets the neighbor_side pointers of our nth neighbor (and its descendants, if appropriate) to point ...
Definition: elem.C:1007
libMesh::Elem::parent
const Elem * parent() const
Definition: elem.h:2434
libMesh::Elem::refinement_flag
RefinementState refinement_flag() const
Definition: elem.h:2614
libMesh::INVALID_ELEM
Definition: enum_elem_type.h:75
libMesh::Elem::interior_parent
const Elem * interior_parent() const
Definition: elem.C:749
libMesh::Elem::type_to_n_nodes_map
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition: elem.h:576
libMesh::Elem::n_children
virtual unsigned int n_children() const =0
libMesh::Elem::subdomain_id
subdomain_id_type subdomain_id() const
Definition: elem.h:2069
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::BoundaryInfo::add_edge
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure.
Definition: boundary_info.C:707
libMesh::Elem::has_children
bool has_children() const
Definition: elem.h:2383
libMesh::Elem::side_index_range
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2188
libMesh::DofObject::invalid_processor_id
static const 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:432
libMesh::Elem
This is the base class from which all geometric element types are derived.
Definition: elem.h:100
libMesh::BoundaryInfo::n_shellface_boundary_ids
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) const
Definition: boundary_info.C:1167
libMesh::BoundaryInfo::n_edge_boundary_ids
unsigned int n_edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
Definition: boundary_info.C:1088
libMesh::Elem::set_refinement_flag
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:2622
libMesh::BoundaryInfo::add_shellface
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
Add shell face shellface of element number elem with boundary id id to the boundary information data ...
Definition: boundary_info.C:794
libMesh::Elem::neighbor_ptr
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2085
libMesh::TestClass
Definition: id_types.h:33
libMesh::Elem::node_id
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1977
libMesh::Elem::n_sides
virtual unsigned int n_sides() const =0
libMesh::Elem::build
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:246
libMesh::BoundaryInfo::add_side
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure.
Definition: boundary_info.C:886
libMesh::DistributedMesh
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
Definition: distributed_mesh.h:50
libMesh::Elem::hack_p_level
void hack_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element without altering the p-level of its ancestor...
Definition: elem.h:2668
libMesh::Elem::type
virtual ElemType type() const =0
libMesh::remote_elem
const RemoteElem * remote_elem
Definition: remote_elem.C:57
libMesh::Elem::INVALID_REFINEMENTSTATE
Definition: elem.h:1176
libMesh::Elem::which_child_am_i
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:2596
libMesh::ElemType
ElemType
Defines an enum for geometric element types.
Definition: enum_elem_type.h:33