LCOV - code coverage report
Current view: top level - src/parallel - parallel_elem.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4476 (4beb67) with base a68cc6 Lines: 297 311 95.5 %
Date: 2026-06-03 20:22:46 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          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    79460858 : 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    79460858 :     cast_int<unsigned int>(*in);
      68             : 
      69             :   // int 4: element type
      70    79460858 :   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    79460858 :   const unsigned int n_nodes =
      77             :     Elem::type_to_n_nodes_map[type];
      78             : 
      79    79460858 :   if (n_nodes == invalid_uint)
      80           0 :     libmesh_not_implemented_msg("Support for Polygons/Polyhedra not yet implemented");
      81             : 
      82    79460858 :   const unsigned int n_sides =
      83             :     Elem::type_to_n_sides_map[type];
      84             : 
      85    79460858 :   const unsigned int n_edges =
      86             :     Elem::type_to_n_edges_map[type];
      87             : 
      88    79460858 :   const unsigned int pre_indexing_size =
      89    79460858 :     header_size + n_nodes + n_sides*2;
      90             : 
      91             :   const unsigned int indexing_size =
      92    79460858 :     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    79460858 :   largest_id_type on_boundary = *(in + pre_indexing_size + indexing_size);
      97             : 
      98    79460858 :   if (on_boundary)
      99             :   {
     100             :     // Extracting if the children are allowed on the boundary
     101       12299 :     total_packed_bc_data++;
     102    12537258 :     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    12537258 :     if (level == 0 || allow_children_on_boundary)
     107             :     {
     108    66716980 :       for (unsigned int s = 0; s != n_sides; ++s)
     109             :       {
     110             :         const int n_bcs = cast_int<int>
     111    54235854 :           (*(in + pre_indexing_size + indexing_size +
     112    54235854 :             total_packed_bc_data++));
     113       56132 :         libmesh_assert_greater_equal (n_bcs, 0);
     114    54179722 :         total_packed_bc_data += n_bcs;
     115             :       }
     116             :     }
     117             :   }
     118    79460858 :   if (level == 0)
     119             :     {
     120   207013171 :       for (unsigned int e = 0; e != n_edges; ++e)
     121             :         {
     122             :           const int n_bcs = cast_int<int>
     123   179668692 :             (*(in + pre_indexing_size + indexing_size +
     124   179668692 :               total_packed_bc_data++));
     125      617308 :           libmesh_assert_greater_equal (n_bcs, 0);
     126   179051384 :           total_packed_bc_data += n_bcs;
     127             :         }
     128             : 
     129    83885361 :       for (unsigned short sf=0; sf != 2; ++sf)
     130             :         {
     131             :           const int n_bcs = cast_int<int>
     132    56124726 :             (*(in + pre_indexing_size + indexing_size +
     133    56124726 :               total_packed_bc_data++));
     134      201152 :           libmesh_assert_greater_equal (n_bcs, 0);
     135    55923574 :           total_packed_bc_data += n_bcs;
     136             :         }
     137             :     }
     138             : 
     139             :   return
     140             : #ifndef NDEBUG
     141             :     1 + // Account for magic header
     142             : #endif
     143    79460858 :     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    23853727 : 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    23853727 :   const unsigned short n_sides = elem->n_sides();
     165             : 
     166      107946 :   largest_id_type on_boundary = 0;
     167   105079197 :   for (auto s : elem->side_index_range())
     168    86488580 :     if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
     169             :     {
     170       11822 :       on_boundary = 1;
     171       11822 :       break;
     172             :     }
     173             : 
     174    23853727 :   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     5317102 :     if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
     181             :     {
     182     5317102 :       total_packed_bcs += n_sides;
     183    27866474 :       for (unsigned short s = 0; s != n_sides; ++s)
     184    22549372 :         total_packed_bcs +=
     185    22549372 :           mesh->get_boundary_info().n_raw_boundary_ids(elem,s);
     186             :     }
     187             :   }
     188             : 
     189    23853727 :   if (elem->level() == 0)
     190             :     {
     191    12641668 :       const unsigned short n_edges = elem->n_edges();
     192    12641668 :       total_packed_bcs += n_edges;
     193    94344256 :       for (unsigned short e = 0; e != n_edges; ++e)
     194    81702588 :         total_packed_bcs +=
     195    81702588 :           mesh->get_boundary_info().n_edge_boundary_ids(elem,e);
     196             : 
     197    12641668 :       total_packed_bcs += 2; // shellfaces
     198    37925004 :       for (unsigned short sf=0; sf != 2; ++sf)
     199    25283336 :         total_packed_bcs +=
     200    25283336 :           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    23853727 :     header_size + elem->n_nodes() + n_sides*2 +
     208    23853727 :     elem->packed_indexing_size() + total_packed_bcs;
     209             : }
     210             : 
     211             : 
     212             : 
     213             : template <>
     214             : unsigned int
     215    15856332 : Packing<const Elem *>::packable_size (const Elem * const & elem,
     216             :                                       const DistributedMesh * mesh)
     217             : {
     218    15856332 :   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    23798993 : 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    23798993 :   *data_out++ = (static_cast<largest_id_type>(elem->level()));
     247    23798993 :   *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    23798993 :     static_cast<largest_id_type>(elem->refinement_flag());
     255       53954 :   if (elem->has_children())
     256     3103032 :     refinement_info +=
     257             :       static_cast<largest_id_type>(Elem::INVALID_REFINEMENTSTATE) + 1;
     258       53954 :   *data_out++ = (refinement_info);
     259             : 
     260    23798993 :   *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    23798993 :   *data_out++ = (static_cast<largest_id_type>(elem->type()));
     268    23798993 :   *data_out++ = (elem->processor_id());
     269    23798993 :   *data_out++ = (elem->subdomain_id());
     270    23798993 :   *data_out++ = (elem->id());
     271             : 
     272             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     273    23798993 :   if (elem->valid_unique_id())
     274    23798993 :     *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    23798993 :   if (elem->level() == 0)
     283             :     {
     284      100004 :       *data_out++ =(DofObject::invalid_id);
     285      100004 :       *data_out++ =(DofObject::invalid_id);
     286             :     }
     287             :   else
     288             :     {
     289    11212059 :       *data_out++ =(elem->parent()->id());
     290    11212059 :       *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    30902715 :   if ((elem->dim() < LIBMESH_DIM) &&
     298     7103722 :       elem->interior_parent())
     299        4588 :     *data_out++ =(elem->interior_parent()->id());
     300             :   else
     301      107852 :     *data_out++ =(DofObject::invalid_id);
     302             : 
     303   253198153 :   for (const Node & node : elem->node_ref_range())
     304   229345206 :     *data_out++ = node.id();
     305             : 
     306             :   // Add the id of and the side for any return link from each neighbor
     307   124370817 :   for (auto neigh : elem->neighbor_ptr_range())
     308             :     {
     309   100517870 :       if (neigh)
     310             :       {
     311    90487346 :         *data_out++ = (neigh->id());
     312    90487346 :         if (neigh == remote_elem)
     313        5970 :           *data_out++ = (DofObject::invalid_id);
     314             :         else
     315    83122535 :           *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    23798993 :   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    23798993 :   largest_id_type on_boundary = 0;
     331   104819779 :   for (auto s : elem->side_index_range())
     332    86277384 :     if (mesh->get_boundary_info().n_raw_boundary_ids(elem,s))
     333             :     {
     334     5310552 :       on_boundary = 1;
     335     5310552 :       break;
     336             :     }
     337             : 
     338       53954 :   *data_out++ = on_boundary;
     339             : 
     340    23798993 :   if (on_boundary)
     341             :   {
     342     5310552 :     *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     5310552 :     if (elem->level() == 0 || mesh->get_boundary_info().is_children_on_boundary_side())
     346             :     {
     347       11788 :       std::vector<boundary_id_type> bcs;
     348    27836548 :       for (auto s : elem->side_index_range())
     349             :       {
     350    22520102 :         mesh->get_boundary_info().raw_boundary_ids(elem, s, bcs);
     351             : 
     352    45013538 :         *data_out++ =(bcs.size());
     353             : 
     354    28412256 :         for (const auto & bid : bcs)
     355    11768924 :           *data_out++ = bid;
     356             :       }
     357             :     }
     358             :   }
     359             : 
     360             :   // If this is a coarse element,
     361             :   // Add any element side boundary condition ids
     362    23798993 :   if (elem->level() == 0)
     363             :   {
     364      100004 :     std::vector<boundary_id_type> bcs;
     365    94034414 :     for (auto e : elem->edge_index_range())
     366             :       {
     367    81393526 :         mesh->get_boundary_info().edge_boundary_ids(elem, e, bcs);
     368             : 
     369   162481090 :         *data_out++ =(bcs.size());
     370             : 
     371    81394182 :         for (const auto & bid : bcs)
     372        1216 :           *data_out++ = bid;
     373             :       }
     374             : 
     375    37772658 :     for (unsigned short sf=0; sf != 2; ++sf)
     376             :       {
     377    25181772 :         mesh->get_boundary_info().shellface_boundary_ids(elem, sf, bcs);
     378             : 
     379    50263540 :         *data_out++ =(bcs.size());
     380             : 
     381    25249532 :         for (const auto & bid : bcs)
     382      128864 :           *data_out++ = bid;
     383             :       }
     384             :   }
     385    23798993 : }
     386             : 
     387             : 
     388             : 
     389             : template <>
     390             : void
     391    15847860 : 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    15847860 :   pack(elem, data_out, static_cast<const MeshBase*>(mesh));
     396    15847860 : }
     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    79406904 : 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    79406904 :     cast_int<unsigned int>(*in++);
     427             : 
     428             : #ifdef LIBMESH_ENABLE_AMR
     429             :   // int 1: p level
     430             :   const unsigned int p_level =
     431    79406904 :     cast_int<unsigned int>(*in++);
     432             : 
     433             :   // int 2: refinement flag and encoded has_children
     434    79406904 :   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    79406904 :   const Elem::RefinementState refinement_flag = has_children ?
     444    15194697 :     cast_int<Elem::RefinementState>(rflag - invalid_rflag - 1) :
     445       53910 :     cast_int<Elem::RefinementState>(rflag);
     446             : 
     447             :   // int 3: p refinement flag
     448    79406904 :   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    79406904 :   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    79406904 :   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    79406904 :     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    79406904 :     cast_int<subdomain_id_type>(*in++);
     476             : 
     477             :   // int 7: dof object id
     478             :   const dof_id_type id =
     479    79406904 :     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    79406904 :     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    79406904 :     ? static_cast<dof_id_type>(*in++)
     497    51495119 :     : 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    79406904 :     ? static_cast<unsigned int>(*in++)
     507    51495119 :     : 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    79406904 :     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    79406904 :   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    79406904 :   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    49308834 :         if (interior_parent_id == DofObject::invalid_id)
     568             :           {
     569    49291137 :             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   256346699 :       for (auto n : elem->side_index_range())
     617             :         {
     618             :           const dof_id_type neighbor_id =
     619   207037865 :             cast_int<dof_id_type>(*in++);
     620             : 
     621             :           const dof_id_type neighbor_side =
     622   207037865 :             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   207037865 :           if (neighbor_id == DofObject::invalid_id)
     629             :             {
     630    19793180 :               const Elem * my_neigh = elem->neighbor_ptr(n);
     631    19793180 :               if (my_neigh == remote_elem)
     632           1 :                 elem->set_neighbor(n, nullptr);
     633             :               else
     634        4883 :                 libmesh_assert (!my_neigh);
     635    19793180 :               continue;
     636    19783412 :             }
     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   187244685 :           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    18148657 :               continue;
     650             :             }
     651             : 
     652   169092983 :           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   169092983 :           if (!neigh)
     658             :             {
     659        2442 :               libmesh_assert_equal_to (elem->neighbor_ptr(n), remote_elem);
     660     5503090 :               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   163625346 :           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   163587451 :           if (neighbor_side != libMesh::invalid_uint)
     684   163580948 :             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    49318524 :       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    30098070 :       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    25270975 :           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    30098070 :       elem = Elem::build(type,parent).release();
     734       45284 :       libmesh_assert (elem);
     735             : 
     736             : #ifdef LIBMESH_ENABLE_AMR
     737    30098070 :       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    25270975 :           parent->add_child(elem, which_child_am_i);
     744             :         }
     745             : 
     746             :       // Assign the refinement flags and levels
     747    30098070 :       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    30098070 :       if (has_children)
     756             :         {
     757     6019252 :           const unsigned int nc = elem->n_children();
     758    30359302 :           for (unsigned int c=0; c != nc; ++c)
     759    24340050 :             elem->add_child(const_cast<RemoteElem *>(remote_elem), c);
     760             :         }
     761             : 
     762             : #endif // LIBMESH_ENABLE_AMR
     763             : 
     764             :       // Assign the IDs
     765    30098070 :       elem->subdomain_id()  = subdomain_id;
     766    30098070 :       elem->processor_id()  = processor_id;
     767    30098070 :       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   170460772 :       for (unsigned int n=0; n != n_nodes; n++)
     776   140601747 :         elem->set_node (n, mesh->node_ptr
     777   140601747 :                         (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    30098070 :         if (interior_parent_id == remote_elem->id())
     787             :           {
     788             :             elem->set_interior_parent
     789           0 :               (const_cast<RemoteElem *>(remote_elem));
     790             :           }
     791    30098070 :         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   151134911 :       for (auto n : elem->side_index_range())
     806             :         {
     807             :           const dof_id_type neighbor_id =
     808   121036841 :             cast_int<dof_id_type>(*in++);
     809             : 
     810             :             const dof_id_type neighbor_side =
     811   121036841 :               cast_int<dof_id_type>(*in++);
     812             : 
     813   121036841 :           if (neighbor_id == DofObject::invalid_id)
     814    14123074 :             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   213467438 :           if (neighbor_id == remote_elem->id())
     822             :             {
     823     3885804 :               elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
     824     3885804 :               continue;
     825             :             }
     826             : 
     827             :           // If we don't have the neighbor element, then it's a
     828             :           // remote_elem until we get it.
     829   102849429 :           Elem * neigh = mesh->query_elem_ptr(neighbor_id);
     830   102849429 :           if (!neigh)
     831             :             {
     832    48616608 :               elem->set_neighbor(n, const_cast<RemoteElem *>(remote_elem));
     833    48616608 :               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    54232821 :           elem->set_neighbor(n, neigh);
     840             : 
     841    54232821 :           if (neighbor_side != libMesh::invalid_uint)
     842    54231669 :             elem->make_links_to_me_local(n, neighbor_side);
     843             :         }
     844             : 
     845    30098070 :       elem->unpack_indexing(in);
     846             : 
     847    30098070 :       mesh->add_elem(elem);
     848             :     }
     849             : 
     850    79406904 :   in += elem->packed_indexing_size();
     851             : 
     852             :   // We check if this is cell holds a boundary ID or not
     853    79406904 :   auto on_boundary = *in++;
     854    79406904 :   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    12531364 :     auto children_on_boundary = *in++;
     860    12531364 :     if (elem->level() == 0 || children_on_boundary)
     861             :     {
     862    66684420 :       for (auto s : elem->side_index_range())
     863             :         {
     864             :           const boundary_id_type num_bcs =
     865    54153056 :             cast_int<boundary_id_type>(*in++);
     866             : 
     867    69257011 :           for (boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
     868        8778 :             mesh->get_boundary_info().add_side
     869    15112733 :               (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    79406904 :   if (level == 0)
     877             :     {
     878   206657207 :       for (auto e : elem->edge_index_range())
     879             :         {
     880             :           const boundary_id_type num_bcs =
     881   178745422 :             cast_int<boundary_id_type>(*in++);
     882             : 
     883   178748606 :           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    83735355 :       for (unsigned short sf=0; sf != 2; ++sf)
     889             :         {
     890             :           const boundary_id_type num_bcs =
     891    55823570 :             cast_int<boundary_id_type>(*in++);
     892             : 
     893    56084478 :           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    79406904 :   return elem;
     901             : }
     902             : 
     903             : 
     904             : 
     905             : template <>
     906             : Elem *
     907    15847860 : Packing<Elem *>::unpack (std::vector<largest_id_type>::const_iterator in,
     908             :                          DistributedMesh * mesh)
     909             : {
     910    15847860 :   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

Generated by: LCOV version 1.14