libMesh
parallel_node.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2017 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/mesh_base.h"
26 #include "libmesh/node.h"
27 #include "libmesh/parallel.h"
28 #include "libmesh/parallel_mesh.h"
29 
30 // Helper functions in anonymous namespace
31 
32 namespace
33 {
34 using namespace libMesh;
35 
36 #ifdef LIBMESH_ENABLE_UNIQUE_ID
37 static const unsigned int header_size = 3;
38 #else
39 static const unsigned int header_size = 2;
40 #endif
41 
42 // use "(a+b-1)/b" trick to get a/b to round up
43 static const unsigned int idtypes_per_Real =
44  (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
45 
46 #ifndef NDEBUG
47 // Currently this constant is only used for debugging.
48 static const largest_id_type node_magic_header = 1234567890;
49 #endif
50 }
51 
52 
53 namespace libMesh
54 {
55 
56 namespace Parallel
57 {
58 
59 template <>
60 template <>
61 unsigned int
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() +
71  1 + mesh->get_boundary_info().n_boundary_ids(node);
72 }
73 
74 
75 
76 template <>
77 template <>
78 unsigned int
79 Packing<const Node *>::packed_size (const std::vector<largest_id_type>::const_iterator in)
80 {
81  const unsigned int pre_indexing_size =
82 #ifndef NDEBUG
83  1 + // add an int for the magic header when testing
84 #endif
85  header_size + LIBMESH_DIM*idtypes_per_Real;
86 
87  const unsigned int indexing_size =
88  DofObject::unpackable_indexing_size(in+pre_indexing_size);
89 
90  const int n_bcs = cast_int<int>
91  (*(in + pre_indexing_size + indexing_size));
92  libmesh_assert_greater_equal (n_bcs, 0);
93 
94  return pre_indexing_size + indexing_size + 1 + n_bcs;
95 }
96 
97 
98 
99 template <>
100 template <>
101 unsigned int
102 Packing<const Node *>::packed_size (const std::vector<largest_id_type>::iterator in)
103 {
104  return packed_size(std::vector<largest_id_type>::const_iterator(in));
105 }
106 
107 
108 
109 template <>
110 template <>
111 unsigned int
113  const DistributedMesh * mesh)
114 {
115  return packable_size(node, static_cast<const MeshBase *>(mesh));
116 }
117 
118 
119 
120 template <>
121 template <>
122 unsigned int
124  const ParallelMesh * mesh)
125 {
126  return packable_size(node, static_cast<const MeshBase *>(mesh));
127 }
128 
129 
130 
131 template <>
132 template <>
133 void
134 Packing<const Node *>::pack (const Node * const & node,
135  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
136  const MeshBase * mesh)
137 {
138  libmesh_assert(node);
139 
140 #ifndef NDEBUG
141  *data_out++ = (node_magic_header);
142 #endif
143 
144  *data_out++ = (static_cast<largest_id_type>(node->processor_id()));
145  *data_out++ = (static_cast<largest_id_type>(node->id()));
146 
147 #ifdef LIBMESH_ENABLE_UNIQUE_ID
148  if (node->valid_unique_id())
149  *data_out++ = (static_cast<largest_id_type>(node->unique_id()));
150  else
151  // OK to send invalid unique id, we must not own this DOF
152  *data_out++ = (static_cast<largest_id_type>(DofObject::invalid_unique_id));
153 #endif
154 
155  // use "(a+b-1)/b" trick to get a/b to round up
156  static const unsigned int idtypes_per_Real =
157  (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
158 
159  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
160  {
161  const largest_id_type * Real_as_idtypes =
162  reinterpret_cast<const largest_id_type *>(&((*node)(i)));
163  for (unsigned int j=0; j != idtypes_per_Real; ++j)
164  {
165  *data_out++ =(Real_as_idtypes[j]);
166  }
167  }
168 
169  // Add any DofObject indices
170  node->pack_indexing(data_out);
171 
172  // Add any nodal boundary condition ids
173  std::vector<boundary_id_type> bcs;
174  mesh->get_boundary_info().boundary_ids(node, bcs);
175 
177 
178  *data_out++ =(bcs.size());
179 
180  for (std::vector<boundary_id_type>::iterator bc_it=bcs.begin();
181  bc_it != bcs.end(); ++bc_it)
182  *data_out++ =(*bc_it);
183 }
184 
185 
186 
187 template <>
188 template <>
189 void
190 Packing<const Node *>::pack (const Node * const & node,
191  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
192  const DistributedMesh * mesh)
193 {
194  pack(node, data_out, static_cast<const MeshBase*>(mesh));
195 }
196 
197 
198 
199 template <>
200 template <>
201 void
202 Packing<const Node *>::pack (const Node * const & node,
203  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
204  const ParallelMesh * mesh)
205 {
206  pack(node, data_out, static_cast<const MeshBase*>(mesh));
207 }
208 
209 
210 
211 template <>
212 template <>
213 Node *
214 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
215  MeshBase * mesh)
216 {
217 #ifndef NDEBUG
218  const std::vector<largest_id_type>::const_iterator original_in = in;
219  const largest_id_type incoming_header = *in++;
220  libmesh_assert_equal_to (incoming_header, node_magic_header);
221 #endif
222 
223  const processor_id_type processor_id = cast_int<processor_id_type>(*in++);
225  processor_id < mesh->n_processors());
226 
227  const dof_id_type id = cast_int<dof_id_type>(*in++);
228 
229 #ifdef LIBMESH_ENABLE_UNIQUE_ID
230  const unique_id_type unique_id = cast_int<unique_id_type>(*in++);
231 #endif
232 
233  Node * node = mesh->query_node_ptr(id);
234 
235  if (node)
236  {
237  libmesh_assert_equal_to (node->processor_id(), processor_id);
238 
239  // We currently don't communicate mesh motion via packed Nodes,
240  // so it should usually be safe to assume (and assert) that Node
241  // locations are consistent between processors.
242  //
243  // There may be exceptions due to rounding in file I/O, so we'll
244  // only assert equality to within a tight tolerance, and we'll
245  // believe the sender's node locations over our own if we don't
246  // own the node.
247  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
248  {
249  const Real & idtypes_as_Real = *(reinterpret_cast<const Real *>(&(*in)));
250  libmesh_assert_less_equal ((*node)(i), idtypes_as_Real + (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
251  libmesh_assert_greater_equal ((*node)(i), idtypes_as_Real - (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
252 
253  if (processor_id != mesh->processor_id())
254  (*node)(i) = idtypes_as_Real;
255  in += idtypes_per_Real;
256  }
257 
258  if (!node->has_dofs())
259  {
260  node->unpack_indexing(in);
261  libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
262  node->packed_indexing_size());
263  in += node->packed_indexing_size();
264  }
265  else
266  {
267  // FIXME: We should add some debug mode tests to ensure that
268  // the encoded indexing is consistent
270  }
271  }
272  else
273  {
274  // If we don't already have it, we need to allocate it
275  node = new Node();
276 
277  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
278  {
279  const Real * idtypes_as_Real = reinterpret_cast<const Real *>(&(*in));
280  (*node)(i) = *idtypes_as_Real;
281  in += idtypes_per_Real;
282  }
283 
284  node->set_id() = id;
285 #ifdef LIBMESH_ENABLE_UNIQUE_ID
286  node->set_unique_id() = unique_id;
287 #endif
288  node->processor_id() = processor_id;
289 
290  node->unpack_indexing(in);
291  libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
292  node->packed_indexing_size());
293  in += node->packed_indexing_size();
294  }
295 
296  // FIXME: We should add some debug mode tests to ensure that the
297  // encoded boundary conditions are consistent
298 
299  // Add any nodal boundary condition ids
300  const largest_id_type num_bcs = *in++;
301  // libmesh_assert_greater_equal (num_bcs, 0);
302 
303  for (largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
305  (node, cast_int<boundary_id_type>(*in++));
306 
307 #ifndef NDEBUG
308  libmesh_assert (in - original_in ==
309  cast_int<int>
311 #endif
312 
313  return node;
314 }
315 
316 
317 
318 template <>
319 template <>
320 Node *
321 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
323 {
324  return unpack(in, static_cast<MeshBase*>(mesh));
325 }
326 
327 
328 
329 template <>
330 template <>
331 Node *
332 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
333  ParallelMesh * mesh)
334 {
335  return unpack(in, static_cast<MeshBase*>(mesh));
336 }
337 
338 } // namespace Parallel
339 
340 } // namespace libMesh
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:117
A Node is like a Point, but with more information.
Definition: node.h:52
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:473
MeshBase & mesh
uint64_t largest_id_type
Definition: id_types.h:139
uint8_t processor_id_type
Definition: id_types.h:99
static const Real TOLERANCE
The libMesh namespace provides an interface to certain functionality in the library.
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: parallel.h:582
long double max(long double a, double b)
This is the MeshBase class.
Definition: mesh_base.h:68
bool valid_unique_id() const
Definition: dof_object.h:682
libmesh_assert(j)
std::vector< boundary_id_type > boundary_ids(const Node *node) const
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:532
void add_node(const Node *node, const boundary_id_type id)
Add Node node with boundary id id to the boundary information data structures.
static const unique_id_type invalid_unique_id
An invalid unique_id to distinguish an uninitialized DofObject.
Definition: dof_object.h:329
static const 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:335
virtual const Node * query_node_ptr(const dof_id_type i) const =0
The DistributedMesh class is derived from the MeshBase class, and is intended to provide identical fu...
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:457
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::size_t n_boundary_ids() const
static unsigned int packable_size(const T &object, const Context *context)
static unsigned int packed_size(BufferIter iter)
dof_id_type id() const
Definition: dof_object.h:632
static void pack(const T &object, OutputIter data_out, const Context *context)
unique_id_type unique_id() const
Definition: dof_object.h:649
static T unpack(BufferIter in, Context *ctx)
processor_id_type processor_id()
Definition: libmesh_base.h:96
uint8_t unique_id_type
Definition: id_types.h:79
processor_id_type processor_id() const
uint8_t dof_id_type
Definition: id_types.h:64
processor_id_type processor_id() const
Definition: dof_object.h:694
processor_id_type n_processors()
Definition: libmesh_base.h:88