parallel_node.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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"
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() +
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 
176  libmesh_assert(bcs.size() < std::numeric_limits<largest_id_type>::max());
177 
178  *data_out++ =(bcs.size());
179 
180  for (const auto & bid : bcs)
181  *data_out++ = bid;
182 }
183 
184 
185 
186 template <>
187 template <>
188 void
189 Packing<const Node *>::pack (const Node * const & node,
190  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
191  const DistributedMesh * mesh)
192 {
193  pack(node, data_out, static_cast<const MeshBase*>(mesh));
194 }
195 
196 
197 
198 template <>
199 template <>
200 void
201 Packing<const Node *>::pack (const Node * const & node,
202  std::back_insert_iterator<std::vector<largest_id_type>> data_out,
203  const ParallelMesh * mesh)
204 {
205  pack(node, data_out, static_cast<const MeshBase*>(mesh));
206 }
207 
208 
209 
210 template <>
211 template <>
212 Node *
213 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
214  MeshBase * mesh)
215 {
216 #ifndef NDEBUG
217  const std::vector<largest_id_type>::const_iterator original_in = in;
218  const largest_id_type incoming_header = *in++;
219  libmesh_assert_equal_to (incoming_header, node_magic_header);
220 #endif
221 
222  const processor_id_type processor_id = cast_int<processor_id_type>(*in++);
223  libmesh_assert(processor_id == DofObject::invalid_processor_id ||
224  processor_id < mesh->n_processors());
225 
226  const dof_id_type id = cast_int<dof_id_type>(*in++);
227 
228 #ifdef LIBMESH_ENABLE_UNIQUE_ID
229  const unique_id_type unique_id = cast_int<unique_id_type>(*in++);
230 #endif
231 
232  Node * node = mesh->query_node_ptr(id);
233 
234  if (node)
235  {
236  libmesh_assert_equal_to (node->processor_id(), processor_id);
237 
238  // We currently don't communicate mesh motion via packed Nodes,
239  // so it should usually be safe to assume (and assert) that Node
240  // locations are consistent between processors.
241  //
242  // There may be exceptions due to rounding in file I/O, so we'll
243  // only assert equality to within a tight tolerance, and we'll
244  // believe the sender's node locations over our own if we don't
245  // own the node.
246  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
247  {
248  const Real & idtypes_as_Real = *(reinterpret_cast<const Real *>(&(*in)));
249  libmesh_assert_less_equal ((*node)(i), idtypes_as_Real + (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
250  libmesh_assert_greater_equal ((*node)(i), idtypes_as_Real - (std::max(Real(1),idtypes_as_Real)*TOLERANCE*TOLERANCE));
251 
252  if (processor_id != mesh->processor_id())
253  (*node)(i) = idtypes_as_Real;
254  in += idtypes_per_Real;
255  }
256 
257  if (!node->has_dofs())
258  {
259  node->unpack_indexing(in);
260  libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
261  node->packed_indexing_size());
262  in += node->packed_indexing_size();
263  }
264  else
265  {
266  // FIXME: We should add some debug mode tests to ensure that
267  // the encoded indexing is consistent
269  }
270  }
271  else
272  {
273  // If we don't already have it, we need to allocate it
274  node = new Node();
275 
276  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
277  {
278  const Real * idtypes_as_Real = reinterpret_cast<const Real *>(&(*in));
279  (*node)(i) = *idtypes_as_Real;
280  in += idtypes_per_Real;
281  }
282 
283  node->set_id() = id;
284 #ifdef LIBMESH_ENABLE_UNIQUE_ID
285  node->set_unique_id() = unique_id;
286 #endif
287  node->processor_id() = processor_id;
288 
289  node->unpack_indexing(in);
290  libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
291  node->packed_indexing_size());
292  in += node->packed_indexing_size();
293  }
294 
295  // FIXME: We should add some debug mode tests to ensure that the
296  // encoded boundary conditions are consistent
297 
298  // Add any nodal boundary condition ids
299  const largest_id_type num_bcs = *in++;
300  // libmesh_assert_greater_equal (num_bcs, 0);
301 
302  for (largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
304  (node, cast_int<boundary_id_type>(*in++));
305 
306 #ifndef NDEBUG
307  libmesh_assert (in - original_in ==
308  cast_int<int>
310 #endif
311 
312  return node;
313 }
314 
315 
316 
317 template <>
318 template <>
319 Node *
320 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
322 {
323  return unpack(in, static_cast<MeshBase*>(mesh));
324 }
325 
326 
327 
328 template <>
329 template <>
330 Node *
331 Packing<Node *>::unpack (std::vector<largest_id_type>::const_iterator in,
332  ParallelMesh * mesh)
333 {
334  return unpack(in, static_cast<MeshBase*>(mesh));
335 }
336 
337 } // namespace Parallel
338 
339 } // namespace libMesh
A geometric point in (x,y,z) space associated with a DOF.
Definition: node.h:52
static unsigned int unpackable_indexing_size(std::vector< largest_id_type >::const_iterator begin)
Definition: dof_object.C:461
MeshBase & mesh
uint64_t largest_id_type
Definition: id_types.h:139
uint8_t processor_id_type
Definition: id_types.h:99
unique_id_type unique_id() const
Definition: dof_object.h:672
static const Real TOLERANCE
const BoundaryInfo & get_boundary_info() const
Definition: mesh_base.h:131
long double max(long double a, double b)
Base class for Mesh.
Definition: mesh_base.h:77
std::size_t n_boundary_ids() const
std::vector< boundary_id_type > boundary_ids(const Node *node) const
void add_node(const Node *node, const boundary_id_type id)
dof_id_type id() const
Definition: dof_object.h:655
static const unique_id_type invalid_unique_id
Definition: dof_object.h:352
static const processor_id_type invalid_processor_id
Definition: dof_object.h:358
virtual const Node * query_node_ptr(const dof_id_type i) const =0
bool valid_unique_id() const
Definition: dof_object.h:705
Mesh data structure which is distributed across all processors.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
unsigned int packed_indexing_size() const
Definition: dof_object.C:445
void pack_indexing(std::back_insert_iterator< std::vector< largest_id_type >> target) const
Definition: dof_object.C:520
static unsigned int packable_size(const T &object, const Context *context)
static unsigned int packed_size(BufferIter iter)
static void pack(const T &object, OutputIter data_out, const Context *context)
processor_id_type processor_id() const
processor_id_type processor_id() const
Definition: dof_object.h:717
static T unpack(BufferIter in, Context *ctx)
uint8_t unique_id_type
Definition: id_types.h:79
uint8_t dof_id_type
Definition: id_types.h:64