Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : // C++ includes
21 :
22 : // Local includes
23 : #include "libmesh/boundary_info.h"
24 : #include "libmesh/distributed_mesh.h"
25 : #include "libmesh/elem.h"
26 : #include "libmesh/mesh_base.h"
27 : #include "libmesh/parallel_elem.h"
28 : #include "libmesh/parallel_mesh.h"
29 : #include "libmesh/remote_elem.h"
30 :
31 : // Helper functions in anonymous namespace
32 :
33 : namespace
34 : {
35 : using namespace libMesh;
36 :
37 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
38 : static const unsigned int header_size = 12;
39 : #else
40 : static const unsigned int header_size = 11;
41 : #endif
42 :
43 : #ifndef NDEBUG
44 : // Currently this constant is only used for debugging.
45 : static const largest_id_type elem_magic_header = 987654321;
46 : #endif
47 : }
48 :
49 :
50 : namespace libMesh
51 : {
52 :
53 : namespace Parallel
54 : {
55 :
56 : template <>
57 : unsigned int
58 74576193 : Packing<const Elem *>::packed_size (std::vector<largest_id_type>::const_iterator in)
59 : {
60 : #ifndef NDEBUG
61 102998 : const largest_id_type packed_header = *in++;
62 102998 : libmesh_assert_equal_to (packed_header, elem_magic_header);
63 : #endif
64 :
65 : // int 0: level
66 : const unsigned int level =
67 74576193 : cast_int<unsigned int>(*in);
68 :
69 : // int 4: element type
70 74576193 : const int typeint = cast_int<int>(*(in+4));
71 102998 : libmesh_assert_greater_equal (typeint, 0);
72 102998 : libmesh_assert_less (typeint, INVALID_ELEM);
73 : const ElemType type =
74 102998 : cast_int<ElemType>(typeint);
75 :
76 74576193 : const unsigned int n_nodes =
77 : Elem::type_to_n_nodes_map[type];
78 :
79 74576193 : if (n_nodes == invalid_uint)
80 0 : libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
81 :
82 74576193 : const unsigned int n_sides =
83 : Elem::type_to_n_sides_map[type];
84 :
85 74576193 : const unsigned int n_edges =
86 : Elem::type_to_n_edges_map[type];
87 :
88 74576193 : const unsigned int pre_indexing_size =
89 74576193 : header_size + n_nodes + n_sides*2;
90 :
91 : const unsigned int indexing_size =
92 74576193 : DofObject::unpackable_indexing_size(in+pre_indexing_size);
93 :
94 : // We communicate if we are on the boundary or not
95 102998 : unsigned int total_packed_bc_data = 1;
96 74576193 : largest_id_type on_boundary = *(in + pre_indexing_size + indexing_size);
97 :
98 74576193 : if (on_boundary)
99 : {
100 : // Extracting if the children are allowed on the boundary
101 10031 : total_packed_bc_data++;
102 10600306 : 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 10600306 : if (level == 0 || allow_children_on_boundary)
107 : {
108 56111140 : for (unsigned int s = 0; s != n_sides; ++s)
109 : {
110 : const int n_bcs = cast_int<int>
111 45556998 : (*(in + pre_indexing_size + indexing_size +
112 45556998 : total_packed_bc_data++));
113 46164 : libmesh_assert_greater_equal (n_bcs, 0);
114 45510834 : total_packed_bc_data += n_bcs;
115 : }
116 : }
117 : }
118 74576193 : if (level == 0)
119 : {
120 171425559 : for (unsigned int e = 0; e != n_edges; ++e)
121 : {
122 : const int n_bcs = cast_int<int>
123 148649250 : (*(in + pre_indexing_size + indexing_size +
124 148649250 : total_packed_bc_data++));
125 590684 : libmesh_assert_greater_equal (n_bcs, 0);
126 148058566 : total_packed_bc_data += n_bcs;
127 : }
128 :
129 70100979 : for (unsigned short sf=0; sf != 2; ++sf)
130 : {
131 : const int n_bcs = cast_int<int>
132 46927118 : (*(in + pre_indexing_size + indexing_size +
133 46927118 : total_packed_bc_data++));
134 193132 : libmesh_assert_greater_equal (n_bcs, 0);
135 46733986 : total_packed_bc_data += n_bcs;
136 : }
137 : }
138 :
139 : return
140 : #ifndef NDEBUG
141 : 1 + // Account for magic header
142 : #endif
143 74576193 : pre_indexing_size + indexing_size + total_packed_bc_data;
144 : }
145 :
146 :
147 :
148 : template <>
149 : unsigned int
150 50991 : Packing<const Elem *>::packed_size (std::vector<largest_id_type>::iterator in)
151 : {
152 50991 : return packed_size(std::vector<largest_id_type>::const_iterator(in));
153 : }
154 :
155 :
156 :
157 : template <>
158 : unsigned int
159 22469059 : 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 102020 : unsigned int total_packed_bcs = 1;
164 22469059 : const unsigned short n_sides = elem->n_sides();
165 :
166 102020 : largest_id_type on_boundary = 0;
167 98769455 : for (auto s : elem->side_index_range())
168 81192860 : if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
169 : {
170 9558 : on_boundary = 1;
171 9558 : break;
172 : }
173 :
174 22469059 : 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 9558 : total_packed_bcs++;
180 4943493 : if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
181 : {
182 4943493 : total_packed_bcs += n_sides;
183 25844951 : for (unsigned short s = 0; s != n_sides; ++s)
184 20901458 : total_packed_bcs +=
185 20901458 : mesh->get_boundary_info().n_raw_boundary_ids(elem,s);
186 : }
187 : }
188 :
189 22469059 : if (elem->level() == 0)
190 : {
191 11429056 : const unsigned short n_edges = elem->n_edges();
192 11429056 : total_packed_bcs += n_edges;
193 85178256 : for (unsigned short e = 0; e != n_edges; ++e)
194 73749200 : total_packed_bcs +=
195 73749200 : mesh->get_boundary_info().n_edge_boundary_ids(elem,e);
196 :
197 11429056 : total_packed_bcs += 2; // shellfaces
198 34287168 : for (unsigned short sf=0; sf != 2; ++sf)
199 22858112 : total_packed_bcs +=
200 22858112 : 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 22469059 : header_size + elem->n_nodes() + n_sides*2 +
208 22469059 : elem->packed_indexing_size() + total_packed_bcs;
209 : }
210 :
211 :
212 :
213 : template <>
214 : unsigned int
215 14875147 : Packing<const Elem *>::packable_size (const Elem * const & elem,
216 : const DistributedMesh * mesh)
217 : {
218 14875147 : 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 22417288 : 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 50991 : libmesh_assert(elem);
240 :
241 : #ifndef NDEBUG
242 50991 : *data_out++ = elem_magic_header;
243 : #endif
244 :
245 : #ifdef LIBMESH_ENABLE_AMR
246 22417288 : *data_out++ = (static_cast<largest_id_type>(elem->level()));
247 22417288 : *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 22417288 : static_cast<largest_id_type>(elem->refinement_flag());
255 50991 : if (elem->has_children())
256 3040622 : refinement_info +=
257 : static_cast<largest_id_type>(Elem::INVALID_REFINEMENTSTATE) + 1;
258 50991 : *data_out++ = (refinement_info);
259 :
260 22417288 : *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 22417288 : *data_out++ = (static_cast<largest_id_type>(elem->type()));
268 22417288 : *data_out++ = (elem->processor_id());
269 22417288 : *data_out++ = (elem->subdomain_id());
270 22417288 : *data_out++ = (elem->id());
271 :
272 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
273 22417288 : if (elem->valid_unique_id())
274 22417288 : *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 22417288 : if (elem->level() == 0)
283 : {
284 95998 : *data_out++ =(DofObject::invalid_id);
285 95998 : *data_out++ =(DofObject::invalid_id);
286 : }
287 : else
288 : {
289 11040003 : *data_out++ =(elem->parent()->id());
290 11040003 : *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 29341876 : if ((elem->dim() < LIBMESH_DIM) &&
298 6924588 : elem->interior_parent())
299 4588 : *data_out++ =(elem->interior_parent()->id());
300 : else
301 101926 : *data_out++ =(DofObject::invalid_id);
302 :
303 236106130 : for (const Node & node : elem->node_ref_range())
304 213637851 : *data_out++ = node.id();
305 :
306 : // Add the id of and the side for any return link from each neighbor
307 116877473 : for (auto neigh : elem->neighbor_ptr_range())
308 : {
309 94409194 : if (neigh)
310 : {
311 84941784 : *data_out++ = (neigh->id());
312 84941784 : if (neigh == remote_elem)
313 4938 : *data_out++ = (DofObject::invalid_id);
314 : else
315 78376044 : *data_out++ = neigh->which_neighbor_am_i(elem);
316 : }
317 : else
318 : {
319 347056 : *data_out++ = (DofObject::invalid_id);
320 347056 : *data_out++ = (DofObject::invalid_id);
321 : }
322 : }
323 :
324 : // Add any DofObject indices
325 22417288 : 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 22417288 : largest_id_type on_boundary = 0;
331 98523134 : for (auto s : elem->side_index_range())
332 80992930 : if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
333 : {
334 4938075 : on_boundary = 1;
335 4938075 : break;
336 : }
337 :
338 50991 : *data_out++ = on_boundary;
339 :
340 22417288 : if (on_boundary)
341 : {
342 4938075 : *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 4938075 : if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
346 : {
347 9524 : std::vector<boundary_id_type> bcs;
348 25820001 : for (auto s : elem->side_index_range())
349 : {
350 20877164 : mesh->get_boundary_info().raw_boundary_ids(elem, s, bcs);
351 :
352 41732638 : *data_out++ =(bcs.size());
353 :
354 26335041 : for (const auto & bid : bcs)
355 10903322 : *data_out++ = bid;
356 : }
357 : }
358 : }
359 :
360 : // If this is a coarse element,
361 : // Add any element side boundary condition ids
362 22417288 : if (elem->level() == 0)
363 : {
364 95998 : std::vector<boundary_id_type> bcs;
365 84881718 : for (auto e : elem->edge_index_range())
366 : {
367 73453442 : mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
368 :
369 146614226 : *data_out++ =(bcs.size());
370 :
371 73454098 : for (const auto & bid : bcs)
372 1216 : *data_out++ = bid;
373 : }
374 :
375 34140831 : for (unsigned short sf=0; sf != 2; ++sf)
376 : {
377 22760554 : mesh->get_boundary_info().shellface_boundary_ids(elem, sf, bcs);
378 :
379 45425110 : *data_out++ =(bcs.size());
380 :
381 22828314 : for (const auto & bid : bcs)
382 128864 : *data_out++ = bid;
383 : }
384 : }
385 22417288 : }
386 :
387 :
388 :
389 : template <>
390 : void
391 14867675 : 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 14867675 : pack(elem, data_out, static_cast<const MeshBase*>(mesh));
396 14867675 : }
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 74525202 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
415 : MeshBase * mesh)
416 : {
417 : #ifndef NDEBUG
418 52007 : const std::vector<largest_id_type>::const_iterator original_in = in;
419 :
420 52007 : const largest_id_type incoming_header = *in++;
421 52007 : libmesh_assert_equal_to (incoming_header, elem_magic_header);
422 : #endif
423 :
424 : // int 0: level
425 : const unsigned int level =
426 74525202 : cast_int<unsigned int>(*in++);
427 :
428 : #ifdef LIBMESH_ENABLE_AMR
429 : // int 1: p level
430 : const unsigned int p_level =
431 74525202 : cast_int<unsigned int>(*in++);
432 :
433 : // int 2: refinement flag and encoded has_children
434 74525202 : const int rflag = cast_int<int>(*in++);
435 : const int invalid_rflag =
436 52007 : cast_int<int>(Elem::INVALID_REFINEMENTSTATE);
437 52007 : libmesh_assert_greater_equal (rflag, 0);
438 :
439 52007 : libmesh_assert_less (rflag, invalid_rflag*2+1);
440 :
441 52007 : const bool has_children = (rflag > invalid_rflag);
442 :
443 74525202 : const Elem::RefinementState refinement_flag = has_children ?
444 15098057 : cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
445 51195 : cast_int<Elem::RefinementState>(rflag);
446 :
447 : // int 3: p refinement flag
448 74525202 : const int pflag = cast_int<int>(*in++);
449 52007 : libmesh_assert_greater_equal (pflag, 0);
450 52007 : libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
451 : const Elem::RefinementState p_refinement_flag =
452 52007 : cast_int<Elem::RefinementState>(pflag);
453 : #else
454 : in += 3;
455 : #endif // LIBMESH_ENABLE_AMR
456 :
457 : // int 4: element type
458 74525202 : const int typeint = cast_int<int>(*in++);
459 52007 : libmesh_assert_greater_equal (typeint, 0);
460 52007 : libmesh_assert_less (typeint, INVALID_ELEM);
461 : const ElemType type =
462 52007 : cast_int<ElemType>(typeint);
463 :
464 74525202 : const unsigned int n_nodes =
465 52007 : Elem::type_to_n_nodes_map[type];
466 :
467 : // int 5: processor id
468 : const processor_id_type processor_id =
469 74525202 : cast_int<processor_id_type>(*in++);
470 52007 : 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 74525202 : cast_int<subdomain_id_type>(*in++);
476 :
477 : // int 7: dof object id
478 : const dof_id_type id =
479 74525202 : cast_int<dof_id_type>(*in++);
480 52007 : 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 74525202 : 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 52007 : (level == 0)
496 74525202 : ? static_cast<dof_id_type>(*in++)
497 51206208 : : cast_int<dof_id_type>(*in++);
498 52007 : libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
499 52007 : 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 52007 : (level == 0)
506 74525202 : ? static_cast<unsigned int>(*in++)
507 51206208 : : 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 74525202 : 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 52007 : libmesh_assert_equal_to (in - original_in, header_size + 1);
518 :
519 74525202 : 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 74525202 : if (elem)
525 : {
526 8682 : libmesh_assert_equal_to (elem->level(), level);
527 8682 : libmesh_assert_equal_to (elem->id(), id);
528 : //#ifdef LIBMESH_ENABLE_UNIQUE_ID
529 : // No check for unique id sanity
530 : //#endif
531 8682 : libmesh_assert_equal_to (elem->processor_id(), processor_id);
532 8682 : libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
533 8682 : libmesh_assert_equal_to (elem->type(), type);
534 8682 : libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
535 :
536 : #ifndef NDEBUG
537 : // All our nodes should be correct
538 97640 : for (unsigned int i=0; i != n_nodes; ++i)
539 88958 : 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 8682 : libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
547 8682 : libmesh_assert_equal_to (elem->has_children(), has_children);
548 :
549 : #ifdef DEBUG
550 8682 : if (elem->active())
551 : {
552 7956 : libmesh_assert_equal_to (elem->p_level(), p_level);
553 7956 : libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);
554 : }
555 : #endif
556 :
557 8682 : libmesh_assert (!level || elem->parent() != nullptr);
558 8682 : libmesh_assert (!level || elem->parent()->id() == parent_id);
559 8682 : 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 44764312 : if (interior_parent_id == DofObject::invalid_id)
568 : {
569 44746615 : if (elem->dim() < LIBMESH_DIM)
570 2435 : 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 : // For subactive elements, we don't bother keeping neighbor
614 : // links in good shape, so there's nothing we need to set or can
615 : // safely assert here.
616 44764312 : if (!elem->subactive())
617 231740880 : for (auto n : elem->side_index_range())
618 : {
619 : const dof_id_type neighbor_id =
620 186986941 : cast_int<dof_id_type>(*in++);
621 :
622 : const dof_id_type neighbor_side =
623 186986941 : cast_int<dof_id_type>(*in++);
624 :
625 : // If the sending processor sees a domain boundary here,
626 : // we'd better agree ... unless all we see is a
627 : // remote_elem? In that case maybe we just couldn't keep
628 : // up with a user's delete_elem. Let's trust them.
629 186986941 : if (neighbor_id == DofObject::invalid_id)
630 : {
631 17400699 : const Elem * my_neigh = elem->neighbor_ptr(n);
632 17400699 : if (my_neigh == remote_elem)
633 1 : elem->set_neighbor(n, nullptr);
634 : else
635 4599 : libmesh_assert (!my_neigh);
636 17400699 : continue;
637 17391499 : }
638 :
639 : // If the sending processor has a remote_elem neighbor here,
640 : // then all we know is that we'd better *not* have a domain
641 : // boundary ... except that maybe it's the *sending*
642 : // processor who missed a delete_elem we saw.
643 169586242 : if (neighbor_id == remote_elem->id())
644 : {
645 : // At this level of the code we can't even assert in
646 : // cases where the neighbor should know what they're
647 : // talking about, so skip it.
648 :
649 : // libmesh_assert(elem->neighbor_ptr(n));
650 15720365 : continue;
651 : }
652 :
653 153863348 : Elem * neigh = mesh->query_elem_ptr(neighbor_id);
654 :
655 : // The sending processor sees a neighbor here, so if we
656 : // don't have that neighboring element, then we'd better
657 : // have a remote_elem signifying that fact.
658 153863348 : if (!neigh)
659 : {
660 1926 : libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
661 5001009 : continue;
662 : }
663 :
664 : // The sending processor has a neighbor here, and we have
665 : // that element, but that does *NOT* mean we're already
666 : // linking to it. Perhaps we initially received both elem
667 : // and neigh from processors on which their mutual link was
668 : // remote?
669 33579 : libmesh_assert(elem->neighbor_ptr(n) == neigh ||
670 : elem->neighbor_ptr(n) == remote_elem);
671 :
672 : // If the link was originally remote, we should update it,
673 : // and make sure the appropriate parts of its family link
674 : // back to us.
675 148893992 : if (elem->neighbor_ptr(n) == remote_elem)
676 : {
677 0 : elem->set_neighbor(n, neigh);
678 :
679 178797 : elem->make_links_to_me_local(n, neighbor_side);
680 : }
681 : else
682 33579 : libmesh_assert(neigh->level() < elem->level() ||
683 : neigh->neighbor_ptr(neighbor_side) == elem);
684 : }
685 : else
686 : // We skip these to go to the boundary information if the element is
687 : // actually subactive
688 10373 : in += 2*elem->n_sides();
689 :
690 : // Our p level and refinement flags should be "close to" correct
691 : // if we're not an active element - we might have a p level
692 : // increased or decreased by changes in remote_elem children.
693 : //
694 : // But if we have remote_elem children, then we shouldn't be
695 : // doing a projection on this inactive element on this
696 : // processor, so we won't need correct p settings. Couldn't
697 : // hurt to update, though.
698 : #ifdef LIBMESH_ENABLE_AMR
699 44772994 : if (elem->processor_id() != mesh->processor_id())
700 : {
701 : // Do this simultaneously; otherwise we can get a false
702 : // positive when a hack_p_level or set_p_refineemnt_flag
703 : // assertion sees inconsistency between an old flag and new
704 : // value or vice-versa
705 3602 : elem->hack_p_level_and_refinement_flag(p_level, p_refinement_flag);
706 : }
707 : #endif // LIBMESH_ENABLE_AMR
708 :
709 : // FIXME: We should add some debug mode tests to ensure that the
710 : // encoded indexing and boundary conditions are consistent.
711 : }
712 : else
713 : {
714 : // We don't already have the element, so we need to create it.
715 :
716 : // Find the parent if necessary
717 43325 : Elem * parent = nullptr;
718 : #ifdef LIBMESH_ENABLE_AMR
719 : // Find a child element's parent
720 29760890 : if (level > 0)
721 : {
722 : // Note that we must be very careful to construct the send
723 : // connectivity so that parents are encountered before
724 : // children. If we get here and can't find the parent that
725 : // is a fatal error.
726 25248907 : parent = mesh->elem_ptr(parent_id);
727 : }
728 : // Or assert that the sending processor sees no parent
729 : else
730 42973 : libmesh_assert_equal_to (parent_id, DofObject::invalid_id);
731 : #else
732 : // No non-level-0 elements without AMR
733 : libmesh_assert_equal_to (level, 0);
734 : #endif
735 :
736 29760890 : elem = Elem::build(type,parent).release();
737 43325 : libmesh_assert (elem);
738 :
739 : #ifdef LIBMESH_ENABLE_AMR
740 29760890 : if (level != 0)
741 : {
742 : // Since this is a newly created element, the parent must
743 : // have previously thought of this child as a remote element.
744 352 : libmesh_assert_equal_to (parent->child_ptr(which_child_am_i), remote_elem);
745 :
746 25248907 : parent->add_child(elem, which_child_am_i);
747 : }
748 :
749 : // Assign the refinement flags and levels
750 29760890 : elem->set_p_level(p_level);
751 43325 : elem->set_refinement_flag(refinement_flag);
752 43325 : elem->set_p_refinement_flag(p_refinement_flag);
753 43325 : libmesh_assert_equal_to (elem->level(), level);
754 :
755 : // If this element should have children, assign remote_elem to
756 : // all of them for now, for consistency. Later unpacked
757 : // elements may overwrite that.
758 29760890 : if (has_children)
759 : {
760 6013553 : const unsigned int nc = elem->n_children();
761 30332339 : for (unsigned int c=0; c != nc; ++c)
762 24318786 : elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
763 : }
764 :
765 : #endif // LIBMESH_ENABLE_AMR
766 :
767 : // Assign the IDs
768 29760890 : elem->subdomain_id() = subdomain_id;
769 29760890 : elem->processor_id() = processor_id;
770 29760890 : elem->set_id() = id;
771 : #ifdef LIBMESH_ENABLE_UNIQUE_ID
772 43325 : elem->set_unique_id(unique_id);
773 : #endif
774 :
775 : // Assign the connectivity
776 43325 : libmesh_assert_equal_to (elem->n_nodes(), n_nodes);
777 :
778 166883470 : for (unsigned int n=0; n != n_nodes; n++)
779 137341515 : elem->set_node (n, mesh->node_ptr
780 137341515 : (cast_int<dof_id_type>(*in++)));
781 :
782 : // Set interior_parent if found
783 : {
784 : // We may be unpacking an element that was a ghost element on the
785 : // sender, in which case the element's interior_parent may not be
786 : // known by the packed element. We'll have to set such
787 : // interior_parents to remote_elem ourselves and wait for a
788 : // later packed element to give us better information.
789 29760890 : if (interior_parent_id == remote_elem->id())
790 : {
791 : elem->set_interior_parent
792 0 : (const_cast<RemoteElem *>(remote_elem));
793 : }
794 29760890 : else if (interior_parent_id != DofObject::invalid_id)
795 : {
796 : // If we don't have the interior parent element, then it's
797 : // a remote_elem until we get it.
798 : Elem * ip =
799 11209 : mesh->interior_mesh().query_elem_ptr(interior_parent_id);
800 11209 : if (!ip )
801 : elem->set_interior_parent
802 1065 : (const_cast<RemoteElem *>(remote_elem));
803 : else
804 10144 : elem->set_interior_parent(ip);
805 : }
806 : }
807 :
808 149399460 : for (auto n : elem->side_index_range())
809 : {
810 : const dof_id_type neighbor_id =
811 119638570 : cast_int<dof_id_type>(*in++);
812 :
813 : const dof_id_type neighbor_side =
814 119638570 : cast_int<dof_id_type>(*in++);
815 :
816 119638570 : if (neighbor_id == DofObject::invalid_id)
817 13456592 : continue;
818 :
819 : // We may be unpacking an element that was a ghost element on the
820 : // sender, in which case the element's neighbors may not all be
821 : // known by the packed element. We'll have to set such
822 : // neighbors to remote_elem ourselves and wait for a later
823 : // packed element to give us better information.
824 106011778 : if (neighbor_id == remote_elem->id())
825 : {
826 3784624 : elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
827 3784624 : continue;
828 : }
829 :
830 : // If we don't have the neighbor element, then it's a
831 : // remote_elem until we get it.
832 102227154 : Elem * neigh = mesh->query_elem_ptr(neighbor_id);
833 102227154 : if (!neigh)
834 : {
835 48405262 : elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
836 48405262 : continue;
837 : }
838 :
839 : // If we have the neighbor element, then link to it, and
840 : // make sure any appropriate parts of its family link back
841 : // to us.
842 53821892 : elem->set_neighbor(n, neigh);
843 :
844 53821892 : elem->make_links_to_me_local(n, neighbor_side);
845 : }
846 :
847 29760890 : elem->unpack_indexing(in);
848 :
849 29760890 : mesh->add_elem(elem);
850 : }
851 :
852 74525202 : in += elem->packed_indexing_size();
853 :
854 : // We check if this is cell holds a boundary ID or not
855 74525202 : auto on_boundary = *in++;
856 74525202 : if (on_boundary)
857 : {
858 : // Only treat the sides with caution. This is because we might hold boundary IDs
859 : // on the sides of the children. This is not supported for edges and shell faces, thus
860 : // they are treated assuming that only top parents can hold the IDs.
861 10595544 : auto children_on_boundary = *in++;
862 10595544 : if (elem->level() == 0 || children_on_boundary)
863 : {
864 56084688 : for (auto s : elem->side_index_range())
865 : {
866 : const boundary_id_type num_bcs =
867 45489144 : cast_int<boundary_id_type>(*in++);
868 :
869 58081168 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
870 7294 : mesh->get_boundary_info().add_side
871 12599318 : (elem, s, cast_int<boundary_id_type>(*in++));
872 : }
873 : }
874 : }
875 :
876 : // If this is a coarse element,
877 : // add any element side or edge boundary condition ids
878 74525202 : if (level == 0)
879 : {
880 171084902 : for (auto e : elem->edge_index_range())
881 : {
882 : const boundary_id_type num_bcs =
883 147765908 : cast_int<boundary_id_type>(*in++);
884 :
885 147769092 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
886 48 : mesh->get_boundary_info().add_edge
887 3232 : (elem, e, cast_int<boundary_id_type>(*in++));
888 : }
889 :
890 69956982 : for (unsigned short sf=0; sf != 2; ++sf)
891 : {
892 : const boundary_id_type num_bcs =
893 46637988 : cast_int<boundary_id_type>(*in++);
894 :
895 46898896 : for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
896 3328 : mesh->get_boundary_info().add_shellface
897 264236 : (elem, sf, cast_int<boundary_id_type>(*in++));
898 : }
899 : }
900 :
901 : // Return the new element
902 74525202 : return elem;
903 : }
904 :
905 :
906 :
907 : template <>
908 : Elem *
909 14867675 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
910 : DistributedMesh * mesh)
911 : {
912 14867675 : return unpack(in, static_cast<MeshBase*>(mesh));
913 : }
914 :
915 :
916 :
917 : template <>
918 : Elem *
919 0 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
920 : ParallelMesh * mesh)
921 : {
922 0 : return unpack(in, static_cast<MeshBase*>(mesh));
923 : }
924 :
925 : } // namespace Parallel
926 :
927 : } // namespace libMesh
|