LCOV - code coverage report
Current view: top level - src/parallel - parallel_elem.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 297 311 95.5 %
Date: 2025-08-19 19:27:09 Functions: 8 11 72.7 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14