libMesh
Loading...
Searching...
No Matches
parallel_node.C
Go to the documentation of this file.
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// 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
33namespace
34{
35using namespace libMesh;
36
37#ifdef LIBMESH_ENABLE_UNIQUE_ID
38static const unsigned int header_size = 3;
39#else
40static const unsigned int header_size = 2;
41#endif
42
43// use "(a+b-1)/b" trick to get a/b to round up
44static 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.
49static const largest_id_type node_magic_header = 1234567890;
50#endif
51}
52
53
54namespace libMesh
55{
56
57namespace Parallel
58{
59
60template <>
61unsigned int
62Packing<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 node->packed_indexing_size() +
72}
73
74
75
76template <>
77unsigned int
78Packing<const Node *>::packed_size (const std::vector<largest_id_type>::const_iterator in)
79{
80 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 DofObject::unpackable_indexing_size(in+pre_indexing_size);
88
89 const int n_bcs = cast_int<int>
90 (*(in + pre_indexing_size + indexing_size));
91 libmesh_assert_greater_equal (n_bcs, 0);
92
93 return pre_indexing_size + indexing_size + 1 + n_bcs;
94}
95
96
97
98template <>
99unsigned int
100Packing<const Node *>::packed_size (const std::vector<largest_id_type>::iterator in)
101{
102 return packed_size(std::vector<largest_id_type>::const_iterator(in));
103}
104
105
106
107template <>
108unsigned int
109Packing<const Node *>::packable_size (const Node * const & node,
110 const DistributedMesh * mesh)
111{
112 return packable_size(node, static_cast<const MeshBase *>(mesh));
113}
114
115
116
117template <>
118unsigned int
119Packing<const Node *>::packable_size (const Node * const & node,
120 const ParallelMesh * mesh)
121{
122 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
131template <>
132void
133Packing<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 libmesh_assert(node);
138
139#ifndef NDEBUG
140 *data_out++ = (node_magic_header);
141#endif
142
143 *data_out++ = (static_cast<largest_id_type>(node->processor_id()));
144 *data_out++ = (static_cast<largest_id_type>(node->id()));
145
146#ifdef LIBMESH_ENABLE_UNIQUE_ID
147 if (node->valid_unique_id())
148 *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 *data_out++ = (static_cast<largest_id_type>(DofObject::invalid_unique_id));
152#endif
153
154 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
155 {
156 const Real node_i = (*node)(i);
157 largest_id_type Real_as_idtypes[idtypes_per_Real];
158 std::memcpy(Real_as_idtypes, &node_i, sizeof(Real));
159 for (unsigned int j=0; j != idtypes_per_Real; ++j)
160 *data_out++ =(Real_as_idtypes[j]);
161 }
162
163 // Add any DofObject indices
164 node->pack_indexing(data_out);
165
166 // Add any nodal boundary condition ids
167 std::vector<boundary_id_type> bcs;
168 mesh->get_boundary_info().boundary_ids(node, bcs);
169
170 libmesh_assert(bcs.size() < std::numeric_limits<largest_id_type>::max());
171
172 *data_out++ =(bcs.size());
173
174 for (const auto & bid : bcs)
175 *data_out++ = bid;
176}
177
178
179
180template <>
181Node *
182Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
183 MeshBase * mesh)
184{
185#ifndef NDEBUG
186 const std::vector<largest_id_type>::const_iterator original_in = in;
187 const largest_id_type incoming_header = *in++;
188 libmesh_assert_equal_to (incoming_header, node_magic_header);
189#endif
190
191 const processor_id_type processor_id = cast_int<processor_id_type>(*in++);
193 processor_id < mesh->n_processors());
194
195 const dof_id_type id = cast_int<dof_id_type>(*in++);
196
197#ifdef LIBMESH_ENABLE_UNIQUE_ID
198 const unique_id_type unique_id = cast_int<unique_id_type>(*in++);
199#endif
200
201 Node * node = mesh->query_node_ptr(id);
202
203 if (node)
204 {
205 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 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
216 {
217 Real idtypes_as_Real;
218 std::memcpy(&idtypes_as_Real, &(*in), sizeof(Real));
219 in += idtypes_per_Real;
220 libmesh_assert_less_equal ((*node)(i), idtypes_as_Real + (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
221 libmesh_assert_greater_equal ((*node)(i), idtypes_as_Real - (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
222
223 if (processor_id != mesh->processor_id())
224 (*node)(i) = idtypes_as_Real;
225 }
226
227 if (!node->has_dofs())
228 {
229 node->unpack_indexing(in);
230 libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
231 node->packed_indexing_size());
232 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
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 auto unode = std::make_unique<Node>();
247
248 for (unsigned int i=0; i != LIBMESH_DIM; ++i)
249 {
250 Real idtypes_as_Real;
251 std::memcpy(&idtypes_as_Real, &(*in), sizeof(Real));
252 (*unode)(i) = idtypes_as_Real;
253 in += idtypes_per_Real;
254 }
255
256 unode->set_id() = id;
257#ifdef LIBMESH_ENABLE_UNIQUE_ID
258 unode->set_unique_id(unique_id);
259#endif
260 unode->processor_id() = processor_id;
261
262 unode->unpack_indexing(in);
263 libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
264 unode->packed_indexing_size());
265 in += unode->packed_indexing_size();
266
267 node = mesh->add_node(std::move(unode));
268 }
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 const largest_id_type num_bcs = *in++;
275 // libmesh_assert_greater_equal (num_bcs, 0);
276
277 for (largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
279 (node, cast_int<boundary_id_type>(*in++));
280
281#ifndef NDEBUG
282 libmesh_assert (in - original_in ==
283 cast_int<int>
285#endif
286
287 return node;
288}
289
290
291#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
292#include "libmesh/restore_warnings.h"
293#endif
294
295
296template <>
297void
298Packing<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 pack(node, data_out, static_cast<const MeshBase*>(mesh));
303}
304
305
306
307template <>
308void
309Packing<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 pack(node, data_out, static_cast<const MeshBase*>(mesh));
314}
315
316
317
318template <>
319Node *
320Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
322{
323 return unpack(in, static_cast<MeshBase*>(mesh));
324}
325
326
327
328template <>
329Node *
330Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
332{
333 return unpack(in, static_cast<MeshBase*>(mesh));
334}
335
336} // namespace Parallel
337
338} // namespace libMesh
std::size_t n_boundary_ids() const
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
static unsigned int unpackable_indexing_size(std::vector< largest_id_type >::const_iterator begin)
If we have indices packed into an buffer for communications, how much of that buffer applies to this ...
Definition dof_object.C:567
processor_id_type processor_id() const
Definition dof_object.h:881
unique_id_type unique_id() const
Definition dof_object.h:835
void pack_indexing(std::back_insert_iterator< std::vector< largest_id_type > > target) const
A method for creating packed data from our index buffer - basically a copy with prepended size with o...
Definition dof_object.C:634
static constexpr unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition dof_object.h:478
bool valid_unique_id() const
Definition dof_object.h:869
dof_id_type id() const
Definition dof_object.h:819
static constexpr processor_id_type invalid_processor_id
An invalid processor_id to distinguish DoFs that have not been assigned to a processor.
Definition dof_object.h:484
unsigned int packed_indexing_size() const
If we pack our indices into an buffer for communications, how many ints do we need?
Definition dof_object.C:552
void unpack_indexing(std::vector< largest_id_type >::const_iterator begin)
A method for creating our index buffer from packed data - basically with our current implementation w...
Definition dof_object.C:587
bool has_dofs(const unsigned int s=libMesh::invalid_uint) const
This is the MeshBase class.
Definition mesh_base.h:81
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
virtual const Node * query_node_ptr(const dof_id_type i) const =0
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
A Node is like a Point, but with more information.
Definition node.h:55
processor_id_type processor_id() const
std::pair< T1, T2 > unpack(BufferIter in, Context *ctx)
static unsigned int packed_size(BufferIter iter)
unsigned int packable_size(const std::pair< T1, T2 > &pr, const Context *ctx)
void pack(const std::pair< T1, T2 > &pr, OutputIter data_out, const Context *ctx)
MeshBase & mesh
uint8_t processor_id_type
The libMesh namespace provides an interface to certain functionality in the library.
uint8_t unique_id_type
Definition id_types.h:86
libmesh_assert(ctx)
uint64_t largest_id_type
Definition id_types.h:148
static constexpr Real TOLERANCE
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real