libMesh
parallel_elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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  // For subactive elements, we don't bother keeping neighbor
614  // links in good shape, so there's nothing we need to set or can
615  // safely assert here.
616  if (!elem->subactive())
617  for (auto n : elem->side_index_range())
618  {
619  const dof_id_type neighbor_id =
620  cast_int<dof_id_type>(*in++);
621 
622  const dof_id_type neighbor_side =
623  cast_int<dof_id_type>(*in++);
624 
625  // If the sending processor sees a domain boundary here,
626  // we'd better agree ... unless all we see is a
627  // remote_elem? In that case maybe we just couldn't keep
628  // up with a user's delete_elem. Let's trust them.
629  if (neighbor_id == DofObject::invalid_id)
630  {
631  const Elem * my_neigh = elem->neighbor_ptr(n);
632  if (my_neigh == remote_elem)
633  elem->set_neighbor(n, nullptr);
634  else
635  libmesh_assert (!my_neigh);
636  continue;
637  }
638 
639  // If the sending processor has a remote_elem neighbor here,
640  // then all we know is that we'd better *not* have a domain
641  // boundary ... except that maybe it's the *sending*
642  // processor who missed a delete_elem we saw.
643  if (neighbor_id == remote_elem->id())
644  {
645  // At this level of the code we can't even assert in
646  // cases where the neighbor should know what they're
647  // talking about, so skip it.
648 
649  // libmesh_assert(elem->neighbor_ptr(n));
650  continue;
651  }
652 
653  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
654 
655  // The sending processor sees a neighbor here, so if we
656  // don't have that neighboring element, then we'd better
657  // have a remote_elem signifying that fact.
658  if (!neigh)
659  {
660  libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
661  continue;
662  }
663 
664  // The sending processor has a neighbor here, and we have
665  // that element, but that does *NOT* mean we're already
666  // linking to it. Perhaps we initially received both elem
667  // and neigh from processors on which their mutual link was
668  // remote?
669  libmesh_assert(elem->neighbor_ptr(n) == neigh ||
670  elem->neighbor_ptr(n) == remote_elem);
671 
672  // If the link was originally remote, we should update it,
673  // and make sure the appropriate parts of its family link
674  // back to us.
675  if (elem->neighbor_ptr(n) == remote_elem)
676  {
677  elem->set_neighbor(n, neigh);
678 
679  elem->make_links_to_me_local(n, neighbor_side);
680  }
681  else
682  libmesh_assert(neigh->level() < elem->level() ||
683  neigh->neighbor_ptr(neighbor_side) == elem);
684  }
685  else
686  // We skip these to go to the boundary information if the element is
687  // actually subactive
688  in += 2*elem->n_sides();
689 
690  // Our p level and refinement flags should be "close to" correct
691  // if we're not an active element - we might have a p level
692  // increased or decreased by changes in remote_elem children.
693  //
694  // But if we have remote_elem children, then we shouldn't be
695  // doing a projection on this inactive element on this
696  // processor, so we won't need correct p settings. Couldn't
697  // hurt to update, though.
698 #ifdef LIBMESH_ENABLE_AMR
699  if (elem->processor_id() != mesh->processor_id())
700  {
701  // Do this simultaneously; otherwise we can get a false
702  // positive when a hack_p_level or set_p_refineemnt_flag
703  // assertion sees inconsistency between an old flag and new
704  // value or vice-versa
705  elem->hack_p_level_and_refinement_flag(p_level, p_refinement_flag);
706  }
707 #endif // LIBMESH_ENABLE_AMR
708 
709  // FIXME: We should add some debug mode tests to ensure that the
710  // encoded indexing and boundary conditions are consistent.
711  }
712  else
713  {
714  // We don't already have the element, so we need to create it.
715 
716  // Find the parent if necessary
717  Elem * parent = nullptr;
718 #ifdef LIBMESH_ENABLE_AMR
719  // Find a child element's parent
720  if (level > 0)
721  {
722  // Note that we must be very careful to construct the send
723  // connectivity so that parents are encountered before
724  // children. If we get here and can't find the parent that
725  // is a fatal error.
726  parent = mesh->elem_ptr(parent_id);
727  }
728  // Or assert that the sending processor sees no parent
729  else
730  libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
731 #else
732  // No non-level-0 elements without AMR
733  libmesh_assert_equal_to (level, 0);
734 #endif
735 
736  elem = Elem::build(type,parent).release();
737  libmesh_assert (elem);
738 
739 #ifdef LIBMESH_ENABLE_AMR
740  if (level != 0)
741  {
742  // Since this is a newly created element, the parent must
743  // have previously thought of this child as a remote element.
744  libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
745 
746  parent->add_child(elem, which_child_am_i);
747  }
748 
749  // Assign the refinement flags and levels
750  elem->set_p_level(p_level);
751  elem->set_refinement_flag(refinement_flag);
752  elem->set_p_refinement_flag(p_refinement_flag);
753  libmesh_assert_equal_to (elem->level(), level);
754 
755  // If this element should have children, assign remote_elem to
756  // all of them for now, for consistency. Later unpacked
757  // elements may overwrite that.
758  if (has_children)
759  {
760  const unsigned int nc = elem->n_children();
761  for (unsigned int c=0; c != nc; ++c)
762  elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
763  }
764 
765 #endif // LIBMESH_ENABLE_AMR
766 
767  // Assign the IDs
768  elem->subdomain_id() = subdomain_id;
769  elem->processor_id() = processor_id;
770  elem->set_id() = id;
771 #ifdef LIBMESH_ENABLE_UNIQUE_ID
772  elem->set_unique_id(unique_id);
773 #endif
774 
775  // Assign the connectivity
776  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
777 
778  for (unsigned int n=0; n != n_nodes; n++)
779  elem->set_node (n, mesh->node_ptr
780  (cast_int<dof_id_type>(*in++)));
781 
782  // Set interior_parent if found
783  {
784  // We may be unpacking an element that was a ghost element on the
785  // sender, in which case the element's interior_parent may not be
786  // known by the packed element. We'll have to set such
787  // interior_parents to remote_elem ourselves and wait for a
788  // later packed element to give us better information.
789  if (interior_parent_id == remote_elem->id())
790  {
791  elem->set_interior_parent
792  (const_cast<RemoteElem *>(remote_elem));
793  }
794  else if (interior_parent_id != DofObject::invalid_id)
795  {
796  // If we don't have the interior parent element, then it's
797  // a remote_elem until we get it.
798  Elem * ip =
799  mesh->interior_mesh().query_elem_ptr(interior_parent_id);
800  if (!ip )
801  elem->set_interior_parent
802  (const_cast<RemoteElem *>(remote_elem));
803  else
804  elem->set_interior_parent(ip);
805  }
806  }
807 
808  for (auto n : elem->side_index_range())
809  {
810  const dof_id_type neighbor_id =
811  cast_int<dof_id_type>(*in++);
812 
813  const dof_id_type neighbor_side =
814  cast_int<dof_id_type>(*in++);
815 
816  if (neighbor_id == DofObject::invalid_id)
817  continue;
818 
819  // We may be unpacking an element that was a ghost element on the
820  // sender, in which case the element's neighbors may not all be
821  // known by the packed element. We'll have to set such
822  // neighbors to remote_elem ourselves and wait for a later
823  // packed element to give us better information.
824  if (neighbor_id == remote_elem->id())
825  {
826  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
827  continue;
828  }
829 
830  // If we don't have the neighbor element, then it's a
831  // remote_elem until we get it.
832  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
833  if (!neigh)
834  {
835  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
836  continue;
837  }
838 
839  // If we have the neighbor element, then link to it, and
840  // make sure any appropriate parts of its family link back
841  // to us.
842  elem->set_neighbor(n, neigh);
843 
844  elem->make_links_to_me_local(n, neighbor_side);
845  }
846 
847  elem->unpack_indexing(in);
848 
849  mesh->add_elem(elem);
850  }
851 
852  in += elem->packed_indexing_size();
853 
854  // We check if this is cell holds a boundary ID or not
855  auto on_boundary = *in++;
856  if (on_boundary)
857  {
858  // Only treat the sides with caution. This is because we might hold boundary IDs
859  // on the sides of the children. This is not supported for edges and shell faces, thus
860  // they are treated assuming that only top parents can hold the IDs.
861  auto children_on_boundary = *in++;
862  if (elem->level() == 0 || children_on_boundary)
863  {
864  for (auto s : elem->side_index_range())
865  {
866  const boundary_id_type num_bcs =
867  cast_int<boundary_id_type>(*in++);
868 
869  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
871  (elem, s, cast_int<boundary_id_type>(*in++));
872  }
873  }
874  }
875 
876  // If this is a coarse element,
877  // add any element side or edge boundary condition ids
878  if (level == 0)
879  {
880  for (auto e : elem->edge_index_range())
881  {
882  const boundary_id_type num_bcs =
883  cast_int<boundary_id_type>(*in++);
884 
885  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
887  (elem, e, cast_int<boundary_id_type>(*in++));
888  }
889 
890  for (unsigned short sf=0; sf != 2; ++sf)
891  {
892  const boundary_id_type num_bcs =
893  cast_int<boundary_id_type>(*in++);
894 
895  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
897  (elem, sf, cast_int<boundary_id_type>(*in++));
898  }
899  }
900 
901  // Return the new element
902  return elem;
903 }
904 
905 
906 
907 template <>
908 Elem *
909 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
911 {
912  return unpack(in, static_cast<MeshBase*>(mesh));
913 }
914 
915 
916 
917 template <>
918 Elem *
919 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
920  ParallelMesh * mesh)
921 {
922  return unpack(in, static_cast<MeshBase*>(mesh));
923 }
924 
925 } // namespace Parallel
926 
927 } // 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:3210
ElemType
Defines an enum for geometric element types.
unique_id_type & set_unique_id()
Definition: dof_object.h:858
const Elem * parent() const
Definition: elem.h:3030
void raw_boundary_ids(const Elem *const elem, const unsigned short int side, std::vector< boundary_id_type > &vec_to_fill) const
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2558
A Node is like a Point, but with more information.
Definition: node.h:52
const MeshBase & interior_mesh() const
Definition: mesh_base.h:1797
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:575
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:310
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:685
const Elem * interior_parent() const
Definition: elem.C:1186
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2710
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) const
RefinementState p_refinement_flag() const
Definition: elem.h:3226
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:2044
RefinementState
Enumeration of possible element refinement states.
Definition: elem.h:1452
void set_refinement_flag(const RefinementState rflag)
Sets the value of the refinement flag for the element.
Definition: elem.h:3218
unique_id_type unique_id() const
Definition: dof_object.h:844
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:3108
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:165
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:1248
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:650
static unsigned int packable_size(const T &object, const Context *context)
This is the MeshBase class.
Definition: mesh_base.h:75
dof_id_type & set_id()
Definition: dof_object.h:836
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2692
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:1455
dof_id_type id() const
Definition: dof_object.h:828
virtual unsigned int n_nodes() const =0
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:487
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:493
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:743
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:444
static unsigned int packed_size(BufferIter iter)
libmesh_assert(ctx)
static const dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:482
bool valid_unique_id() const
Definition: dof_object.h:893
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:3275
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2618
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:3192
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2665
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:2598
unsigned int level() const
Definition: elem.h:3074
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:2582
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:560
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:642
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:2959
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:595
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:3503
void set_p_refinement_flag(const RefinementState pflag)
Sets the value of the p-refinement flag for the element.
Definition: elem.h:3234
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
bool active() const
Definition: elem.h:2941
processor_id_type processor_id() const
Definition: dof_object.h:905
virtual ElemType type() const =0
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2475
uint8_t unique_id_type
Definition: id_types.h:86
bool has_children() const
Definition: elem.h:2979
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:3163
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