parallel_node.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2014 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/mesh_base.h"
25 #include "libmesh/node.h"
26 #include "libmesh/parallel.h"
27 #include "libmesh/parallel_mesh.h"
28 
29 // Helper functions in anonymous namespace
30 
31 namespace
32 {
33  using namespace libMesh;
34 
35 #ifdef LIBMESH_ENABLE_UNIQUE_ID
36  static const unsigned int header_size = 3;
37 #else
38  static const unsigned int header_size = 2;
39 #endif
40 
41  // use "(a+b-1)/b" trick to get a/b to round up
42  static const unsigned int idtypes_per_Real =
43  (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
44 
45  static const largest_id_type node_magic_header = 1234567890;
46 }
47 
48 
49 namespace libMesh
50 {
51 
52 #ifdef LIBMESH_HAVE_MPI
53 
54 namespace Parallel
55 {
56 
57 template <>
58 unsigned int packable_size (const Node* node, const MeshBase* mesh)
59 {
60  return
61 #ifndef NDEBUG
62  1 + // add an int for the magic header when testing
63 #endif
64  header_size + LIBMESH_DIM*idtypes_per_Real +
65  node->packed_indexing_size() +
66  1 + mesh->boundary_info->n_boundary_ids(node);
67 }
68 
69 
70 
71 template <>
72 unsigned int packed_size (const Node*,
73  const std::vector<largest_id_type>::const_iterator in)
74 {
75  const unsigned int pre_indexing_size =
76 #ifndef NDEBUG
77  1 + // add an int for the magic header when testing
78 #endif
79  header_size + LIBMESH_DIM*idtypes_per_Real;
80 
81  const unsigned int indexing_size =
82  DofObject::unpackable_indexing_size(in+pre_indexing_size);
83 
84  const int n_bcs =
85  *(in + pre_indexing_size + indexing_size);
86  libmesh_assert_greater_equal (n_bcs, 0);
87 
88  return pre_indexing_size + indexing_size + 1 + n_bcs;
89 }
90 
91 
92 
93 template <>
94 unsigned int packed_size (const Node* n,
95  const std::vector<largest_id_type>::iterator in)
96 {
97  return packed_size(n, std::vector<largest_id_type>::const_iterator(in));
98 }
99 
100 
101 
102 template <>
103 unsigned int packable_size (const Node* node, const ParallelMesh* mesh)
104 {
105  return packable_size(node, static_cast<const MeshBase*>(mesh));
106 }
107 
108 
109 
110 template <>
111 void pack (const Node* node,
112  std::vector<largest_id_type>& data,
113  const MeshBase* mesh)
114 {
115  libmesh_assert(node);
116 
117  // This should be redundant when used with Parallel::pack_range()
118  // data.reserve (data.size() + Parallel::packable_size(node, mesh));
119 
120 #ifndef NDEBUG
121  data.push_back (node_magic_header);
122 #endif
123 
124  data.push_back (static_cast<largest_id_type>(node->processor_id()));
125  data.push_back (static_cast<largest_id_type>(node->id()));
126 
127 #ifdef LIBMESH_ENABLE_UNIQUE_ID
128  if (node->valid_unique_id())
129  data.push_back (static_cast<largest_id_type>(node->unique_id()));
130  else
131  // OK to send invalid unique id, we must not own this DOF
132  data.push_back (static_cast<largest_id_type>(DofObject::invalid_unique_id));
133 #endif
134 
135  // use "(a+b-1)/b" trick to get a/b to round up
136  static const unsigned int idtypes_per_Real =
137  (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
138 
139  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
140  {
141  const largest_id_type* Real_as_idtypes =
142  reinterpret_cast<const largest_id_type*>(&((*node)(i)));
143  for (unsigned int j=0; j != idtypes_per_Real; ++j)
144  {
145  data.push_back(Real_as_idtypes[j]);
146  }
147  }
148 
149 #ifndef NDEBUG
150  const std::size_t start_indices = data.size();
151 #endif
152  // Add any DofObject indices
153  node->pack_indexing(std::back_inserter(data));
154 
157  start_indices));
158 
159  libmesh_assert_equal_to (node->packed_indexing_size(),
160  data.size() - start_indices);
161 
162  // Add any nodal boundary condition ids
163  std::vector<boundary_id_type> bcs =
164  mesh->boundary_info->boundary_ids(node);
165 
167 
168  data.push_back(bcs.size());
169 
170  for (std::size_t bc_it=0; bc_it < bcs.size(); bc_it++)
171  data.push_back(bcs[bc_it]);
172 }
173 
174 
175 
176 template <>
177 void pack (const Node* node,
178  std::vector<largest_id_type>& data,
179  const ParallelMesh* mesh)
180 {
181  pack(node, data, static_cast<const MeshBase*>(mesh));
182 }
183 
184 
185 
186 template <>
187 void unpack (std::vector<largest_id_type>::const_iterator in,
188  Node** out,
189  MeshBase* mesh)
190 {
191 #ifndef NDEBUG
192  const std::vector<largest_id_type>::const_iterator original_in = in;
193  const largest_id_type incoming_header = *in++;
194  libmesh_assert_equal_to (incoming_header, node_magic_header);
195 #endif
196 
197  const processor_id_type processor_id = static_cast<processor_id_type>(*in++);
199  processor_id < mesh->n_processors());
200 
201  const dof_id_type id = static_cast<dof_id_type>(*in++);
202 
203 #ifdef LIBMESH_ENABLE_UNIQUE_ID
204  const unique_id_type unique_id = static_cast<unique_id_type>(*in++);
205 #endif
206 
207  Node *node = mesh->query_node_ptr(id);
208 
209  if (node)
210  {
211  libmesh_assert_equal_to (node->processor_id(), processor_id);
212 
213  // We currently don't communicate mesh motion via packed Nodes,
214  // so it should be safe to assume (and assert) that Node
215  // locations are consistent between processors
216 #ifndef NDEBUG
217  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
218  {
219  const Real* idtypes_as_Real = reinterpret_cast<const Real*>(&(*in));
220  libmesh_assert_equal_to ((*node)(i), *idtypes_as_Real);
221  in += idtypes_per_Real;
222  }
223 #else
224  in += LIBMESH_DIM * idtypes_per_Real;
225 #endif // !NDEBUG
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  *out = node;
242  }
243  else
244  {
245  // If we don't already have it, we need to allocate it
246  node = new Node();
247 
248  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
249  {
250  const Real* idtypes_as_Real = reinterpret_cast<const Real*>(&(*in));
251  (*node)(i) = *idtypes_as_Real;
252  in += idtypes_per_Real;
253  }
254 
255  node->set_id() = id;
256 #ifdef LIBMESH_ENABLE_UNIQUE_ID
257  node->set_unique_id() = unique_id;
258 #endif
259  node->processor_id() = processor_id;
260 
261  node->unpack_indexing(in);
262  libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
263  node->packed_indexing_size());
264  in += node->packed_indexing_size();
265  }
266 
267  // FIXME: We should add some debug mode tests to ensure that the
268  // encoded boundary conditions are consistent
269 
270  // Add any nodal boundary condition ids
271  const largest_id_type num_bcs = *in++;
272  // libmesh_assert_greater_equal (num_bcs, 0);
273 
274  for(largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
275  mesh->boundary_info->add_node (node, *in++);
276 
277  *out = node;
278 
279 #ifndef NDEBUG
280  libmesh_assert (in - original_in ==
281  static_cast<int>
282  (Parallel::packed_size(node, original_in)));
283 #endif
284 }
285 
286 
287 
288 template <>
289 void unpack (std::vector<largest_id_type>::const_iterator in,
290  Node** out,
292 {
293  unpack(in, out, static_cast<MeshBase*>(mesh));
294 }
295 
296 } // namespace Parallel
297 
298 #endif // #ifdef LIBMESH_HAVE_MPI
299 
300 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:06 UTC

Hosted By:
SourceForge.net Logo