parallel_elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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"
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 +=
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 +=
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 (const auto & bid : bcs)
299  *data_out++ = bid;
300  }
301 
302  for (auto e : elem->edge_index_range())
303  {
304  mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
305 
306  *data_out++ =(bcs.size());
307 
308  for (const auto & bid : bcs)
309  *data_out++ = bid;
310  }
311 
312  for (unsigned short sf=0; sf != 2; ++sf)
313  {
315 
316  *data_out++ =(bcs.size());
317 
318  for (const auto & bid : bcs)
319  *data_out++ = bid;
320  }
321  }
322 }
323 
324 
325 
326 template <>
327 template <>
328 void
329 Packing<const Elem *>::pack (const Elem * const & elem,
330  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
331  const DistributedMesh * mesh)
332 {
333  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
334 }
335 
336 
337 
338 template <>
339 template <>
340 void
341 Packing<const Elem *>::pack (const Elem * const & elem,
342  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
343  const ParallelMesh * mesh)
344 {
345  pack(elem, data_out, static_cast<const MeshBase*>(mesh));
346 }
347 
348 
349 
350 // FIXME - this needs serious work to be 64-bit compatible
351 template <>
352 template <>
353 Elem *
354 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
355  MeshBase * mesh)
356 {
357 #ifndef NDEBUG
358  const std::vector<largest_id_type>::const_iterator original_in = in;
359 
360  const largest_id_type incoming_header = *in++;
361  libmesh_assert_equal_to (incoming_header, elem_magic_header);
362 #endif
363 
364  // int 0: level
365  const unsigned int level =
366  cast_int<unsigned int>(*in++);
367 
368 #ifdef LIBMESH_ENABLE_AMR
369  // int 1: p level
370  const unsigned int p_level =
371  cast_int<unsigned int>(*in++);
372 
373  // int 2: refinement flag and encoded has_children
374  const int rflag = cast_int<int>(*in++);
375  const int invalid_rflag =
376  cast_int<int>(Elem::INVALID_REFINEMENTSTATE);
377  libmesh_assert_greater_equal (rflag, 0);
378 
379  libmesh_assert_less (rflag, invalid_rflag*2+1);
380 
381  const bool has_children = (rflag > invalid_rflag);
382 
383  const Elem::RefinementState refinement_flag = has_children ?
384  cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
385  cast_int<Elem::RefinementState>(rflag);
386 
387  // int 3: p refinement flag
388  const int pflag = cast_int<int>(*in++);
389  libmesh_assert_greater_equal (pflag, 0);
390  libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
391  const Elem::RefinementState p_refinement_flag =
392  cast_int<Elem::RefinementState>(pflag);
393 #else
394  in += 3;
395 #endif // LIBMESH_ENABLE_AMR
396 
397  // int 4: element type
398  const int typeint = cast_int<int>(*in++);
399  libmesh_assert_greater_equal (typeint, 0);
400  libmesh_assert_less (typeint, INVALID_ELEM);
401  const ElemType type =
402  cast_int<ElemType>(typeint);
403 
404  const unsigned int n_nodes =
406 
407  // int 5: processor id
408  const processor_id_type processor_id =
409  cast_int<processor_id_type>(*in++);
410  libmesh_assert (processor_id < mesh->n_processors() ||
411  processor_id == DofObject::invalid_processor_id);
412 
413  // int 6: subdomain id
414  const subdomain_id_type subdomain_id =
415  cast_int<subdomain_id_type>(*in++);
416 
417  // int 7: dof object id
418  const dof_id_type id =
419  cast_int<dof_id_type>(*in++);
420  libmesh_assert_not_equal_to (id, DofObject::invalid_id);
421 
422 #ifdef LIBMESH_ENABLE_UNIQUE_ID
423  // int 8: dof object unique id
424  const unique_id_type unique_id =
425  cast_int<unique_id_type>(*in++);
426 #endif
427 
428 #ifdef LIBMESH_ENABLE_AMR
429  // int 9: parent dof object id.
430  // Note: If level==0, then (*in) == invalid_id. In
431  // this case, the equality check in cast_int<unsigned>(*in) will
432  // never succeed. Therefore, we should only attempt the more
433  // rigorous cast verification in cases where level != 0.
434  const dof_id_type parent_id =
435  (level == 0)
436  ? static_cast<dof_id_type>(*in++)
437  : cast_int<dof_id_type>(*in++);
438  libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
439  libmesh_assert (level != 0 || parent_id == DofObject::invalid_id);
440 
441  // int 10: local child id
442  // Note: If level==0, then which_child_am_i is not valid, so don't
443  // do the more rigorous cast verification.
444  const unsigned int which_child_am_i =
445  (level == 0)
446  ? static_cast<unsigned int>(*in++)
447  : cast_int<unsigned int>(*in++);
448 #else
449  in += 2;
450 #endif // LIBMESH_ENABLE_AMR
451 
452  const dof_id_type interior_parent_id =
453  static_cast<dof_id_type>(*in++);
454 
455  // Make sure we don't miscount above when adding the "magic" header
456  // plus the real data header
457  libmesh_assert_equal_to (in - original_in, header_size + 1);
458 
459  Elem * elem = mesh->query_elem_ptr(id);
460 
461  // if we already have this element, make sure its
462  // properties match, and update any missing neighbor
463  // links, but then go on
464  if (elem)
465  {
466  libmesh_assert_equal_to (elem->level(), level);
467  libmesh_assert_equal_to (elem->id(), id);
468  //#ifdef LIBMESH_ENABLE_UNIQUE_ID
469  // No check for unique id sanity
470  //#endif
471  libmesh_assert_equal_to (elem->processor_id(), processor_id);
472  libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
473  libmesh_assert_equal_to (elem->type(), type);
474  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
475 
476 #ifndef NDEBUG
477  // All our nodes should be correct
478  for (unsigned int i=0; i != n_nodes; ++i)
479  libmesh_assert(elem->node_id(i) ==
480  cast_int<dof_id_type>(*in++));
481 #else
482  in += n_nodes;
483 #endif
484 
485 #ifdef LIBMESH_ENABLE_AMR
486  libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
487  libmesh_assert_equal_to (elem->has_children(), has_children);
488 
489 #ifdef DEBUG
490  if (elem->active())
491  {
492  libmesh_assert_equal_to (elem->p_level(), p_level);
493  libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);
494  }
495 #endif
496 
497  libmesh_assert (!level || elem->parent() != nullptr);
498  libmesh_assert (!level || elem->parent()->id() == parent_id);
499  libmesh_assert (!level || elem->parent()->child_ptr(which_child_am_i) == elem);
500 #endif
501  // Our interior_parent link should be "close to" correct - we
502  // may have to update it, but we can check for some
503  // inconsistencies.
504  {
505  // If the sending processor sees no interior_parent here, we'd
506  // better agree.
507  if (interior_parent_id == DofObject::invalid_id)
508  {
509  if (elem->dim() < LIBMESH_DIM)
510  libmesh_assert (!(elem->interior_parent()));
511  }
512 
513  // If the sending processor has a remote_elem interior_parent,
514  // then all we know is that we'd better have *some*
515  // interior_parent
516  else if (interior_parent_id == remote_elem->id())
517  {
518  libmesh_assert(elem->interior_parent());
519  }
520  else
521  {
522  Elem * ip = mesh->query_elem_ptr(interior_parent_id);
523 
524  // The sending processor sees an interior parent here, so
525  // if we don't have that interior element, then we'd
526  // better have a remote_elem signifying that fact.
527  if (!ip)
528  libmesh_assert_equal_to (elem->interior_parent(), remote_elem);
529  else
530  {
531  // The sending processor has an interior_parent here,
532  // and we have that element, but that does *NOT* mean
533  // we're already linking to it. Perhaps we initially
534  // received elem from a processor on which the
535  // interior_parent link was remote?
536  libmesh_assert(elem->interior_parent() == ip ||
537  elem->interior_parent() == remote_elem);
538 
539  // If the link was originally remote, update it
540  if (elem->interior_parent() == remote_elem)
541  {
542  elem->set_interior_parent(ip);
543  }
544  }
545  }
546  }
547 
548  // Our neighbor links should be "close to" correct - we may have
549  // to update a remote_elem link, and we can check for possible
550  // inconsistencies along the way.
551  //
552  // For subactive elements, we don't bother keeping neighbor
553  // links in good shape, so there's nothing we need to set or can
554  // safely assert here.
555  if (!elem->subactive())
556  for (auto n : elem->side_index_range())
557  {
558  const dof_id_type neighbor_id =
559  cast_int<dof_id_type>(*in++);
560 
561  // If the sending processor sees a domain boundary here,
562  // we'd better agree.
563  if (neighbor_id == DofObject::invalid_id)
564  {
565  libmesh_assert (!(elem->neighbor_ptr(n)));
566  continue;
567  }
568 
569  // If the sending processor has a remote_elem neighbor here,
570  // then all we know is that we'd better *not* have a domain
571  // boundary.
572  if (neighbor_id == remote_elem->id())
573  {
574  libmesh_assert(elem->neighbor_ptr(n));
575  continue;
576  }
577 
578  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
579 
580  // The sending processor sees a neighbor here, so if we
581  // don't have that neighboring element, then we'd better
582  // have a remote_elem signifying that fact.
583  if (!neigh)
584  {
585  libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
586  continue;
587  }
588 
589  // The sending processor has a neighbor here, and we have
590  // that element, but that does *NOT* mean we're already
591  // linking to it. Perhaps we initially received both elem
592  // and neigh from processors on which their mutual link was
593  // remote?
594  libmesh_assert(elem->neighbor_ptr(n) == neigh ||
595  elem->neighbor_ptr(n) == remote_elem);
596 
597  // If the link was originally remote, we should update it,
598  // and make sure the appropriate parts of its family link
599  // back to us.
600  if (elem->neighbor_ptr(n) == remote_elem)
601  {
602  elem->set_neighbor(n, neigh);
603 
604  elem->make_links_to_me_local(n);
605  }
606  }
607 
608  // Our p level and refinement flags should be "close to" correct
609  // if we're not an active element - we might have a p level
610  // increased or decreased by changes in remote_elem children.
611  //
612  // But if we have remote_elem children, then we shouldn't be
613  // doing a projection on this inactive element on this
614  // processor, so we won't need correct p settings. Couldn't
615  // hurt to update, though.
616 #ifdef LIBMESH_ENABLE_AMR
617  if (elem->processor_id() != mesh->processor_id())
618  {
619  elem->hack_p_level(p_level);
620  elem->set_p_refinement_flag(p_refinement_flag);
621  }
622 #endif // LIBMESH_ENABLE_AMR
623 
624  // FIXME: We should add some debug mode tests to ensure that the
625  // encoded indexing and boundary conditions are consistent.
626  }
627  else
628  {
629  // We don't already have the element, so we need to create it.
630 
631  // Find the parent if necessary
632  Elem * parent = nullptr;
633 #ifdef LIBMESH_ENABLE_AMR
634  // Find a child element's parent
635  if (level > 0)
636  {
637  // Note that we must be very careful to construct the send
638  // connectivity so that parents are encountered before
639  // children. If we get here and can't find the parent that
640  // is a fatal error.
641  parent = mesh->elem_ptr(parent_id);
642  }
643  // Or assert that the sending processor sees no parent
644  else
645  libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
646 #else
647  // No non-level-0 elements without AMR
648  libmesh_assert_equal_to (level, 0);
649 #endif
650 
651  elem = Elem::build(type,parent).release();
652  libmesh_assert (elem);
653 
654 #ifdef LIBMESH_ENABLE_AMR
655  if (level != 0)
656  {
657  // Since this is a newly created element, the parent must
658  // have previously thought of this child as a remote element.
659  libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
660 
661  parent->add_child(elem, which_child_am_i);
662  }
663 
664  // Assign the refinement flags and levels
665  elem->set_p_level(p_level);
666  elem->set_refinement_flag(refinement_flag);
667  elem->set_p_refinement_flag(p_refinement_flag);
668  libmesh_assert_equal_to (elem->level(), level);
669 
670  // If this element should have children, assign remote_elem to
671  // all of them for now, for consistency. Later unpacked
672  // elements may overwrite that.
673  if (has_children)
674  {
675  const unsigned int nc = elem->n_children();
676  for (unsigned int c=0; c != nc; ++c)
677  elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
678  }
679 
680 #endif // LIBMESH_ENABLE_AMR
681 
682  // Assign the IDs
683  elem->subdomain_id() = subdomain_id;
684  elem->processor_id() = processor_id;
685  elem->set_id() = id;
686 #ifdef LIBMESH_ENABLE_UNIQUE_ID
687  elem->set_unique_id() = unique_id;
688 #endif
689 
690  // Assign the connectivity
691  libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
692 
693  for (unsigned int n=0; n != n_nodes; n++)
694  elem->set_node(n) =
695  mesh->node_ptr
696  (cast_int<dof_id_type>(*in++));
697 
698  // Set interior_parent if found
699  {
700  // We may be unpacking an element that was a ghost element on the
701  // sender, in which case the element's interior_parent may not be
702  // known by the packed element. We'll have to set such
703  // interior_parents to remote_elem ourselves and wait for a
704  // later packed element to give us better information.
705  if (interior_parent_id == remote_elem->id())
706  {
707  elem->set_interior_parent
708  (const_cast<RemoteElem *>(remote_elem));
709  }
710  else if (interior_parent_id != DofObject::invalid_id)
711  {
712  // If we don't have the interior parent element, then it's
713  // a remote_elem until we get it.
714  Elem * ip = mesh->query_elem_ptr(interior_parent_id);
715  if (!ip )
716  elem->set_interior_parent
717  (const_cast<RemoteElem *>(remote_elem));
718  else
719  elem->set_interior_parent(ip);
720  }
721  }
722 
723  for (auto n : elem->side_index_range())
724  {
725  const dof_id_type neighbor_id =
726  cast_int<dof_id_type>(*in++);
727 
728  if (neighbor_id == DofObject::invalid_id)
729  continue;
730 
731  // We may be unpacking an element that was a ghost element on the
732  // sender, in which case the element's neighbors may not all be
733  // known by the packed element. We'll have to set such
734  // neighbors to remote_elem ourselves and wait for a later
735  // packed element to give us better information.
736  if (neighbor_id == remote_elem->id())
737  {
738  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
739  continue;
740  }
741 
742  // If we don't have the neighbor element, then it's a
743  // remote_elem until we get it.
744  Elem * neigh = mesh->query_elem_ptr(neighbor_id);
745  if (!neigh)
746  {
747  elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
748  continue;
749  }
750 
751  // If we have the neighbor element, then link to it, and
752  // make sure the appropriate parts of its family link back
753  // to us.
754  elem->set_neighbor(n, neigh);
755 
756  elem->make_links_to_me_local(n);
757  }
758 
759  elem->unpack_indexing(in);
760  }
761 
762  in += elem->packed_indexing_size();
763 
764  // If this is a coarse element,
765  // add any element side or edge boundary condition ids
766  if (level == 0)
767  {
768  for (auto s : elem->side_index_range())
769  {
770  const boundary_id_type num_bcs =
771  cast_int<boundary_id_type>(*in++);
772 
773  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
775  (elem, s, cast_int<boundary_id_type>(*in++));
776  }
777 
778  for (auto e : elem->edge_index_range())
779  {
780  const boundary_id_type num_bcs =
781  cast_int<boundary_id_type>(*in++);
782 
783  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
785  (elem, e, cast_int<boundary_id_type>(*in++));
786  }
787 
788  for (unsigned short sf=0; sf != 2; ++sf)
789  {
790  const boundary_id_type num_bcs =
791  cast_int<boundary_id_type>(*in++);
792 
793  for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
795  (elem, sf, cast_int<boundary_id_type>(*in++));
796  }
797  }
798 
799  // Return the new element
800  return elem;
801 }
802 
803 
804 
805 template <>
806 template <>
807 Elem *
808 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
810 {
811  return unpack(in, static_cast<MeshBase*>(mesh));
812 }
813 
814 
815 
816 template <>
817 template <>
818 Elem *
819 Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
820  ParallelMesh * mesh)
821 {
822  return unpack(in, static_cast<MeshBase*>(mesh));
823 }
824 
825 } // namespace Parallel
826 
827 } // namespace libMesh
void set_p_level(const unsigned int p)
Definition: elem.h:2692
RefinementState refinement_flag() const
Definition: elem.h:2638
unique_id_type & set_unique_id()
Definition: dof_object.h:685
const Elem * parent() const
Definition: elem.h:2479
virtual Node *& set_node(const unsigned int i)
Definition: elem.h:2024
static unsigned int unpackable_indexing_size(std::vector< largest_id_type >::const_iterator begin)
Definition: dof_object.C:461
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
Definition: elem.h:620
const Elem * interior_parent() const
Definition: elem.C:804
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2166
unsigned int n_shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface) const
RefinementState p_refinement_flag() const
Definition: elem.h:2654
The base class for all geometric element types.
Definition: elem.h:100
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)
Definition: elem.C:1461
void set_refinement_flag(const RefinementState rflag)
Definition: elem.h:2646
unique_id_type unique_id() const
Definition: dof_object.h:672
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:2555
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:131
void set_interior_parent(Elem *p)
Definition: elem.C:856
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
Definition: elem.h:589
Base class for Mesh.
Definition: mesh_base.h:77
dof_id_type & set_id()
Definition: dof_object.h:664
std::size_t n_boundary_ids() const
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2157
std::vector< boundary_id_type > boundary_ids(const Node *node) const
const dof_id_type n_nodes
Definition: tecplot_io.C:68
int8_t boundary_id_type
Definition: id_types.h:51
dof_id_type id() const
Definition: dof_object.h:655
virtual unsigned int n_nodes() const =0
static const unique_id_type invalid_unique_id
Definition: dof_object.h:352
static const processor_id_type invalid_processor_id
Definition: dof_object.h:358
static const unsigned int type_to_n_edges_map[INVALID_ELEM]
Definition: elem.h:669
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:245
static const dof_id_type invalid_id
Definition: dof_object.h:347
bool valid_unique_id() const
Definition: dof_object.h:705
virtual unsigned int n_edges() const =0
void set_neighbor(const unsigned int i, Elem *n)
Definition: elem.h:2083
Mesh data structure which is distributed across all processors.
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:2620
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:2050
unsigned int level() const
Definition: elem.h:2521
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:2034
unsigned int packed_indexing_size() const
Definition: dof_object.C:445
virtual unsigned short dim() const =0
void pack_indexing(std::back_insert_iterator< std::vector< largest_id_type >> target) const
Definition: dof_object.C:520
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
void add_shellface(const dof_id_type elem, const unsigned short int shellface, const boundary_id_type id)
bool subactive() const
Definition: elem.h:2408
void unpack_indexing(std::vector< largest_id_type >::const_iterator begin)
Definition: dof_object.C:482
static unsigned int packable_size(const T &object, const Context *context)
static unsigned int packed_size(BufferIter iter)
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Definition: elem.h:2988
void set_p_refinement_flag(const RefinementState pflag)
Definition: elem.h:2662
virtual const Node * node_ptr(const dof_id_type i) const =0
void make_links_to_me_local(unsigned int n)
Definition: elem.C:1062
static void pack(const T &object, OutputIter data_out, const Context *context)
processor_id_type processor_id() const
bool active() const
Definition: elem.h:2390
void hack_p_level(const unsigned int p)
Definition: elem.h:2739
processor_id_type processor_id() const
Definition: dof_object.h:717
static T unpack(BufferIter in, Context *ctx)
virtual ElemType type() const =0
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1914
uint8_t unique_id_type
Definition: id_types.h:79
bool has_children() const
Definition: elem.h:2428
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:2578
uint8_t dof_id_type
Definition: id_types.h:64
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
std::vector< boundary_id_type > edge_boundary_ids(const Elem *const elem, const unsigned short int edge) const
const RemoteElem * remote_elem
Definition: remote_elem.C:57