Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : // C++ includes
21 :
22 : // Local includes
23 : #include "libmesh/boundary_info.h"
24 : #include "libmesh/distributed_mesh.h"
25 : #include "libmesh/elem.h"
26 : #include "libmesh/mesh_base.h"
27 : #include "libmesh/parallel_elem.h"
28 : #include "libmesh/parallel_mesh.h"
29 : #include "libmesh/remote_elem.h"
30 :
31 : // Helper functions in anonymous namespace
32 :
33 : namespace
34 : {
35 : using namespace libMesh;
36 :
37 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
38 : static const unsigned int header_size = 12;
39 : #else
40 : static const unsigned int header_size = 11;
41 : #endif
42 :
43 : #ifndef NDEBUG
44 : // Currently this constant is only used for debugging.
45 : static const largest_id_type elem_magic_header = 987654321;
46 : #endif
47 : }
48 :
49 :
50 : namespace libMesh
51 : {
52 :
53 : namespace Parallel
54 : {
55 :
56 : template <>
57 : unsigned int
58 80106656 : Packing<const Elem *>::packed_size (std::vector<largest_id_type>::const_iterator in)
59 : {
60 : #ifndef NDEBUG
61 108928 : const largest_id_type packed_header = *in++;
62 108928 : libmesh_assert_equal_to (packed_header, elem_magic_header);
63 : #endif
64 :
65 : // int 0: level
66 : const unsigned int level =
67 80106656 : cast_int<unsigned int>(*in);
68 :
69 : // int 4: element type
70 80106656 : const int typeint = cast_int<int>(*(in+4));
71 108928 : libmesh_assert_greater_equal (typeint, 0);
72 108928 : libmesh_assert_less (typeint, INVALID_ELEM);
73 : const ElemType type =
74 108928 : cast_int<ElemType>(typeint);
75 :
76 80106656 : const unsigned int n_nodes =
77 : Elem::type_to_n_nodes_map[type];
78 :
79 80106656 : if (n_nodes == invalid_uint)
80 0 : libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
81 :
82 80106656 : const unsigned int n_sides =
83 : Elem::type_to_n_sides_map[type];
84 :
85 80106656 : const unsigned int n_edges =
86 : Elem::type_to_n_edges_map[type];
87 :
88 80106656 : const unsigned int pre_indexing_size =
89 80106656 : header_size + n_nodes + n_sides*2;
90 :
91 : const unsigned int indexing_size =
92 80106656 : DofObject::unpackable_indexing_size(in+pre_indexing_size);
93 :
94 : // We communicate if we are on the boundary or not
95 108928 : unsigned int total_packed_bc_data = 1;
96 80106656 : largest_id_type on_boundary = *(in + pre_indexing_size + indexing_size);
97 :
98 80106656 : if (on_boundary)
99 : {
100 : // Extracting if the children are allowed on the boundary
101 12299 : total_packed_bc_data++;
102 12563398 : 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 12563398 : if (level == 0 || allow_children_on_boundary)
107 : {
108 66900044 : for (unsigned int s = 0; s != n_sides; ++s)
109 : {
110 : const int n_bcs = cast_int<int>
111 54392778 : (*(in + pre_indexing_size + indexing_size +
112 54392778 : total_packed_bc_data++));
113 56132 : libmesh_assert_greater_equal (n_bcs, 0);
114 54336646 : total_packed_bc_data += n_bcs;
115 : }
116 : }
117 : }
118 80106656 : if (level == 0)
119 : {
120 210820480 : for (unsigned int e = 0; e != n_edges; ++e)
121 : {
122 : const int n_bcs = cast_int<int>
123 183184476 : (*(in + pre_indexing_size + indexing_size +
124 183184476 : total_packed_bc_data++));
125 617308 : libmesh_assert_greater_equal (n_bcs, 0);
126 182567168 : total_packed_bc_data += n_bcs;
127 : }
128 :
129 84759936 : for (unsigned short sf=0; sf != 2; ++sf)
130 : {
131 : const int n_bcs = cast_int<int>
132 56707776 : (*(in + pre_indexing_size + indexing_size +
133 56707776 : total_packed_bc_data++));
134 201152 : libmesh_assert_greater_equal (n_bcs, 0);
135 56506624 : total_packed_bc_data += n_bcs;
136 : }
137 : }
138 :
139 : return
140 : #ifndef NDEBUG
141 : 1 + // Account for magic header
142 : #endif
143 80106656 : pre_indexing_size + indexing_size + total_packed_bc_data;
144 : }
145 :
146 :
147 :
148 : template <>
149 : unsigned int
150 53954 : Packing<const Elem *>::packed_size (std::vector<largest_id_type>::iterator in)
151 : {
152 53954 : return packed_size(std::vector<largest_id_type>::const_iterator(in));
153 : }
154 :
155 :
156 :
157 : template <>
158 : unsigned int
159 24352632 : 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 107946 : unsigned int total_packed_bcs = 1;
164 24352632 : const unsigned short n_sides = elem->n_sides();
165 :
166 107946 : largest_id_type on_boundary = 0;
167 108518989 : for (auto s : elem->side_index_range())
168 89446516 : if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
169 : {
170 11822 : on_boundary = 1;
171 11822 : break;
172 : }
173 :
174 24352632 : 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 11822 : total_packed_bcs++;
180 5334151 : if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
181 : {
182 5334151 : total_packed_bcs += n_sides;
183 27985886 : for (unsigned short s = 0; s != n_sides; ++s)
184 22651735 : total_packed_bcs +=
185 22651735 : mesh->get_boundary_info().n_raw_boundary_ids(elem,s);
186 : }
187 : }
188 :
189 24352632 : if (elem->level() == 0)
190 : {
191 12871950 : const unsigned short n_edges = elem->n_edges();
192 12871950 : total_packed_bcs += n_edges;
193 97355361 : for (unsigned short e = 0; e != n_edges; ++e)
194 84483411 : total_packed_bcs +=
195 84483411 : mesh->get_boundary_info().n_edge_boundary_ids(elem,e);
196 :
197 12871950 : total_packed_bcs += 2; // shellfaces
198 38615850 : for (unsigned short sf=0; sf != 2; ++sf)
199 25743900 : total_packed_bcs +=
200 25743900 : mesh->get_boundary_info().n_shellface_boundary_ids(elem,sf);
201 : }
202 :
203 : return
204 : #ifndef NDEBUG
205 : 1 + // add an int for the magic header when testing
206 : #endif
207 24352632 : header_size + elem->n_nodes() + n_sides*2 +
208 24352632 : elem->packed_indexing_size() + total_packed_bcs;
209 : }
210 :
211 :
212 :
213 : template <>
214 : unsigned int
215 16342799 : Packing<const Elem *>::packable_size (const Elem * const & elem,
216 : const DistributedMesh * mesh)
217 : {
218 16342799 : return packable_size(elem, static_cast<const MeshBase *>(mesh));
219 : }
220 :
221 :
222 :
223 : template <>
224 : unsigned int
225 0 : Packing<const Elem *>::packable_size (const Elem * const & elem,
226 : const ParallelMesh * mesh)
227 : {
228 0 : return packable_size(elem, static_cast<const MeshBase *>(mesh));
229 : }
230 :
231 :
232 :
233 : template <>
234 : void
235 24297898 : 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 53954 : libmesh_assert(elem);
240 :
241 : #ifndef NDEBUG
242 53954 : *data_out++ = elem_magic_header;
243 : #endif
244 :
245 : #ifdef LIBMESH_ENABLE_AMR
246 24297898 : *data_out++ = (static_cast<largest_id_type>(elem->level()));
247 24297898 : *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 24297898 : static_cast<largest_id_type>(elem->refinement_flag());
255 53954 : if (elem->has_children())
256 3163262 : refinement_info +=
257 : static_cast<largest_id_type>(Elem::INVALID_REFINEMENTSTATE) + 1;
258 53954 : *data_out++ = (refinement_info);
259 :
260 24297898 : *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 24297898 : *data_out++ = (static_cast<largest_id_type>(elem->type()));
268 24297898 : *data_out++ = (elem->processor_id());
269 24297898 : *data_out++ = (elem->subdomain_id());
270 24297898 : *data_out++ = (elem->id());
271 :
272 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
273 24297898 : if (elem->valid_unique_id())
274 24297898 : *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 0 : *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 24297898 : if (elem->level() == 0)
283 : {
284 100004 : *data_out++ =(DofObject::invalid_id);
285 100004 : *data_out++ =(DofObject::invalid_id);
286 : }
287 : else
288 : {
289 11480682 : *data_out++ =(elem->parent()->id());
290 11480682 : *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 31400811 : if ((elem->dim() < LIBMESH_DIM) &&
298 7102913 : elem->interior_parent())
299 4588 : *data_out++ =(elem->interior_parent()->id());
300 : else
301 107852 : *data_out++ =(DofObject::invalid_id);
302 :
303 260395961 : for (const Node & node : elem->node_ref_range())
304 236044109 : *data_out++ = node.id();
305 :
306 : // Add the id of and the side for any return link from each neighbor
307 127870758 : for (auto neigh : elem->neighbor_ptr_range())
308 : {
309 103518906 : if (neigh)
310 : {
311 93352788 : *data_out++ = (neigh->id());
312 93352788 : if (neigh == remote_elem)
313 5970 : *data_out++ = (DofObject::invalid_id);
314 : else
315 85534470 : *data_out++ = neigh->which_neighbor_am_i(elem);
316 : }
317 : else
318 : {
319 364268 : *data_out++ = (DofObject::invalid_id);
320 364268 : *data_out++ = (DofObject::invalid_id);
321 : }
322 : }
323 :
324 : // Add any DofObject indices
325 24297898 : 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 24297898 : largest_id_type on_boundary = 0;
331 108259571 : for (auto s : elem->side_index_range())
332 89235320 : if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
333 : {
334 5327601 : on_boundary = 1;
335 5327601 : break;
336 : }
337 :
338 53954 : *data_out++ = on_boundary;
339 :
340 24297898 : if (on_boundary)
341 : {
342 5327601 : *data_out++ = mesh->get_boundary_info().is_children_on_boundary_side();
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 5327601 : if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
346 : {
347 11788 : std::vector<boundary_id_type> bcs;
348 27955960 : for (auto s : elem->side_index_range())
349 : {
350 22622465 : mesh->get_boundary_info().raw_boundary_ids(elem, s, bcs);
351 :
352 45218264 : *data_out++ =(bcs.size());
353 :
354 28531667 : for (const auto & bid : bcs)
355 11803020 : *data_out++ = bid;
356 : }
357 : }
358 : }
359 :
360 : // If this is a coarse element,
361 : // Add any element side boundary condition ids
362 24297898 : if (elem->level() == 0)
363 : {
364 100004 : std::vector<boundary_id_type> bcs;
365 97045519 : for (auto e : elem->edge_index_range())
366 : {
367 84174349 : mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
368 :
369 168042736 : *data_out++ =(bcs.size());
370 :
371 84175005 : for (const auto & bid : bcs)
372 1216 : *data_out++ = bid;
373 : }
374 :
375 38463504 : for (unsigned short sf=0; sf != 2; ++sf)
376 : {
377 25642336 : mesh->get_boundary_info().shellface_boundary_ids(elem, sf, bcs);
378 :
379 51184668 : *data_out++ =(bcs.size());
380 :
381 25710096 : for (const auto & bid : bcs)
382 128864 : *data_out++ = bid;
383 : }
384 : }
385 24297898 : }
386 :
387 :
388 :
389 : template <>
390 : void
391 16334327 : 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 16334327 : pack(elem, data_out, static_cast<const MeshBase*>(mesh));
396 16334327 : }
397 :
398 :
399 :
400 : template <>
401 : void
402 0 : 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 0 : pack(elem, data_out, static_cast<const MeshBase*>(mesh));
407 0 : }
408 :
409 :
410 :
411 : // FIXME - this needs serious work to be 64-bit compatible
412 : template <>
413 : Elem *
414 80052702 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
415 : MeshBase * mesh)
416 : {
417 : #ifndef NDEBUG
418 54974 : const std::vector<largest_id_type>::const_iterator original_in = in;
419 :
420 54974 : const largest_id_type incoming_header = *in++;
421 54974 : libmesh_assert_equal_to (incoming_header, elem_magic_header);
422 : #endif
423 :
424 : // int 0: level
425 : const unsigned int level =
426 80052702 : cast_int<unsigned int>(*in++);
427 :
428 : #ifdef LIBMESH_ENABLE_AMR
429 : // int 1: p level
430 : const unsigned int p_level =
431 80052702 : cast_int<unsigned int>(*in++);
432 :
433 : // int 2: refinement flag and encoded has_children
434 80052702 : const int rflag = cast_int<int>(*in++);
435 : const int invalid_rflag =
436 54974 : cast_int<int>(Elem::INVALID_REFINEMENTSTATE);
437 54974 : libmesh_assert_greater_equal (rflag, 0);
438 :
439 54974 : libmesh_assert_less (rflag, invalid_rflag*2+1);
440 :
441 54974 : const bool has_children = (rflag > invalid_rflag);
442 :
443 80052702 : const Elem::RefinementState refinement_flag = has_children ?
444 15265810 : cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
445 53910 : cast_int<Elem::RefinementState>(rflag);
446 :
447 : // int 3: p refinement flag
448 80052702 : const int pflag = cast_int<int>(*in++);
449 54974 : libmesh_assert_greater_equal (pflag, 0);
450 54974 : libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
451 : const Elem::RefinementState p_refinement_flag =
452 54974 : cast_int<Elem::RefinementState>(pflag);
453 : #else
454 : in += 3;
455 : #endif // LIBMESH_ENABLE_AMR
456 :
457 : // int 4: element type
458 80052702 : const int typeint = cast_int<int>(*in++);
459 54974 : libmesh_assert_greater_equal (typeint, 0);
460 54974 : libmesh_assert_less (typeint, INVALID_ELEM);
461 : const ElemType type =
462 54974 : cast_int<ElemType>(typeint);
463 :
464 80052702 : const unsigned int n_nodes =
465 54974 : Elem::type_to_n_nodes_map[type];
466 :
467 : // int 5: processor id
468 : const processor_id_type processor_id =
469 80052702 : cast_int<processor_id_type>(*in++);
470 54974 : 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 80052702 : cast_int<subdomain_id_type>(*in++);
476 :
477 : // int 7: dof object id
478 : const dof_id_type id =
479 80052702 : cast_int<dof_id_type>(*in++);
480 54974 : 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 80052702 : 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 54974 : (level == 0)
496 80052702 : ? static_cast<dof_id_type>(*in++)
497 51849392 : : cast_int<dof_id_type>(*in++);
498 54974 : libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
499 54974 : 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 54974 : (level == 0)
506 80052702 : ? static_cast<unsigned int>(*in++)
507 51849392 : : 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 80052702 : 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 54974 : libmesh_assert_equal_to (in - original_in, header_size + 1);
518 :
519 80052702 : 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 80052702 : if (elem)
525 : {
526 9690 : libmesh_assert_equal_to (elem->level(), level);
527 9690 : libmesh_assert_equal_to (elem->id(), id);
528 : //#ifdef LIBMESH_ENABLE_UNIQUE_ID
529 : // No check for unique id sanity
530 : //#endif
531 9690 : libmesh_assert_equal_to (elem->processor_id(), processor_id);
532 9690 : libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
533 9690 : libmesh_assert_equal_to (elem->type(), type);
534 9690 : libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
535 :
536 : #ifndef NDEBUG
537 : // All our nodes should be correct
538 105990 : for (unsigned int i=0; i != n_nodes; ++i)
539 96300 : 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 9690 : libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
547 9690 : libmesh_assert_equal_to (elem->has_children(), has_children);
548 :
549 : #ifdef DEBUG
550 9690 : if (elem->active())
551 : {
552 8712 : libmesh_assert_equal_to (elem->p_level(), p_level);
553 8712 : libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);
554 : }
555 : #endif
556 :
557 9690 : libmesh_assert (!level || elem->parent() != nullptr);
558 9690 : libmesh_assert (!level || elem->parent()->id() == parent_id);
559 9690 : 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 49938784 : if (interior_parent_id == DofObject::invalid_id)
568 : {
569 49921087 : if (elem->dim() < LIBMESH_DIM)
570 2623 : 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 17697 : else if (interior_parent_id == remote_elem->id())
577 : {
578 0 : libmesh_assert(elem->interior_parent());
579 : }
580 : else
581 : {
582 : Elem * ip =
583 17697 : 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 17697 : if (!ip)
589 0 : 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 28 : libmesh_assert(elem->interior_parent() == ip ||
598 : elem->interior_parent() == remote_elem);
599 :
600 : // If the link was originally remote, update it
601 17138 : if (elem->interior_parent() == remote_elem)
602 : {
603 0 : elem->set_interior_parent(ip);
604 : }
605 : }
606 : }
607 : }
608 :
609 : // Our neighbor links should be "close to" correct - we may have
610 : // to update a remote_elem link, and we can check for possible
611 : // inconsistencies along the way.
612 : //
613 : // Even for subactive elements, we'll try to keep neighbor links
614 : // in good shape now, if only so any future find_neighbors() is
615 : // idempotent.
616 260761899 : for (auto n : elem->side_index_range())
617 : {
618 : const dof_id_type neighbor_id =
619 210823115 : cast_int<dof_id_type>(*in++);
620 :
621 : const dof_id_type neighbor_side =
622 210823115 : cast_int<dof_id_type>(*in++);
623 :
624 : // If the sending processor sees a domain boundary here,
625 : // we'd better agree ... unless all we see is a remote_elem?
626 : // In that case maybe we just couldn't keep up with a user's
627 : // delete_elem. Let's trust them.
628 210823115 : if (neighbor_id == DofObject::invalid_id)
629 : {
630 19993737 : const Elem * my_neigh = elem->neighbor_ptr(n);
631 19993737 : if (my_neigh == remote_elem)
632 1 : elem->set_neighbor(n, nullptr);
633 : else
634 4883 : libmesh_assert (!my_neigh);
635 19993737 : continue;
636 19983969 : }
637 :
638 : // If the sending processor has a remote_elem neighbor here,
639 : // then all we know is that we'd better *not* have a domain
640 : // boundary ... except that maybe it's the *sending*
641 : // processor who missed a delete_elem we saw.
642 190829378 : if (neighbor_id == remote_elem->id())
643 : {
644 : // At this level of the code we can't even assert in
645 : // cases where the neighbor should know what they're
646 : // talking about, so skip it.
647 :
648 : // libmesh_assert(elem->neighbor_ptr(n));
649 18709670 : continue;
650 : }
651 :
652 172116663 : Elem * neigh = mesh->query_elem_ptr(neighbor_id);
653 :
654 : // The sending processor sees a neighbor here, so if we
655 : // don't have that neighboring element, then we'd better
656 : // have a remote_elem signifying that fact.
657 172116663 : if (!neigh)
658 : {
659 2442 : libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
660 5784329 : continue;
661 : }
662 :
663 : // The sending processor has a neighbor here, and we have
664 : // that element, but that does *NOT* mean we're already
665 : // linking to it. Perhaps we initially received both elem
666 : // and neigh from processors on which their mutual link was
667 : // remote?
668 37895 : libmesh_assert(elem->neighbor_ptr(n) == neigh ||
669 : elem->neighbor_ptr(n) == remote_elem);
670 :
671 : // If the link was originally remote, we should update it,
672 : // and make sure the appropriate parts of its family link
673 : // back to us.
674 166367787 : if (elem->neighbor_ptr(n) == remote_elem)
675 : {
676 0 : elem->set_neighbor(n, neigh);
677 : }
678 : else
679 37895 : libmesh_assert(elem->subactive() ||
680 : neigh->level() < elem->level() ||
681 : neigh->neighbor_ptr(neighbor_side) == elem);
682 :
683 166329892 : if (neighbor_side != libMesh::invalid_uint)
684 166323389 : elem->make_links_to_me_local(n, neighbor_side);
685 : }
686 :
687 : // Our p level and refinement flags should be "close to" correct
688 : // if we're not an active element - we might have a p level
689 : // increased or decreased by changes in remote_elem children.
690 : //
691 : // But if we have remote_elem children, then we shouldn't be
692 : // doing a projection on this inactive element on this
693 : // processor, so we won't need correct p settings. Couldn't
694 : // hurt to update, though.
695 : #ifdef LIBMESH_ENABLE_AMR
696 49948474 : if (elem->processor_id() != mesh->processor_id())
697 : {
698 : // Do this simultaneously; otherwise we can get a false
699 : // positive when a hack_p_level or set_p_refineemnt_flag
700 : // assertion sees inconsistency between an old flag and new
701 : // value or vice-versa
702 4106 : elem->hack_p_level_and_refinement_flag(p_level, p_refinement_flag);
703 : }
704 : #endif // LIBMESH_ENABLE_AMR
705 :
706 : // FIXME: We should add some debug mode tests to ensure that the
707 : // encoded indexing and boundary conditions are consistent.
708 : }
709 : else
710 : {
711 : // We don't already have the element, so we need to create it.
712 :
713 : // Find the parent if necessary
714 45284 : Elem * parent = nullptr;
715 : #ifdef LIBMESH_ENABLE_AMR
716 : // Find a child element's parent
717 30113918 : if (level > 0)
718 : {
719 : // Note that we must be very careful to construct the send
720 : // connectivity so that parents are encountered before
721 : // children. If we get here and can't find the parent that
722 : // is a fatal error.
723 25280490 : parent = mesh->elem_ptr(parent_id);
724 : }
725 : // Or assert that the sending processor sees no parent
726 : else
727 44932 : libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
728 : #else
729 : // No non-level-0 elements without AMR
730 : libmesh_assert_equal_to (level, 0);
731 : #endif
732 :
733 30113918 : elem = Elem::build(type,parent).release();
734 45284 : libmesh_assert (elem);
735 :
736 : #ifdef LIBMESH_ENABLE_AMR
737 30113918 : if (level != 0)
738 : {
739 : // Since this is a newly created element, the parent must
740 : // have previously thought of this child as a remote element.
741 352 : libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
742 :
743 25280490 : parent->add_child(elem, which_child_am_i);
744 : }
745 :
746 : // Assign the refinement flags and levels
747 30113918 : elem->set_p_level(p_level);
748 45284 : elem->set_refinement_flag(refinement_flag);
749 45284 : elem->set_p_refinement_flag(p_refinement_flag);
750 45284 : libmesh_assert_equal_to (elem->level(), level);
751 :
752 : // If this element should have children, assign remote_elem to
753 : // all of them for now, for consistency. Later unpacked
754 : // elements may overwrite that.
755 30113918 : if (has_children)
756 : {
757 6020658 : const unsigned int nc = elem->n_children();
758 30371868 : for (unsigned int c=0; c != nc; ++c)
759 24351210 : elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
760 : }
761 :
762 : #endif // LIBMESH_ENABLE_AMR
763 :
764 : // Assign the IDs
765 30113918 : elem->subdomain_id() = subdomain_id;
766 30113918 : elem->processor_id() = processor_id;
767 30113918 : elem->set_id() = id;
768 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
769 45284 : elem->set_unique_id(unique_id);
770 : #endif
771 :
772 : // Assign the connectivity
773 45284 : libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
774 :
775 170683260 : for (unsigned int n=0; n != n_nodes; n++)
776 140808387 : elem->set_node (n, mesh->node_ptr
777 140808387 : (cast_int<dof_id_type>(*in++)));
778 :
779 : // Set interior_parent if found
780 : {
781 : // We may be unpacking an element that was a ghost element on the
782 : // sender, in which case the element's interior_parent may not be
783 : // known by the packed element. We'll have to set such
784 : // interior_parents to remote_elem ourselves and wait for a
785 : // later packed element to give us better information.
786 30113918 : if (interior_parent_id == remote_elem->id())
787 : {
788 : elem->set_interior_parent
789 0 : (const_cast<RemoteElem *>(remote_elem));
790 : }
791 30113918 : else if (interior_parent_id != DofObject::invalid_id)
792 : {
793 : // If we don't have the interior parent element, then it's
794 : // a remote_elem until we get it.
795 : Elem * ip =
796 11209 : mesh->interior_mesh().query_elem_ptr(interior_parent_id);
797 11209 : if (!ip )
798 : elem->set_interior_parent
799 1065 : (const_cast<RemoteElem *>(remote_elem));
800 : else
801 10144 : elem->set_interior_parent(ip);
802 : }
803 : }
804 :
805 151245848 : for (auto n : elem->side_index_range())
806 : {
807 : const dof_id_type neighbor_id =
808 121131930 : cast_int<dof_id_type>(*in++);
809 :
810 : const dof_id_type neighbor_side =
811 121131930 : cast_int<dof_id_type>(*in++);
812 :
813 121131930 : if (neighbor_id == DofObject::invalid_id)
814 14130150 : continue;
815 :
816 : // We may be unpacking an element that was a ghost element on the
817 : // sender, in which case the element's neighbors may not all be
818 : // known by the packed element. We'll have to set such
819 : // neighbors to remote_elem ourselves and wait for a later
820 : // packed element to give us better information.
821 213643464 : if (neighbor_id == remote_elem->id())
822 : {
823 3898200 : elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
824 3898200 : continue;
825 : }
826 :
827 : // If we don't have the neighbor element, then it's a
828 : // remote_elem until we get it.
829 102925046 : Elem * neigh = mesh->query_elem_ptr(neighbor_id);
830 102925046 : if (!neigh)
831 : {
832 48648759 : elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
833 48648759 : continue;
834 : }
835 :
836 : // If we have the neighbor element, then link to it, and
837 : // make sure any appropriate parts of its family link back
838 : // to us.
839 54276287 : elem->set_neighbor(n, neigh);
840 :
841 54276287 : if (neighbor_side != libMesh::invalid_uint)
842 54275135 : elem->make_links_to_me_local(n, neighbor_side);
843 : }
844 :
845 30113918 : elem->unpack_indexing(in);
846 :
847 30113918 : mesh->add_elem(elem);
848 : }
849 :
850 80052702 : in += elem->packed_indexing_size();
851 :
852 : // We check if this is cell holds a boundary ID or not
853 80052702 : auto on_boundary = *in++;
854 80052702 : if (on_boundary)
855 : {
856 : // Only treat the sides with caution. This is because we might hold boundary IDs
857 : // on the sides of the children. This is not supported for edges and shell faces, thus
858 : // they are treated assuming that only top parents can hold the IDs.
859 12557504 : auto children_on_boundary = *in++;
860 12557504 : if (elem->level() == 0 || children_on_boundary)
861 : {
862 66867484 : for (auto s : elem->side_index_range())
863 : {
864 : const boundary_id_type num_bcs =
865 54309980 : cast_int<boundary_id_type>(*in++);
866 :
867 69440072 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
868 8778 : mesh->get_boundary_info().add_side
869 15138870 : (elem, s, cast_int<boundary_id_type>(*in++));
870 : }
871 : }
872 : }
873 :
874 : // If this is a coarse element,
875 : // add any element side or edge boundary condition ids
876 80052702 : if (level == 0)
877 : {
878 210464516 : for (auto e : elem->edge_index_range())
879 : {
880 : const boundary_id_type num_bcs =
881 182261206 : cast_int<boundary_id_type>(*in++);
882 :
883 182264390 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
884 48 : mesh->get_boundary_info().add_edge
885 3232 : (elem, e, cast_int<boundary_id_type>(*in++));
886 : }
887 :
888 84609930 : for (unsigned short sf=0; sf != 2; ++sf)
889 : {
890 : const boundary_id_type num_bcs =
891 56406620 : cast_int<boundary_id_type>(*in++);
892 :
893 56667528 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
894 3328 : mesh->get_boundary_info().add_shellface
895 264236 : (elem, sf, cast_int<boundary_id_type>(*in++));
896 : }
897 : }
898 :
899 : // Return the new element
900 80052702 : return elem;
901 : }
902 :
903 :
904 :
905 : template <>
906 : Elem *
907 16334327 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
908 : DistributedMesh * mesh)
909 : {
910 16334327 : return unpack(in, static_cast<MeshBase*>(mesh));
911 : }
912 :
913 :
914 :
915 : template <>
916 : Elem *
917 0 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
918 : ParallelMesh * mesh)
919 : {
920 0 : return unpack(in, static_cast<MeshBase*>(mesh));
921 : }
922 :
923 : } // namespace Parallel
924 :
925 : } // namespace libMesh
|