LCOV - code coverage report
Current view: top level - src/parallel - parallel_node.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 80 88 90.9 %
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             : // Local includes
      21             : #include "libmesh/boundary_info.h"
      22             : #include "libmesh/distributed_mesh.h"
      23             : #include "libmesh/mesh_base.h"
      24             : #include "libmesh/node.h"
      25             : #include "libmesh/parallel_mesh.h"
      26             : #include "libmesh/parallel_node.h"
      27             : 
      28             : // C++ includes
      29             : #include <cstring> // memcpy
      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 = 3;
      39             : #else
      40             : static const unsigned int header_size = 2;
      41             : #endif
      42             : 
      43             : // use "(a+b-1)/b" trick to get a/b to round up
      44             : static const unsigned int idtypes_per_Real =
      45             :   (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
      46             : 
      47             : #ifndef NDEBUG
      48             : // Currently this constant is only used for debugging.
      49             : static const largest_id_type node_magic_header = 1234567890;
      50             : #endif
      51             : }
      52             : 
      53             : 
      54             : namespace libMesh
      55             : {
      56             : 
      57             : namespace Parallel
      58             : {
      59             : 
      60             : template <>
      61             : unsigned int
      62    65454968 : Packing<const Node *>::packable_size (const Node * const & node,
      63             :                                       const MeshBase * mesh)
      64             : {
      65             :   return
      66             : #ifndef NDEBUG
      67             :     1 + // add an int for the magic header when testing
      68             : #endif
      69             :     header_size + LIBMESH_DIM*idtypes_per_Real +
      70    65454968 :     node->packed_indexing_size() +
      71    65454968 :     1 + mesh->get_boundary_info().n_boundary_ids(node);
      72             : }
      73             : 
      74             : 
      75             : 
      76             : template <>
      77             : unsigned int
      78   151988550 : Packing<const Node *>::packed_size (const std::vector<largest_id_type>::const_iterator in)
      79             : {
      80      223734 :   const unsigned int pre_indexing_size =
      81             : #ifndef NDEBUG
      82             :     1 + // add an int for the magic header when testing
      83             : #endif
      84             :     header_size + LIBMESH_DIM*idtypes_per_Real;
      85             : 
      86             :   const unsigned int indexing_size =
      87   151988550 :     DofObject::unpackable_indexing_size(in+pre_indexing_size);
      88             : 
      89             :   const int n_bcs = cast_int<int>
      90   151988550 :     (*(in + pre_indexing_size + indexing_size));
      91      223734 :   libmesh_assert_greater_equal (n_bcs, 0);
      92             : 
      93   151988550 :   return pre_indexing_size + indexing_size + 1 + n_bcs;
      94             : }
      95             : 
      96             : 
      97             : 
      98             : template <>
      99             : unsigned int
     100       71818 : Packing<const Node *>::packed_size (const std::vector<largest_id_type>::iterator in)
     101             : {
     102       71818 :   return packed_size(std::vector<largest_id_type>::const_iterator(in));
     103             : }
     104             : 
     105             : 
     106             : 
     107             : template <>
     108             : unsigned int
     109    51311224 : Packing<const Node *>::packable_size (const Node * const & node,
     110             :                                       const DistributedMesh * mesh)
     111             : {
     112    51311224 :   return packable_size(node, static_cast<const MeshBase *>(mesh));
     113             : }
     114             : 
     115             : 
     116             : 
     117             : template <>
     118             : unsigned int
     119           0 : Packing<const Node *>::packable_size (const Node * const & node,
     120             :                                       const ParallelMesh * mesh)
     121             : {
     122           0 :   return packable_size(node, static_cast<const MeshBase *>(mesh));
     123             : }
     124             : 
     125             : 
     126             : // Ignore warning about memcpy to a boost float128 address
     127             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
     128             : #include "libmesh/ignore_warnings.h"
     129             : #endif
     130             : 
     131             : template <>
     132             : void
     133    65380550 : Packing<const Node *>::pack (const Node * const & node,
     134             :                              std::back_insert_iterator<std::vector<largest_id_type>> data_out,
     135             :                              const MeshBase * mesh)
     136             : {
     137       71818 :   libmesh_assert(node);
     138             : 
     139             : #ifndef NDEBUG
     140       71818 :   *data_out++ = (node_magic_header);
     141             : #endif
     142             : 
     143    65380550 :   *data_out++ = (static_cast<largest_id_type>(node->processor_id()));
     144    65380550 :   *data_out++ = (static_cast<largest_id_type>(node->id()));
     145             : 
     146             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     147    65380550 :   if (node->valid_unique_id())
     148    65380550 :     *data_out++ = (static_cast<largest_id_type>(node->unique_id()));
     149             :   else
     150             :     // OK to send invalid unique id, we must not own this DOF
     151           0 :     *data_out++ = (static_cast<largest_id_type>(DofObject::invalid_unique_id));
     152             : #endif
     153             : 
     154   261522200 :   for (unsigned int i=0; i != LIBMESH_DIM; ++i)
     155             :     {
     156   196141650 :       const Real node_i = (*node)(i);
     157             :       largest_id_type Real_as_idtypes[idtypes_per_Real];
     158   196141650 :       std::memcpy(Real_as_idtypes, &node_i, sizeof(Real));
     159   392283300 :       for (unsigned int j=0; j != idtypes_per_Real; ++j)
     160      215454 :         *data_out++ =(Real_as_idtypes[j]);
     161             :     }
     162             : 
     163             :   // Add any DofObject indices
     164    65380550 :   node->pack_indexing(data_out);
     165             : 
     166             :   // Add any nodal boundary condition ids
     167      143636 :   std::vector<boundary_id_type> bcs;
     168    65380550 :   mesh->get_boundary_info().boundary_ids(node, bcs);
     169             : 
     170       71818 :   libmesh_assert(bcs.size() < std::numeric_limits<largest_id_type>::max());
     171             : 
     172   130689282 :   *data_out++ =(bcs.size());
     173             : 
     174    75368654 :   for (const auto & bid : bcs)
     175    19947590 :     *data_out++ = bid;
     176    65380550 : }
     177             : 
     178             : 
     179             : 
     180             : template <>
     181             : Node *
     182   151840774 : Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
     183             :                          MeshBase * mesh)
     184             : {
     185             : #ifndef NDEBUG
     186       75958 :   const std::vector<largest_id_type>::const_iterator original_in = in;
     187       75958 :   const largest_id_type incoming_header = *in++;
     188       75958 :   libmesh_assert_equal_to (incoming_header, node_magic_header);
     189             : #endif
     190             : 
     191   151840774 :   const processor_id_type processor_id = cast_int<processor_id_type>(*in++);
     192       75958 :   libmesh_assert(processor_id == DofObject::invalid_processor_id ||
     193             :                  processor_id < mesh->n_processors());
     194             : 
     195   151840774 :   const dof_id_type id = cast_int<dof_id_type>(*in++);
     196             : 
     197             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     198   151840774 :   const unique_id_type unique_id = cast_int<unique_id_type>(*in++);
     199             : #endif
     200             : 
     201   151840774 :   Node * node = mesh->query_node_ptr(id);
     202             : 
     203   151840774 :   if (node)
     204             :     {
     205       28524 :       libmesh_assert_equal_to (node->processor_id(), processor_id);
     206             : 
     207             :       // We currently don't communicate mesh motion via packed Nodes,
     208             :       // so it should usually be safe to assume (and assert) that Node
     209             :       // locations are consistent between processors.
     210             :       //
     211             :       // There may be exceptions due to rounding in file I/O, so we'll
     212             :       // only assert equality to within a tight tolerance, and we'll
     213             :       // believe the sender's node locations over our own if we don't
     214             :       // own the node.
     215   490100076 :       for (unsigned int i=0; i != LIBMESH_DIM; ++i)
     216             :         {
     217             :           Real idtypes_as_Real;
     218   367575057 :           std::memcpy(&idtypes_as_Real, &(*in), sizeof(Real));
     219       85572 :           in += idtypes_per_Real;
     220       85572 :           libmesh_assert_less_equal ((*node)(i), idtypes_as_Real + (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
     221       85572 :           libmesh_assert_greater_equal ((*node)(i), idtypes_as_Real - (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
     222             : 
     223   367660629 :           if (processor_id != mesh->processor_id())
     224   306062661 :             (*node)(i) = idtypes_as_Real;
     225             :         }
     226             : 
     227   122525019 :       if (!node->has_dofs())
     228             :         {
     229    86475714 :           node->unpack_indexing(in);
     230       25310 :           libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
     231             :                                    node->packed_indexing_size());
     232    86475714 :           in += node->packed_indexing_size();
     233             :         }
     234             :       else
     235             :         {
     236             :           // FIXME: We should add some debug mode tests to ensure that
     237             :           // the encoded indexing is consistent
     238    36049305 :           in += DofObject::unpackable_indexing_size(in);
     239             :         }
     240             :     }
     241             :   else
     242             :     {
     243             :       // If we don't already have it, we need to allocate it.
     244             :       // There is no Node::build() API that lets you defer setting
     245             :       // the (x,y,z) values, so we just use the Node constructor.
     246    29315755 :       auto unode = std::make_unique<Node>();
     247             : 
     248   117263020 :       for (unsigned int i=0; i != LIBMESH_DIM; ++i)
     249             :         {
     250             :           Real idtypes_as_Real;
     251    87947265 :           std::memcpy(&idtypes_as_Real, &(*in), sizeof(Real));
     252    87947265 :           (*unode)(i) = idtypes_as_Real;
     253      142302 :           in += idtypes_per_Real;
     254             :         }
     255             : 
     256    29315755 :       unode->set_id() = id;
     257             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     258       47434 :       unode->set_unique_id(unique_id);
     259             : #endif
     260    29315755 :       unode->processor_id() = processor_id;
     261             : 
     262    29315755 :       unode->unpack_indexing(in);
     263       47434 :       libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
     264             :                                unode->packed_indexing_size());
     265    29315755 :       in += unode->packed_indexing_size();
     266             : 
     267    29410623 :       node = mesh->add_node(std::move(unode));
     268    29220887 :     }
     269             : 
     270             :   // FIXME: We should add some debug mode tests to ensure that the
     271             :   // encoded boundary conditions are consistent
     272             : 
     273             :   // Add any nodal boundary condition ids
     274   151840774 :   const largest_id_type num_bcs = *in++;
     275             :   // libmesh_assert_greater_equal (num_bcs, 0);
     276             : 
     277   175099898 :   for (largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
     278       17584 :     mesh->get_boundary_info().add_node
     279    23276708 :       (node, cast_int<boundary_id_type>(*in++));
     280             : 
     281             : #ifndef NDEBUG
     282       75958 :   libmesh_assert (in - original_in ==
     283             :                   cast_int<int>
     284             :                   (Parallel::Packing<const Node*>::packed_size(original_in)));
     285             : #endif
     286             : 
     287   151840774 :   return node;
     288             : }
     289             : 
     290             : 
     291             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
     292             : #include "libmesh/restore_warnings.h"
     293             : #endif
     294             : 
     295             : 
     296             : template <>
     297             : void
     298    51288376 : Packing<const Node *>::pack (const Node * const & node,
     299             :                              std::back_insert_iterator<std::vector<largest_id_type>> data_out,
     300             :                              const DistributedMesh * mesh)
     301             : {
     302    51288376 :   pack(node, data_out, static_cast<const MeshBase*>(mesh));
     303    51288376 : }
     304             : 
     305             : 
     306             : 
     307             : template <>
     308             : void
     309           0 : Packing<const Node *>::pack (const Node * const & node,
     310             :                              std::back_insert_iterator<std::vector<largest_id_type>> data_out,
     311             :                              const ParallelMesh * mesh)
     312             : {
     313           0 :   pack(node, data_out, static_cast<const MeshBase*>(mesh));
     314           0 : }
     315             : 
     316             : 
     317             : 
     318             : template <>
     319             : Node *
     320    51288376 : Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
     321             :                          DistributedMesh * mesh)
     322             : {
     323    51288376 :   return unpack(in, static_cast<MeshBase*>(mesh));
     324             : }
     325             : 
     326             : 
     327             : 
     328             : template <>
     329             : Node *
     330           0 : Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
     331             :                          ParallelMesh * mesh)
     332             : {
     333           0 :   return unpack(in, static_cast<MeshBase*>(mesh));
     334             : }
     335             : 
     336             : } // namespace Parallel
     337             : 
     338             : } // namespace libMesh

Generated by: LCOV version 1.14