parallel_node.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // C++ includes 00021 00022 // Local includes 00023 #include "libmesh/boundary_info.h" 00024 #include "libmesh/mesh_base.h" 00025 #include "libmesh/node.h" 00026 #include "libmesh/parallel.h" 00027 #include "libmesh/parallel_mesh.h" 00028 00029 // Helper functions in anonymous namespace 00030 00031 namespace 00032 { 00033 using namespace libMesh; 00034 00035 static const unsigned int header_size = 2; 00036 00037 // use "(a+b-1)/b" trick to get a/b to round up 00038 static const unsigned int ints_per_Real = 00039 (sizeof(Real) + sizeof(int) - 1) / sizeof(int); 00040 00041 static const int node_magic_header = 1234567890; 00042 } 00043 00044 00045 namespace libMesh 00046 { 00047 00048 #ifdef LIBMESH_HAVE_MPI 00049 00050 namespace Parallel 00051 { 00052 00053 template <> 00054 unsigned int packable_size (const Node* node, const MeshBase* mesh) 00055 { 00056 return 00057 #ifndef NDEBUG 00058 1 + // add an int for the magic header when testing 00059 #endif 00060 header_size + LIBMESH_DIM*ints_per_Real + 00061 node->packed_indexing_size() + 00062 1 + mesh->boundary_info->n_boundary_ids(node); 00063 } 00064 00065 00066 00067 template <> 00068 unsigned int packed_size (const Node*, 00069 std::vector<int>::const_iterator in) 00070 { 00071 const unsigned int pre_indexing_size = 00072 #ifndef NDEBUG 00073 1 + // add an int for the magic header when testing 00074 #endif 00075 header_size + LIBMESH_DIM*ints_per_Real; 00076 00077 const unsigned int indexing_size = 00078 DofObject::unpackable_indexing_size(in+pre_indexing_size); 00079 00080 const int n_bcs = 00081 *(in + pre_indexing_size + indexing_size); 00082 libmesh_assert_greater_equal (n_bcs, 0); 00083 00084 return pre_indexing_size + indexing_size + 1 + n_bcs; 00085 } 00086 00087 00088 00089 template <> 00090 unsigned int packable_size (const Node* node, const ParallelMesh* mesh) 00091 { 00092 return packable_size(node, static_cast<const MeshBase*>(mesh)); 00093 } 00094 00095 00096 00097 template <> 00098 void pack (const Node* node, 00099 std::vector<int>& data, 00100 const MeshBase* mesh) 00101 { 00102 libmesh_assert(node); 00103 00104 // This should be redundant when used with Parallel::pack_range() 00105 // data.reserve (data.size() + Parallel::packable_size(node, mesh)); 00106 00107 #ifndef NDEBUG 00108 data.push_back (node_magic_header); 00109 #endif 00110 00111 data.push_back (static_cast<int>(node->processor_id())); 00112 data.push_back (static_cast<int>(node->id())); 00113 00114 // use "(a+b-1)/b" trick to get a/b to round up 00115 static const unsigned int ints_per_Real = 00116 (sizeof(Real) + sizeof(int) - 1) / sizeof(int); 00117 00118 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00119 { 00120 const int* Real_as_ints = reinterpret_cast<const int*>(&((*node)(i))); 00121 for (unsigned int j=0; j != ints_per_Real; ++j) 00122 { 00123 data.push_back(Real_as_ints[j]); 00124 } 00125 } 00126 00127 #ifndef NDEBUG 00128 const int start_indices = data.size(); 00129 #endif 00130 // Add any DofObject indices 00131 node->pack_indexing(std::back_inserter(data)); 00132 00133 libmesh_assert(node->packed_indexing_size() == 00134 DofObject::unpackable_indexing_size(data.begin() + 00135 start_indices)); 00136 00137 libmesh_assert_equal_to (node->packed_indexing_size(), 00138 data.size() - start_indices); 00139 00140 // Add any nodal boundary condition ids 00141 std::vector<boundary_id_type> bcs = 00142 mesh->boundary_info->boundary_ids(node); 00143 00144 data.push_back(bcs.size()); 00145 00146 for(unsigned int bc_it=0; bc_it < bcs.size(); bc_it++) 00147 data.push_back(bcs[bc_it]); 00148 } 00149 00150 00151 00152 template <> 00153 void pack (const Node* node, 00154 std::vector<int>& data, 00155 const ParallelMesh* mesh) 00156 { 00157 pack(node, data, static_cast<const MeshBase*>(mesh)); 00158 } 00159 00160 00161 00162 template <> 00163 void unpack (std::vector<int>::const_iterator in, 00164 Node** out, 00165 MeshBase* mesh) 00166 { 00167 #ifndef NDEBUG 00168 const std::vector<int>::const_iterator original_in = in; 00169 const int incoming_header = *in++; 00170 libmesh_assert_equal_to (incoming_header, node_magic_header); 00171 #endif 00172 00173 const unsigned int processor_id = static_cast<unsigned int>(*in++); 00174 libmesh_assert(processor_id == DofObject::invalid_processor_id || 00175 processor_id < libMesh::n_processors()); 00176 00177 const unsigned int id = static_cast<unsigned int>(*in++); 00178 00179 Node *node = mesh->query_node_ptr(id); 00180 00181 if (node) 00182 { 00183 libmesh_assert_equal_to (node->processor_id(), processor_id); 00184 00185 // We currently don't communicate mesh motion via packed Nodes, 00186 // so it should be safe to assume (and assert) that Node 00187 // locations are consistent between processors 00188 #ifndef NDEBUG 00189 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00190 { 00191 const Real* ints_as_Real = reinterpret_cast<const Real*>(&(*in)); 00192 libmesh_assert_equal_to ((*node)(i), *ints_as_Real); 00193 in += ints_per_Real; 00194 } 00195 #else 00196 in += LIBMESH_DIM * ints_per_Real; 00197 #endif // !NDEBUG 00198 00199 if (!node->has_dofs()) 00200 { 00201 node->unpack_indexing(in); 00202 libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in), 00203 node->packed_indexing_size()); 00204 in += node->packed_indexing_size(); 00205 } 00206 else 00207 { 00208 // FIXME: We should add some debug mode tests to ensure that 00209 // the encoded indexing is consistent 00210 in += DofObject::unpackable_indexing_size(in); 00211 } 00212 00213 *out = node; 00214 } 00215 else 00216 { 00217 // If we don't already have it, we need to allocate it 00218 node = new Node(); 00219 00220 for (unsigned int i=0; i != LIBMESH_DIM; ++i) 00221 { 00222 const Real* ints_as_Real = reinterpret_cast<const Real*>(&(*in)); 00223 (*node)(i) = *ints_as_Real; 00224 in += ints_per_Real; 00225 } 00226 00227 node->set_id() = id; 00228 node->processor_id() = processor_id; 00229 00230 node->unpack_indexing(in); 00231 libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in), 00232 node->packed_indexing_size()); 00233 in += node->packed_indexing_size(); 00234 } 00235 00236 // FIXME: We should add some debug mode tests to ensure that the 00237 // encoded boundary conditions are consistent 00238 00239 // Add any nodal boundary condition ids 00240 const int num_bcs = *in++; 00241 libmesh_assert_greater_equal (num_bcs, 0); 00242 00243 for(int bc_it=0; bc_it < num_bcs; bc_it++) 00244 mesh->boundary_info->add_node (node, *in++); 00245 00246 *out = node; 00247 00248 #ifndef NDEBUG 00249 libmesh_assert (in - original_in == 00250 static_cast<int> 00251 (Parallel::packed_size(node, original_in))); 00252 #endif 00253 } 00254 00255 00256 00257 template <> 00258 void unpack (std::vector<int>::const_iterator in, 00259 Node** out, 00260 ParallelMesh* mesh) 00261 { 00262 unpack(in, out, static_cast<MeshBase*>(mesh)); 00263 } 00264 00265 } // namespace Parallel 00266 00267 #endif // #ifdef LIBMESH_HAVE_MPI 00268 00269 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: