libMesh
parallel_elem.C
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 // 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  if (n_nodes == invalid_uint)
80  libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
81 
82  const unsigned int n_sides =
84 
85  const unsigned int n_edges =
87 
88  const unsigned int pre_indexing_size =
89  header_size + n_nodes + n_sides*2;
90 
91  const unsigned int indexing_size =
92  DofObject::unpackable_indexing_size(in+pre_indexing_size);
93 
94  // We communicate if we are on the boundary or not
95  unsigned int total_packed_bc_data = 1;
96  largest_id_type on_boundary = *(in + pre_indexing_size + indexing_size);
97 
98  if (on_boundary)
99  {
100  // Extracting if the children are allowed on the boundary
101  total_packed_bc_data++;
102  largest_id_type allow_children_on_boundary = *(in + pre_indexing_size + indexing_size + 1);
103 
104  // For now, children are only supported on sides, the nodes and shell faces are
105  // treated using the top parents only
106  if (level == 0 || allow_children_on_boundary)
107  {
108  for (unsigned int s = 0; s != n_sides; ++s)
109  {
110  const int n_bcs = cast_int<int>
111  (*(in + pre_indexing_size + indexing_size +
112  total_packed_bc_data++));
113  libmesh_assert_greater_equal (n_bcs, 0);
114  total_packed_bc_data += n_bcs;
115  }
116  }
117  }
118  if (level == 0)
119  {
120  for (unsigned int e = 0; e != n_edges; ++e)
121  {
122  const int n_bcs = cast_int<int>
123  (*(in + pre_indexing_size + indexing_size +
124  total_packed_bc_data++));
125  libmesh_assert_greater_equal (n_bcs, 0);
126  total_packed_bc_data += n_bcs;
127  }
128 
129  for (unsigned short sf=0; sf != 2; ++sf)
130  {
131  const int n_bcs = cast_int<int>
132  (*(in + pre_indexing_size + indexing_size +
133  total_packed_bc_data++));
134  libmesh_assert_greater_equal (n_bcs, 0);
135  total_packed_bc_data += n_bcs;
136  }
137  }
138 
139  return
140 #ifndef NDEBUG
141  1 + // Account for magic header
142 #endif
143  pre_indexing_size + indexing_size + total_packed_bc_data;
144 }
145 
146 
147 
148 template <>
149 unsigned int
150 Packing<const Elem *>::packed_size (std::vector<largest_id_type>::iterator in)
151 {
152  return packed_size(std::vector<largest_id_type>::const_iterator(in));
153 }
154 
155 
156 
157 template <>
158 unsigned int
159 Packing<const Elem *>::packable_size (const Elem * const & elem,
160  const MeshBase * mesh)
161 {
162  // We always communicate if we are on a boundary or not
163  unsigned int total_packed_bcs = 1;
164  const unsigned short n_sides = elem->n_sides();
165 
166  largest_id_type on_boundary = 0;
167  for (auto s : elem->side_index_range())
169  {
170  on_boundary = 1;
171  break;
172  }
173 
174  if (on_boundary)
175  {
176  // In this case we need another entry to check if we allow children on the boundary.
177  // We only allow children on sides, edges and sheel faces are treated normally using
178  // their top parents.
179  total_packed_bcs++;
180  if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
181  {
182  total_packed_bcs += n_sides;
183  for (unsigned short s = 0; s != n_sides; ++s)
184  total_packed_bcs +=
186  }
187  }
188 
189  if (elem->level() == 0)
190  {
191  const unsigned short n_edges = elem->n_edges();
192  total_packed_bcs += n_edges;
193  for (unsigned short e = 0; e != n_edges; ++e)
194  total_packed_bcs +=
196 
197  total_packed_bcs += 2; // shellfaces
198  for (unsigned short sf=0; sf != 2; ++sf)
199  total_packed_bcs +=
201  }
202 
203  return
204 #ifndef NDEBUG
205  1 + // add an int for the magic header when testing
206 #endif
207  header_size + elem->n_nodes() + n_sides*2 +
208  elem->packed_indexing_size() + total_packed_bcs;
209 }
210 
211 
212 
213 template <>
214 unsigned int
215 Packing<const Elem *>::packable_size (const Elem * const & elem,
216  const DistributedMesh * mesh)
217 {
218  return packable_size(elem, static_cast<const MeshBase *>(mesh));
219 }
220 
221 
222 
223 template <>
224 unsigned int
225 Packing<const Elem *>::packable_size (const Elem * const & elem,
226  const ParallelMesh * mesh)
227 {
228  return packable_size(elem, static_cast<const MeshBase *>(mesh));
229 }
230 
231 
232 
233 template <>
234 void
235 Packing<const Elem *>::pack (const Elem * const & elem,
236  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
237  const MeshBase * mesh)
238 {
239  libmesh_assert(elem);
240 
241 #ifndef NDEBUG
242  *data_out++ = elem_magic_header;
243 #endif
244 
245 #ifdef LIBMESH_ENABLE_AMR
246  *data_out++ = (static_cast<largest_id_type>(elem->level()));
247  *data_out++ = (static_cast<largest_id_type>(elem->p_level()));
248 
249  // Encode both the refinement flag and whether the element has
250  // children together. This coding is unambiguous because our
251  // refinement state encoding starts at 0 and ends at
252  // INVALID_REFINEMENTSTATE
253  largest_id_type refinement_info =
254  static_cast<largest_id_type>(elem->refinement_flag());
255  if (elem->has_children())
256  refinement_info +=
257  static_cast<largest_id_type>(Elem::INVALID_REFINEMENTSTATE) + 1;
258  *data_out++ = (refinement_info);
259 
260  *data_out++ = (static_cast<largest_id_type>(elem->p_refinement_flag()));
261 #else
262  *data_out++ = (0);
263  *data_out++ = (0);
264  *data_out++ = (0);
265  *data_out++ = (0);
266 #endif
267  *data_out++ = (static_cast<largest_id_type>(elem->type()));
268  *data_out++ = (elem->processor_id());
269  *data_out++ = (elem->subdomain_id());
270  *data_out++ = (elem->id());
271 
272 #ifdef LIBMESH_ENABLE_UNIQUE_ID
273  if (elem->valid_unique_id())
274  *data_out++ = (static_cast<largest_id_type>(elem->unique_id()));
275  else
276  // OK to send invalid unique id, we must not own this DOF
277  *data_out++ = (static_cast<largest_id_type>(DofObject::invalid_unique_id));
278 #endif
279 
280 #ifdef LIBMESH_ENABLE_AMR
281  // use parent_ID of invalid_id to indicate a level 0 element
282  if (elem->level() == 0)
283  {
284  *data_out++ =(DofObject::invalid_id);
285  *data_out++ =(DofObject::invalid_id);
286  }
287  else
288  {
289  *data_out++ =(elem->parent()->id());
290  *data_out++ =(elem->parent()->which_child_am_i(elem));
291  }
292 #else
293  *data_out++ = (DofObject::invalid_id);
294  *data_out++ = (DofObject::invalid_id);
295 #endif
296 
297  if ((elem->dim() < LIBMESH_DIM) &&
298  elem->interior_parent())
299  *data_out++ =(elem->interior_parent()->id());
300  else
301  *data_out++ =(DofObject::invalid_id);
302 
303  for (const Node & node : elem->node_ref_range())
304  *data_out++ = node.id();
305 
306  // Add the id of and the side for any return link from each neighbor
307  for (auto neigh : elem->neighbor_ptr_range())
308  {
309  if (neigh)
310  {
311  *data_out++ = (neigh->id());
312  if (neigh == remote_elem)
313  *data_out++ = (DofObject::invalid_id);
314  else
315  *data_out++ = neigh->which_neighbor_am_i(elem);
316  }
317  else
318  {
319  *data_out++ = (DofObject::invalid_id);
320  *data_out++ = (DofObject::invalid_id);
321  }
322  }
323 
324  // Add any DofObject indices
325  elem->pack_indexing(data_out);
326 
327  // We check if this is a boundary cell. We use the raw
328  // IDs because we also communicate the parents which
329  // will bring their associated IDs
330  largest_id_type on_boundary = 0;
331  for (auto s : elem->side_index_range())
333  {
334  on_boundary = 1;
335  break;
336  }
337 
338  *data_out++ = on_boundary;
339 
340  if (on_boundary)
341  {
343  // Again, only do this if we allow children to hold boundary sides, the edges and
344  // shell faces are treated normally using their top parents
345  if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
346  {
347  std::vector<boundary_id_type> bcs;
348  for (auto s : elem->side_index_range())
349  {
350  mesh->get_boundary_info().raw_boundary_ids(elem, s, bcs);
351 
352  *data_out++ =(bcs.size());
353 
354  for (const auto & bid : bcs)
355  *data_out++ = bid;
356  }
357  }
358  }
359 
360  // If this is a coarse element,
361  // Add any element side boundary condition ids
362  if (elem->level() == 0)
363  {
364  std::vector<boundary_id_type> bcs;
365  for (auto e : elem->edge_index_range())
366  {
367  mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
368 
369  *data_out++ =(bcs.size());
370 
371  for (const auto & bid : bcs)
372  *data_out++ = bid;
373  }
374 
375  for (unsigned short sf=0; sf != 2; ++sf)
376  {
378 
379  *data_out++ =(bcs.size());
380 
381  for (const auto & bid : bcs)
382  *data_out++ = bid;
383  }
384  }
385 }
386 
387 
388 
389 template <>
390 void
391 Packing<const Elem *>::pack (const Elem * const & elem,
392  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
393  const DistributedMesh * mesh)
394 {
395  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
396 }
397 
398 
399 
400 template <>
401 void
402 Packing<const Elem *>::pack (const Elem * const & elem,
403  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
404  const ParallelMesh * mesh)
405 {
406  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
407 }
408 
409 
410 
411 // FIXME - this needs serious work to be 64-bit compatible
412 template <>
413 Elem *
414 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
415  MeshBase * mesh)
416 {
417 #ifndef NDEBUG
418  const std::vector<largest_id_type>::const_iterator original_in = in;
419 
420  const largest_id_type incoming_header = *in++;
421  libmesh_assert_equal_to (incoming_header, elem_magic_header);
422 #endif
423 
424  // int 0: level
425  const unsigned int level =
426  cast_int<unsigned int>(*in++);
427 
428 #ifdef LIBMESH_ENABLE_AMR
429  // int 1: p level
430  const unsigned int p_level =
431  cast_int<unsigned int>(*in++);
432 
433  // int 2: refinement flag and encoded has_children
434  const int rflag = cast_int<int>(*in++);
435  const int invalid_rflag =
436  cast_int<int>(Elem::INVALID_REFINEMENTSTATE);
437  libmesh_assert_greater_equal (rflag, 0);
438 
439  libmesh_assert_less (rflag, invalid_rflag*2+1);
440 
441  const bool has_children = (rflag > invalid_rflag);
442 
443  const Elem::RefinementState refinement_flag = has_children ?
444  cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
445  cast_int<Elem::RefinementState>(rflag);
446 
447  // int 3: p refinement flag
448  const int pflag = cast_int<int>(*in++);
449  libmesh_assert_greater_equal (pflag, 0);
450  libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
451  const Elem::RefinementState p_refinement_flag =
452  cast_int<Elem::RefinementState>(pflag);
453 #else
454  in += 3;
455 #endif // LIBMESH_ENABLE_AMR
456 
457  // int 4: element type
458  const int typeint = cast_int<int>(*in++);
459  libmesh_assert_greater_equal (typeint, 0);
460  libmesh_assert_less (typeint, INVALID_ELEM);
461  const ElemType type =
462  cast_int<ElemType>(typeint);
463 
464  const unsigned int n_nodes =
466 
467  // int 5: processor id
468  const processor_id_type processor_id =
469  cast_int<processor_id_type>(*in++);
470  libmesh_assert (processor_id < mesh->n_processors() ||
471  processor_id == DofObject::invalid_processor_id);
472 
473  // int 6: subdomain id
474  const subdomain_id_type subdomain_id =
475  cast_int<subdomain_id_type>(*in++);
476 
477  // int 7: dof object id
478  const dof_id_type id =
479  cast_int<dof_id_type>(*in++);
480  libmesh_assert_not_equal_to (id, DofObject::invalid_id);
481 
482 #ifdef LIBMESH_ENABLE_UNIQUE_ID
483  // int 8: dof object unique id
484  const unique_id_type unique_id =
485  cast_int<unique_id_type>(*in++);
486 #endif
487 
488 #ifdef LIBMESH_ENABLE_AMR
489  // int 9: parent dof object id.
490  // Note: If level==0, then (*in) == invalid_id. In
491  // this case, the equality check in cast_int<unsigned>(*in) will
492  // never succeed. Therefore, we should only attempt the more
493  // rigorous cast verification in cases where level != 0.
494  const dof_id_type parent_id =
495  (level == 0)
496  ? static_cast<dof_id_type>(*in++)
497  : cast_int<dof_id_type>(*in++);
498  libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
499  libmesh_assert (level != 0 || parent_id == DofObject::invalid_id);
500 
501  // int 10: local child id
502  // Note: If level==0, then which_child_am_i is not valid, so don't
503  // do the more rigorous cast verification.
504  const unsigned int which_child_am_i =
505  (level == 0)
506  ? static_cast<unsigned int>(*in++)
507  : cast_int<unsigned int>(*in++);
508 #else
509  in += 2;
510 #endif // LIBMESH_ENABLE_AMR
511 
512  const dof_id_type interior_parent_id =
513  static_cast<dof_id_type>(*in++);
514 
515  // Make sure we don't miscount above when adding the "magic" header
516  // plus the real data header
517  libmesh_assert_equal_to (in - original_in, header_size + 1);
518 
519  Elem * elem = mesh->query_elem_ptr(id);
520 
521  // if we already have this element, make sure its
522  // properties match, and update any missing neighbor
523  // links, but then go on
524  if (elem)
525  {
526  libmesh_assert_equal_to (elem->level(), level);
527  libmesh_assert_equal_to (elem->id(), id);
528  //#ifdef LIBMESH_ENABLE_UNIQUE_ID
529  // No check for unique id sanity
530  //#endif
531  libmesh_assert_equal_to (elem->processor_id(), processor_id);
532  libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
533  libmesh_assert_equal_to (elem->type(), type);
534  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
535 
536 #ifndef NDEBUG
537  // All our nodes should be correct
538  for (unsigned int i=0; i != n_nodes; ++i)
539  libmesh_assert(elem->node_id(i) ==
540  cast_int<dof_id_type>(*in++));
541 #else
542  in += n_nodes;
543 #endif
544 
545 #ifdef LIBMESH_ENABLE_AMR
546  libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
547  libmesh_assert_equal_to (elem->has_children(), has_children);
548 
549 #ifdef DEBUG
550  if (elem->active())
551  {
552  libmesh_assert_equal_to (elem->p_level(), p_level);
553  libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);
554  }
555 #endif
556 
557  libmesh_assert (!level || elem->parent() != nullptr);
558  libmesh_assert (!level || elem->parent()->id() == parent_id);
559  libmesh_assert (!level || elem->parent()->child_ptr(which_child_am_i) == elem);
560 #endif
561  // Our interior_parent link should be "close to" correct - we
562  // may have to update it, but we can check for some
563  // inconsistencies.
564  {
565  // If the sending processor sees no interior_parent here, we'd
566  // better agree.
567  if (interior_parent_id == DofObject::invalid_id)
568  {
569  if (elem->dim() < LIBMESH_DIM)
570  libmesh_assert (!(elem->interior_parent()));
571  }
572 
573  // If the sending processor has a remote_elem interior_parent,
574  // then all we know is that we'd better have *some*
575  // interior_parent
576  else if (interior_parent_id == remote_elem->id())
577  {
579  }
580  else
581  {
582  Elem * ip =
583  mesh->interior_mesh().query_elem_ptr(interior_parent_id);
584 
585  // The sending processor sees an interior parent here, so
586  // if we don't have that interior element, then we'd
587  // better have a remote_elem signifying that fact.
588  if (!ip)
589  libmesh_assert_equal_to (elem->interior_parent(), remote_elem);
590  else
591  {
592  // The sending processor has an interior_parent here,
593  // and we have that element, but that does *NOT* mean
594  // we're already linking to it. Perhaps we initially
595  // received elem from a processor on which the
596  // interior_parent link was remote?
597  libmesh_assert(elem->interior_parent() == ip ||
598  elem->interior_parent() == remote_elem);
599 
600  // If the link was originally remote, update it
601  if (elem->interior_parent() == remote_elem)
602  {
603  elem->set_interior_parent(ip);
604  }
605  }
606  }
607  }
608 
609  // Our neighbor links should be "close to" correct - we may have
610  // to update a remote_elem link, and we can check for possible
611  // inconsistencies along the way.
612  //
613  // Even for subactive elements, we'll try to keep neighbor links
614  // in good shape now, if only so any future find_neighbors() is
615  // idempotent.
616  for (auto n : elem->side_index_range())
617  {
618  const dof_id_type neighbor_id =
619  cast_int<dof_id_type>(*in++);
620 
621  const dof_id_type neighbor_side =
622  cast_int<dof_id_type>(*in++);
623 
624  // If the sending processor sees a domain boundary here,
625  // we'd better agree ... unless all we see is a remote_elem?
626  // In that case maybe we just couldn't keep up with a user's
627  // delete_elem. Let's trust them.
628  if (neighbor_id == DofObject::invalid_id)
629  {
630  const Elem * my_neigh = elem->neighbor_ptr(n);
631  if (my_neigh == remote_elem)
632  elem->set_neighbor(n, nullptr);
633  else
634  libmesh_assert (!my_neigh);
635  continue;
636  }
637 
638  // If the sending processor has a remote_elem neighbor here,
639  // then all we know is that we'd better *not* have a domain
640  // boundary ... except that maybe it's the *sending*
641  // processor who missed a delete_elem we saw.
642  if (neighbor_id == remote_elem->id())
643  {
644  // At this level of the code we can't even assert in
645  // cases where the neighbor should know what they're
646  // talking about, so skip it.
647 
648  // libmesh_assert(elem->neighbor_ptr(n));
649  continue;
650  }
651 
652  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
653 
654  // The sending processor sees a neighbor here, so if we
655  // don't have that neighboring element, then we'd better
656  // have a remote_elem signifying that fact.
657  if (!neigh)
658  {
659  libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
660  continue;
661  }
662 
663  // The sending processor has a neighbor here, and we have
664  // that element, but that does *NOT* mean we're already
665  // linking to it. Perhaps we initially received both elem
666  // and neigh from processors on which their mutual link was
667  // remote?
668  libmesh_assert(elem->neighbor_ptr(n) == neigh ||
669  elem->neighbor_ptr(n) == remote_elem);
670 
671  // If the link was originally remote, we should update it,
672  // and make sure the appropriate parts of its family link
673  // back to us.
674  if (elem->neighbor_ptr(n) == remote_elem)
675  {
676  elem->set_neighbor(n, neigh);
677  }
678  else
679  libmesh_assert(elem->subactive() ||
680  neigh->level() < elem->level() ||
681  neigh->neighbor_ptr(neighbor_side) == elem);
682 
683  if (neighbor_side != libMesh::invalid_uint)
684  elem->make_links_to_me_local(n, neighbor_side);
685  }
686 
687  // Our p level and refinement flags should be "close to" correct
688  // if we're not an active element - we might have a p level
689  // increased or decreased by changes in remote_elem children.
690  //
691  // But if we have remote_elem children, then we shouldn't be
692  // doing a projection on this inactive element on this
693  // processor, so we won't need correct p settings. Couldn't
694  // hurt to update, though.
695 #ifdef LIBMESH_ENABLE_AMR
696  if (elem->processor_id() != mesh->processor_id())
697  {
698  // Do this simultaneously; otherwise we can get a false
699  // positive when a hack_p_level or set_p_refineemnt_flag
700  // assertion sees inconsistency between an old flag and new
701  // value or vice-versa
702  elem->hack_p_level_and_refinement_flag(p_level, p_refinement_flag);
703  }
704 #endif // LIBMESH_ENABLE_AMR
705 
706  // FIXME: We should add some debug mode tests to ensure that the
707  // encoded indexing and boundary conditions are consistent.
708  }
709  else
710  {
711  // We don't already have the element, so we need to create it.
712 
713  // Find the parent if necessary
714  Elem * parent = nullptr;
715 #ifdef LIBMESH_ENABLE_AMR
716  // Find a child element's parent
717  if (level > 0)
718  {
719  // Note that we must be very careful to construct the send
720  // connectivity so that parents are encountered before
721  // children. If we get here and can't find the parent that
722  // is a fatal error.
723  parent = mesh->elem_ptr(parent_id);
724  }
725  // Or assert that the sending processor sees no parent
726  else
727  libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
728 #else
729  // No non-level-0 elements without AMR
730  libmesh_assert_equal_to (level, 0);
731 #endif
732 
733  elem = Elem::build(type,parent).release();
734  libmesh_assert (elem);
735 
736 #ifdef LIBMESH_ENABLE_AMR
737  if (level != 0)
738  {
739  // Since this is a newly created element, the parent must
740  // have previously thought of this child as a remote element.
741  libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
742 
743  parent->add_child(elem, which_child_am_i);
744  }
745 
746  // Assign the refinement flags and levels
747  elem->set_p_level(p_level);
748  elem->set_refinement_flag(refinement_flag);
749  elem->set_p_refinement_flag(p_refinement_flag);
750  libmesh_assert_equal_to (elem->level(), level);
751 
752  // If this element should have children, assign remote_elem to
753  // all of them for now, for consistency. Later unpacked
754  // elements may overwrite that.
755  if (has_children)
756  {
757  const unsigned int nc = elem->n_children();
758  for (unsigned int c=0; c != nc; ++c)
759  elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
760  }
761 
762 #endif // LIBMESH_ENABLE_AMR
763 
764  // Assign the IDs
765  elem->subdomain_id() = subdomain_id;
766  elem->processor_id() = processor_id;
767  elem->set_id() = id;
768 #ifdef LIBMESH_ENABLE_UNIQUE_ID
769  elem->set_unique_id(unique_id);
770 #endif
771 
772  // Assign the connectivity
773  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
774 
775  for (unsigned int n=0; n != n_nodes; n++)
776  elem->set_node (n, mesh->node_ptr
777  (cast_int<dof_id_type>(*in++)));
778 
779  // Set interior_parent if found
780  {
781  // We may be unpacking an element that was a ghost element on the
782  // sender, in which case the element's interior_parent may not be
783  // known by the packed element. We'll have to set such
784  // interior_parents to remote_elem ourselves and wait for a
785  // later packed element to give us better information.
786  if (interior_parent_id == remote_elem->id())
787  {
788  elem->set_interior_parent
789  (const_cast<RemoteElem *>(remote_elem));
790  }
791  else if (interior_parent_id != DofObject::invalid_id)
792  {
793  // If we don't have the interior parent element, then it's
794  // a remote_elem until we get it.
795  Elem * ip =
796  mesh->interior_mesh().query_elem_ptr(interior_parent_id);
797  if (!ip )
798  elem->set_interior_parent
799  (const_cast<RemoteElem *>(remote_elem));
800  else
801  elem->set_interior_parent(ip);
802  }
803  }
804 
805  for (auto n : elem->side_index_range())
806  {
807  const dof_id_type neighbor_id =
808  cast_int<dof_id_type>(*in++);
809 
810  const dof_id_type neighbor_side =
811  cast_int<dof_id_type>(*in++);
812 
813  if (neighbor_id == DofObject::invalid_id)
814  continue;
815 
816  // We may be unpacking an element that was a ghost element on the
817  // sender, in which case the element's neighbors may not all be
818  // known by the packed element. We'll have to set such
819  // neighbors to remote_elem ourselves and wait for a later
820  // packed element to give us better information.
821  if (neighbor_id == remote_elem->id())
822  {
823  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
824  continue;
825  }
826 
827  // If we don't have the neighbor element, then it's a
828  // remote_elem until we get it.
829  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
830  if (!neigh)
831  {
832  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
833  continue;
834  }
835 
836  // If we have the neighbor element, then link to it, and
837  // make sure any appropriate parts of its family link back
838  // to us.
839  elem->set_neighbor(n, neigh);
840 
841  if (neighbor_side != libMesh::invalid_uint)
842  elem->make_links_to_me_local(n, neighbor_side);
843  }
844 
845  elem->unpack_indexing(in);
846 
847  mesh->add_elem(elem);
848  }
849 
850  in += elem->packed_indexing_size();
851 
852  // We check if this is cell holds a boundary ID or not
853  auto on_boundary = *in++;
854  if (on_boundary)
855  {
856  // Only treat the sides with caution. This is because we might hold boundary IDs
857  // on the sides of the children. This is not supported for edges and shell faces, thus
858  // they are treated assuming that only top parents can hold the IDs.
859  auto children_on_boundary = *in++;
860  if (elem->level() == 0 || children_on_boundary)
861  {
862  for (auto s : elem->side_index_range())
863  {
864  const boundary_id_type num_bcs =
865  cast_int<boundary_id_type>(*in++);
866 
867  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
869  (elem, s, cast_int<boundary_id_type>(*in++));
870  }
871  }
872  }
873 
874  // If this is a coarse element,
875  // add any element side or edge boundary condition ids
876  if (level == 0)
877  {
878  for (auto e : elem->edge_index_range())
879  {
880  const boundary_id_type num_bcs =
881  cast_int<boundary_id_type>(*in++);
882 
883  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
885  (elem, e, cast_int<boundary_id_type>(*in++));
886  }
887 
888  for (unsigned short sf=0; sf != 2; ++sf)
889  {
890  const boundary_id_type num_bcs =
891  cast_int<boundary_id_type>(*in++);
892 
893  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
895  (elem, sf, cast_int<boundary_id_type>(*in++));
896  }
897  }
898 
899  // Return the new element
900  return elem;
901 }
902 
903 
904 
905 template <>
906 Elem *
907 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
909 {
910  return unpack(in, static_cast<MeshBase*>(mesh));
911 }
912 
913 
914 
915 template <>
916 Elem *
917 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
918  ParallelMesh * mesh)
919 {
920  return unpack(in, static_cast<MeshBase*>(mesh));
921 }
922 
923 } // namespace Parallel
924 
925 } // namespace libMesh
void set_p_level(const unsigned int p)
Sets the value of the p-refinement level for the element.
RefinementState refinement_flag() const
Definition: elem.h:3224
ElemType
Defines an enum for geometric element types.
const Elem * parent() const
Definition: elem.h:3044
void raw_boundary_ids(const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
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
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2564
A Node is like a Point, but with more information.
Definition: node.h:52
const MeshBase & interior_mesh() const
Definition: mesh_base.h:1983
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:567
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
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:678
const Elem * interior_parent() const
Definition: elem.C:1156
static constexpr unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:478
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2724
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) const
RefinementState p_refinement_flag() const
Definition: elem.h:3240
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
uint64_t largest_id_type
Definition: id_types.h:148
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
Definition: elem.C:2049
RefinementState
Enumeration of possible element refinement states.
Definition: elem.h:1443
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3232
unique_id_type unique_id() const
Definition: dof_object.h:835
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:3122
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
The libMesh namespace provides an interface to certain functionality in the library.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:175
static T unpack(BufferIter in, Context *ctx)
Definition: parallel_elem.h:90
void set_interior_parent(Elem *p)
Sets the pointer to the element&#39;s interior_parent.
Definition: elem.C:1218
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:643
static unsigned int packable_size(const T &object, const Context *context)
This is the MeshBase class.
Definition: mesh_base.h:85
dof_id_type & set_id()
Definition: dof_object.h:827
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2706
uint8_t processor_id_type
const dof_id_type n_nodes
Definition: tecplot_io.C:67
int8_t boundary_id_type
Definition: id_types.h:51
unsigned int n_raw_boundary_ids(const Elem *const elem, const unsigned short int side) const
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:1425
dof_id_type id() const
Definition: dof_object.h:819
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:473
virtual unsigned int n_nodes() const =0
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:742
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:442
static unsigned int packed_size(BufferIter iter)
libmesh_assert(ctx)
bool valid_unique_id() const
Definition: dof_object.h:869
virtual unsigned int n_edges() const =0
void hack_p_level_and_refinement_flag(const unsigned int p, RefinementState pflag)
Sets the value of the p-refinement level for the element without altering the p-level of its ancestor...
Definition: elem.h:3289
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2632
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
static void pack(const T &object, OutputIter data_out, const Context *context)
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:3206
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2679
virtual const Elem * elem_ptr(const dof_id_type i) const =0
virtual unsigned int n_sides() const =0
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2612
unsigned int level() const
Definition: elem.h:3088
void set_unique_id(unique_id_type new_id)
Sets the unique_id for this DofObject.
Definition: dof_object.h:848
unsigned int n_edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
virtual const Elem * query_elem_ptr(const dof_id_type i) const =0
subdomain_id_type subdomain_id() const
Definition: elem.h:2588
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:552
virtual unsigned short dim() const =0
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:634
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...
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 ...
bool subactive() const
Definition: elem.h:2973
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:587
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
bool is_children_on_boundary_side() const
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:3517
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:3248
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
bool active() const
Definition: elem.h:2955
processor_id_type processor_id() const
Definition: dof_object.h:881
virtual ElemType type() const =0
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2481
uint8_t unique_id_type
Definition: id_types.h:86
bool has_children() const
Definition: elem.h:2993
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:3177
uint8_t dof_id_type
Definition: id_types.h:67
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...
const RemoteElem * remote_elem
Definition: remote_elem.C:57