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