$extrastylesheet
libMesh::Parallel Namespace Reference

Namespaces

namespace  Utils

Classes

class  DataPlusInt
struct  data_type
struct  request
struct  status
class  MessageTag
class  DataType
struct  false_type
struct  dependent_false
class  StandardType
struct  Attributes
class  Status
struct  PostWaitWork
class  Request
struct  BufferType< T * >
class  Communicator
class  FakeCommunicator
struct  PostWaitCopyBuffer
struct  PostWaitUnpackBuffer
struct  PostWaitDeleteBuffer
class  StandardType< TypeVector< T > >
class  StandardType< VectorValue< T > >
class  StandardType< Point >
class  StandardType< TypeTensor< T > >
class  StandardType< TensorValue< T > >
class  BinSorter
struct  BufferType< const Elem * >
struct  BufferType< Elem >
class  StandardType< Hilbert::HilbertIndices >
class  Histogram
class  StandardType< std::pair< T1, T2 > >
class  StandardType< std::complex< T > >
struct  BufferType< const Node * >
struct  BufferType< Node >
class  Sort

Typedefs

typedef MPI_Datatype data_type
typedef MPI_Request request
typedef MPI_Status status
typedef MPI_Comm communicator

Functions

template<>
unsigned int packed_size (const Elem *, std::vector< largest_id_type >::const_iterator in)
template<>
unsigned int packed_size (const Elem *e, std::vector< largest_id_type >::iterator in)
template<>
unsigned int packable_size (const Elem *elem, const MeshBase *mesh)
template<>
unsigned int packable_size (const Elem *elem, const ParallelMesh *mesh)
template<>
void pack (const Elem *elem, std::vector< largest_id_type > &data, const MeshBase *mesh)
template<>
void pack (const Elem *elem, std::vector< largest_id_type > &data, const ParallelMesh *mesh)
template<>
void unpack (std::vector< largest_id_type >::const_iterator in, Elem **out, MeshBase *mesh)
template<>
void unpack (std::vector< largest_id_type >::const_iterator in, Elem **out, ParallelMesh *mesh)
template<>
unsigned int packable_size (const Node *node, const MeshBase *mesh)
template<>
unsigned int packed_size (const Node *, const std::vector< largest_id_type >::const_iterator in)
template<>
unsigned int packed_size (const Node *n, const std::vector< largest_id_type >::iterator in)
template<>
unsigned int packable_size (const Node *node, const ParallelMesh *mesh)
template<>
void pack (const Node *node, std::vector< largest_id_type > &data, const MeshBase *mesh)
template<>
void pack (const Node *node, std::vector< largest_id_type > &data, const ParallelMesh *mesh)
template<>
void unpack (std::vector< largest_id_type >::const_iterator in, Node **out, MeshBase *mesh)
template<>
void unpack (std::vector< largest_id_type >::const_iterator in, Node **out, ParallelMesh *mesh)
template<typename T >
data_type dataplusint_type ()
Status wait (Request &r)
void wait (std::vector< Request > &r)
template<typename T , typename buffertype , typename Context >
void pack (const T *object, typename std::vector< buffertype > &data, const Context *context)
template<typename T , typename Context >
unsigned int packable_size (const T *, const Context *)
template<typename T , typename BufferIter >
unsigned int packed_size (const T *, BufferIter)
template<typename T , typename BufferIter , typename Context >
void unpack (BufferIter in, T **out, Context *ctx)
template<typename Context , typename buffertype , typename OutputIter >
void unpack_range (const typename std::vector< buffertype > &buffer, Context *context, OutputIter out)
template<typename Context , typename buffertype , typename Iter >
Iter pack_range (const Context *context, Iter range_begin, const Iter range_end, typename std::vector< buffertype > &buffer)
template<typename Context , typename Iter >
std::size_t packed_range_size (const Context *context, Iter range_begin, const Iter range_end)
template<typename Iterator , typename DofObjType , typename SyncFunctor >
void sync_dofobject_data_by_xyz (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, LocationMap< DofObjType > *location_map, SyncFunctor &sync)
template<typename Iterator , typename SyncFunctor >
void sync_dofobject_data_by_id (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
template<typename Iterator , typename SyncFunctor >
void sync_element_data_by_parent_id (MeshBase &mesh, const Iterator &range_begin, const Iterator &range_end, SyncFunctor &sync)
template<typename SyncFunctor >
void sync_node_data_by_element_id (MeshBase &mesh, const MeshBase::const_element_iterator &range_begin, const MeshBase::const_element_iterator &range_end, SyncFunctor &sync)
template<typename Iterator , typename DofObjType , typename SyncFunctor >
void sync_dofobject_data_by_xyz (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, LocationMap< DofObjType > &location_map, SyncFunctor &sync)
 INT_TYPE (char, MPI_CHAR)
 INT_TYPE (signed char, MPI_SIGNED_CHAR)
 INT_TYPE (unsigned char, MPI_UNSIGNED_CHAR)
 INT_TYPE (short int, MPI_SHORT)
 INT_TYPE (unsigned short int, MPI_UNSIGNED_SHORT)
 INT_TYPE (int, MPI_INT)
 INT_TYPE (unsigned int, MPI_UNSIGNED)
 INT_TYPE (long, MPI_LONG)
 INT_TYPE (unsigned long, MPI_UNSIGNED_LONG)
 INT_TYPE (unsigned long long, MPI_LONG_LONG_INT)
 FLOAT_TYPE (float, MPI_FLOAT)
 FLOAT_TYPE (double, MPI_DOUBLE)
 FLOAT_TYPE (long double, MPI_LONG_DOUBLE)
 CONTAINER_TYPE (std::set)
 CONTAINER_TYPE (std::vector)
template<typename Context , typename buffertype , typename OutputIter >
void unpack_range (const std::vector< buffertype > &buffer, Context *context, OutputIter out)
void barrier (const Communicator &comm=Communicator_World)
template<typename T >
bool verify (const T &r, const Communicator &comm=Communicator_World)
template<typename T >
void min (T &r, const Communicator &comm=Communicator_World)
template<typename T , typename U >
void minloc (T &r, U &min_id, const Communicator &comm=Communicator_World)
template<typename T >
void max (T &r, const Communicator &comm=Communicator_World)
template<typename T , typename U >
void maxloc (T &r, U &max_id, const Communicator &comm=Communicator_World)
template<typename T >
void sum (T &r, const Communicator &comm=Communicator_World)
template<typename T >
void set_union (T &data, const unsigned int root_id, const Communicator &comm=Communicator_World)
template<typename T >
void set_union (T &data, const Communicator &comm=Communicator_World)
status probe (const unsigned int src_processor_id, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void send (const unsigned int dest_processor_id, T &data, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
void send (const unsigned int dest_processor_id, T &data, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
void send (const unsigned int dest_processor_id, T &data, const DataType &type, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
void send (const unsigned int dest_processor_id, T &data, const DataType &type, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename Context , typename Iter >
void send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename Context , typename Iter >
void send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
void nonblocking_send (const unsigned int dest_processor_id, T &buf, const DataType &type, Request &r, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
void nonblocking_send (const unsigned int dest_processor_id, T &buf, Request &r, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename T >
Status receive (const unsigned int src_processor_id, T &buf, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void receive (const unsigned int src_processor_id, T &buf, Request &req, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
Status receive (const unsigned int src_processor_id, T &buf, const DataType &type, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void receive (const unsigned int src_processor_id, T &buf, const DataType &type, Request &req, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename Context , typename OutputIter >
void receive_packed_range (const unsigned int src_processor_id, Context *context, OutputIter out, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void nonblocking_receive (const unsigned int src_processor_id, T &buf, const DataType &type, Request &r, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void nonblocking_receive (const unsigned int src_processor_id, T &buf, Request &r, const MessageTag &tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, T1 &send, const unsigned int source_processor_id, T2 &recv, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, const Communicator &comm=Communicator_World)
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter >
void send_receive_packed_range (const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, T1 &send, const DataType &type1, const unsigned int source_processor_id, T2 &recv, const DataType &type2, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, const Communicator &comm=Communicator_World)
template<typename T >
void gather (const unsigned int root_id, T send, std::vector< T > &recv, const Communicator &comm=Communicator_World)
template<typename T >
void gather (const unsigned int root_id, std::vector< T > &r, const Communicator &comm=Communicator_World)
template<typename T >
void allgather (T send, std::vector< T > &recv, const Communicator &comm=Communicator_World)
template<typename T >
void allgather (std::vector< T > &r, const bool identical_buffer_sizes=false, const Communicator &comm=Communicator_World)
template<typename Context , typename Iter , typename OutputIter >
void gather_packed_range (const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out, const Communicator &comm=Communicator_World)
template<typename Context , typename Iter , typename OutputIter >
void allgather_packed_range (Context *context, Iter range_begin, const Iter range_end, OutputIter out, const Communicator &comm=Communicator_World)
template<typename T >
void alltoall (std::vector< T > &r, const Communicator &comm=Communicator_World)
template<typename T >
void broadcast (T &data, const unsigned int root_id=0, const Communicator &comm=Communicator_World)
template<typename Context , typename OutputContext , typename Iter , typename OutputIter >
void broadcast_packed_range (const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out, const unsigned int root_id=0, const Communicator &comm=Communicator_World)
template<>
data_type dataplusint_type< short int > ()
template<>
data_type dataplusint_type< int > ()
template<>
data_type dataplusint_type< long > ()
template<>
data_type dataplusint_type< float > ()
template<>
data_type dataplusint_type< double > ()
template<>
data_type dataplusint_type< long double > ()

Variables

const unsigned int any_source
const MessageTag any_tag = MessageTag(MPI_ANY_TAG)
const MessageTag no_tag = MessageTag(0)
FakeCommunicatorCommunicator_World = CommWorld

Detailed Description

The Parallel namespace is for wrapper functions for common general parallel synchronization tasks.

For MPI 1.1 compatibility, temporary buffers are used instead of MPI 2's MPI_IN_PLACE


Typedef Documentation

Communicator object for talking with subsets of processors

Definition at line 127 of file parallel.h.

typedef MPI_Datatype libMesh::Parallel::data_type

Data types for communication

Definition at line 105 of file parallel.h.

typedef MPI_Request libMesh::Parallel::request

Request object for non-blocking I/O

Definition at line 117 of file parallel.h.

typedef MPI_Status libMesh::Parallel::status

Status object for querying messages

Definition at line 122 of file parallel.h.


Function Documentation

template<typename T >
void libMesh::Parallel::allgather ( send,
std::vector< T > &  recv,
const Communicator &  comm = Communicator_World 
) [inline]
template<typename T >
void libMesh::Parallel::allgather ( std::vector< T > &  r,
const bool  identical_buffer_sizes = false,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1098 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::allgather().

{ comm.allgather(r, identical_buffer_sizes); }
template<typename Context , typename Iter , typename OutputIter >
void libMesh::Parallel::allgather_packed_range ( Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1113 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::allgather_packed_range().

{ comm.allgather_packed_range(context, range_begin, range_end, out); }
template<typename T >
void libMesh::Parallel::alltoall ( std::vector< T > &  r,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1121 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::alltoall().

{ comm.alltoall(r); }
void libMesh::Parallel::barrier ( const Communicator &  comm = Communicator_World) [inline]

Definition at line 851 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::barrier().

{
  comm.barrier();
}
template<typename T >
void libMesh::Parallel::broadcast ( T &  data,
const unsigned int  root_id = 0,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1126 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::broadcast().

Referenced by libMesh::Parallel::Communicator::broadcast_packed_range().

{ comm.broadcast(data, root_id); }
template<typename Context , typename OutputContext , typename Iter , typename OutputIter >
void libMesh::Parallel::broadcast_packed_range ( const Context *  context1,
Iter  range_begin,
const Iter  range_end,
OutputContext *  context2,
OutputIter  out,
const unsigned int  root_id = 0,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1131 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::broadcast_packed_range().

{ comm.broadcast_packed_range(context1, range_begin, range_end, context2, out, root_id); }
template<typename T >
data_type libMesh::Parallel::dataplusint_type ( ) [inline]

Templated function to return the appropriate MPI datatype for use with built-in C types when combined with an int

template<>
data_type libMesh::Parallel::dataplusint_type< double > ( ) [inline]

Definition at line 1224 of file parallel_implementation.h.

{ return MPI_DOUBLE_INT; }
template<>
data_type libMesh::Parallel::dataplusint_type< float > ( ) [inline]

Definition at line 1221 of file parallel_implementation.h.

{ return MPI_FLOAT_INT; }
template<>
data_type libMesh::Parallel::dataplusint_type< int > ( ) [inline]

Definition at line 1215 of file parallel_implementation.h.

{ return MPI_2INT; }
template<>
data_type libMesh::Parallel::dataplusint_type< long > ( ) [inline]

Definition at line 1218 of file parallel_implementation.h.

{ return MPI_LONG_INT; }
template<>
data_type libMesh::Parallel::dataplusint_type< long double > ( ) [inline]

Definition at line 1227 of file parallel_implementation.h.

{ return MPI_LONG_DOUBLE_INT; }
template<>
data_type libMesh::Parallel::dataplusint_type< short int > ( ) [inline]

Definition at line 1212 of file parallel_implementation.h.

{ return MPI_SHORT_INT; }
libMesh::Parallel::FLOAT_TYPE ( float  ,
MPI_FLOAT   
)
libMesh::Parallel::FLOAT_TYPE ( double  ,
MPI_DOUBLE   
)
libMesh::Parallel::FLOAT_TYPE ( long  double,
MPI_LONG_DOUBLE   
)
template<typename T >
void libMesh::Parallel::gather ( const unsigned int  root_id,
send,
std::vector< T > &  recv,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1079 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::gather().

Referenced by libMesh::Parallel::Communicator::gather_packed_range().

{ comm.gather(root_id, send, recv); }
template<typename T >
void libMesh::Parallel::gather ( const unsigned int  root_id,
std::vector< T > &  r,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1086 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::gather().

{ comm.gather(root_id, r); }
template<typename Context , typename Iter , typename OutputIter >
void libMesh::Parallel::gather_packed_range ( const unsigned int  root_id,
Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1104 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::gather_packed_range().

{ comm.gather_packed_range(root_id, context, range_begin, range_end, out); }
libMesh::Parallel::INT_TYPE ( char  ,
MPI_CHAR   
)
libMesh::Parallel::INT_TYPE ( signed  char,
MPI_SIGNED_CHAR   
)
libMesh::Parallel::INT_TYPE ( unsigned  char,
MPI_UNSIGNED_CHAR   
)
libMesh::Parallel::INT_TYPE ( short  int,
MPI_SHORT   
)
libMesh::Parallel::INT_TYPE ( unsigned short  int,
MPI_UNSIGNED_SHORT   
)
libMesh::Parallel::INT_TYPE ( int  ,
MPI_INT   
)
libMesh::Parallel::INT_TYPE ( unsigned  int,
MPI_UNSIGNED   
)
libMesh::Parallel::INT_TYPE ( long  ,
MPI_LONG   
)
libMesh::Parallel::INT_TYPE ( unsigned  long,
MPI_UNSIGNED_LONG   
)
libMesh::Parallel::INT_TYPE ( unsigned long  long,
MPI_LONG_LONG_INT   
)
template<typename T >
void libMesh::Parallel::max ( T &  r,
const Communicator &  comm = Communicator_World 
) [inline]
template<typename T , typename U >
void libMesh::Parallel::maxloc ( T &  r,
U &  max_id,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 878 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::maxloc().

{ comm.maxloc(r, max_id); }
template<typename T >
void libMesh::Parallel::min ( T &  r,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 862 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::min().

{ comm.min(r); }
template<typename T , typename U >
void libMesh::Parallel::minloc ( T &  r,
U &  min_id,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 867 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::minloc().

{ comm.minloc(r, min_id); }
template<typename T >
void libMesh::Parallel::nonblocking_receive ( const unsigned int  src_processor_id,
T &  buf,
const DataType &  type,
Request &  r,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1024 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ comm.receive (src_processor_id, buf, type, r, tag); }
template<typename T >
void libMesh::Parallel::nonblocking_receive ( const unsigned int  src_processor_id,
T &  buf,
Request &  r,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1033 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ comm.receive (src_processor_id, buf, r, tag); }
template<typename T >
void libMesh::Parallel::nonblocking_send ( const unsigned int  dest_processor_id,
T &  buf,
const DataType &  type,
Request &  r,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 958 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send (dest_processor_id, buf, type, r, tag); }
template<typename T >
void libMesh::Parallel::nonblocking_send ( const unsigned int  dest_processor_id,
T &  buf,
Request &  r,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 967 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send (dest_processor_id, buf, r, tag); }
template<>
void libMesh::Parallel::pack ( const Node node,
std::vector< largest_id_type > &  data,
const MeshBase mesh 
)

Definition at line 111 of file parallel_node.C.

References libMesh::BoundaryInfo::boundary_ids(), libMesh::MeshBase::get_boundary_info(), libMesh::DofObject::id(), libMesh::DofObject::invalid_unique_id, libMesh::libmesh_assert(), max(), libMesh::DofObject::pack_indexing(), libMesh::DofObject::packed_indexing_size(), libMesh::DofObject::processor_id(), libMesh::Real, libMesh::DofObject::unique_id(), libMesh::DofObject::unpackable_indexing_size(), and libMesh::DofObject::valid_unique_id().

{
  libmesh_assert(node);

  // This should be redundant when used with Parallel::pack_range()
  // data.reserve (data.size() + Parallel::packable_size(node, mesh));

#ifndef NDEBUG
  data.push_back (node_magic_header);
#endif

  data.push_back (static_cast<largest_id_type>(node->processor_id()));
  data.push_back (static_cast<largest_id_type>(node->id()));

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  if (node->valid_unique_id())
    data.push_back (static_cast<largest_id_type>(node->unique_id()));
  else
    // OK to send invalid unique id, we must not own this DOF
    data.push_back (static_cast<largest_id_type>(DofObject::invalid_unique_id));
#endif

  // use "(a+b-1)/b" trick to get a/b to round up
  static const unsigned int idtypes_per_Real =
    (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);

  for (unsigned int i=0; i != LIBMESH_DIM; ++i)
    {
      const largest_id_type* Real_as_idtypes =
        reinterpret_cast<const largest_id_type*>(&((*node)(i)));
      for (unsigned int j=0; j != idtypes_per_Real; ++j)
        {
          data.push_back(Real_as_idtypes[j]);
        }
    }

#ifndef NDEBUG
  const std::size_t start_indices = data.size();
#endif
  // Add any DofObject indices
  node->pack_indexing(std::back_inserter(data));

  libmesh_assert(node->packed_indexing_size() ==
                 DofObject::unpackable_indexing_size(data.begin() +
                                                     start_indices));

  libmesh_assert_equal_to (node->packed_indexing_size(),
                           data.size() - start_indices);

  // Add any nodal boundary condition ids
  std::vector<boundary_id_type> bcs =
    mesh->get_boundary_info().boundary_ids(node);

  libmesh_assert(bcs.size() < std::numeric_limits<largest_id_type>::max());

  data.push_back(bcs.size());

  for (std::size_t bc_it=0; bc_it < bcs.size(); bc_it++)
    data.push_back(bcs[bc_it]);
}
template<>
void libMesh::Parallel::pack ( const Elem elem,
std::vector< largest_id_type > &  data,
const MeshBase mesh 
)

Definition at line 166 of file parallel_elem.C.

References libMesh::BoundaryInfo::boundary_ids(), libMesh::BoundaryInfo::edge_boundary_ids(), libMesh::MeshBase::get_boundary_info(), libMesh::DofObject::id(), libMesh::DofObject::invalid_unique_id, libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::n_edges(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor(), libMesh::Elem::node(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::DofObject::pack_indexing(), libMesh::DofObject::packed_indexing_size(), libMesh::Elem::parent(), libMesh::DofObject::processor_id(), libMesh::Elem::refinement_flag(), libMesh::Elem::subdomain_id(), libMesh::Elem::type(), libMesh::DofObject::unique_id(), libMesh::DofObject::unpackable_indexing_size(), libMesh::DofObject::valid_unique_id(), and libMesh::Elem::which_child_am_i().

Referenced by pack(), and pack_range().

{
  libmesh_assert(elem);

  // This should be redundant when used with Parallel::pack_range()
  // data.reserve (data.size() + Parallel::packable_size(elem, mesh));

#ifndef NDEBUG
  data.push_back (elem_magic_header);
#endif

#ifdef LIBMESH_ENABLE_AMR
  data.push_back (static_cast<largest_id_type>(elem->level()));
  data.push_back (static_cast<largest_id_type>(elem->p_level()));
  data.push_back (static_cast<largest_id_type>(elem->refinement_flag()));
  data.push_back (static_cast<largest_id_type>(elem->p_refinement_flag()));
#else
  data.push_back (0);
  data.push_back (0);
  data.push_back (0);
  data.push_back (0);
#endif
  data.push_back (static_cast<largest_id_type>(elem->type()));
  data.push_back (elem->processor_id());
  data.push_back (elem->subdomain_id());
  data.push_back (elem->id());

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  if (elem->valid_unique_id())
    data.push_back (static_cast<largest_id_type>(elem->unique_id()));
  else
    // OK to send invalid unique id, we must not own this DOF
    data.push_back (static_cast<largest_id_type>(DofObject::invalid_unique_id));
#endif

#ifdef LIBMESH_ENABLE_AMR
  // use parent_ID of -1 to indicate a level 0 element
  if (elem->level() == 0)
    {
      data.push_back(-1);
      data.push_back(-1);
    }
  else
    {
      data.push_back(elem->parent()->id());
      data.push_back(elem->parent()->which_child_am_i(elem));
    }
#else
  data.push_back (-1);
  data.push_back (-1);
#endif

  for (unsigned int n=0; n<elem->n_nodes(); n++)
    data.push_back (elem->node(n));

  for (unsigned int n=0; n<elem->n_neighbors(); n++)
    {
      const Elem *neigh = elem->neighbor(n);
      if (neigh)
        data.push_back (neigh->id());
      else
        data.push_back (-1);
    }

#ifndef NDEBUG
  const std::size_t start_indices = data.size();
#endif
  // Add any DofObject indices
  elem->pack_indexing(std::back_inserter(data));

  libmesh_assert(elem->packed_indexing_size() ==
                 DofObject::unpackable_indexing_size(data.begin() +
                                                     start_indices));

  libmesh_assert_equal_to (elem->packed_indexing_size(),
                           data.size() - start_indices);


  // If this is a coarse element,
  // Add any element side boundary condition ids
  if (elem->level() == 0)
    {
      for (unsigned short s = 0; s != elem->n_sides(); ++s)
        {
          std::vector<boundary_id_type> bcs =
            mesh->get_boundary_info().boundary_ids(elem, s);

          data.push_back(bcs.size());

          for(unsigned int bc_it=0; bc_it < bcs.size(); bc_it++)
            data.push_back(bcs[bc_it]);
        }

      for (unsigned short e = 0; e != elem->n_edges(); ++e)
        {
          std::vector<boundary_id_type> bcs =
            mesh->get_boundary_info().edge_boundary_ids(elem, e);

          data.push_back(bcs.size());

          for(unsigned int bc_it=0; bc_it < bcs.size(); bc_it++)
            data.push_back(bcs[bc_it]);
        }
    }
}
template<>
void libMesh::Parallel::pack ( const Node node,
std::vector< largest_id_type > &  data,
const ParallelMesh mesh 
)

Definition at line 177 of file parallel_node.C.

References pack().

{
  pack(node, data, static_cast<const MeshBase*>(mesh));
}
template<>
void libMesh::Parallel::pack ( const Elem elem,
std::vector< largest_id_type > &  data,
const ParallelMesh mesh 
)

Definition at line 277 of file parallel_elem.C.

References pack().

{
  pack(elem, data, static_cast<const MeshBase*>(mesh));
}
template<typename T , typename buffertype , typename Context >
void libMesh::Parallel::pack ( const T *  object,
typename std::vector< buffertype > &  data,
const Context *  context 
)

Encode a potentially-variable-size object at the end of a data array.

Parallel::pack() has no default implementation, and must be specialized for each class which is to be communicated via packed ranges.

template<typename Context , typename buffertype , typename Iter >
Iter libMesh::Parallel::pack_range ( const Context *  context,
Iter  range_begin,
const Iter  range_end,
typename std::vector< buffertype > &  buffer 
) [inline]

Encode a range of potentially-variable-size objects to a data array.

Helper function for range packing

Definition at line 385 of file parallel_implementation.h.

References pack(), packable_size(), and packed_size().

Referenced by libMesh::Parallel::Communicator::allgather_packed_range(), libMesh::Parallel::Communicator::broadcast_packed_range(), libMesh::Parallel::Communicator::gather_packed_range(), and libMesh::Parallel::Communicator::send_packed_range().

{
  // When we serialize into buffers, we need to use large buffers to optimize MPI
  // bandwidth, but not so large as to risk allocation failures.  max_buffer_size
  // is measured in number of buffer type entries; number of bytes may be 4 or 8
  // times larger depending on configuration.

  static const std::size_t max_buffer_size = 1000000;
  // static const std::size_t max_buffer_size = std::size_t(-1);

  // Count the total size of and preallocate buffer for efficiency.
  // Prepare to stop early if the buffer would be too large.
  std::size_t buffer_size = 0;
  Iter range_stop = range_begin;
  for (; range_stop != range_end; ++range_stop)
    {
      std::size_t next_buffer_size =
        Parallel::packable_size(*range_stop, context);
      if (buffer_size + next_buffer_size >= max_buffer_size)
        break;
      else
        buffer_size += next_buffer_size;
    }
  buffer.reserve(buffer.size() + buffer_size);

  // Pack the objects into the buffer
  for (; range_begin != range_stop; ++range_begin)
    {
#ifndef NDEBUG
      std::size_t old_size = buffer.size();
#endif

      Parallel::pack(*range_begin, buffer, context);

#ifndef NDEBUG
      unsigned int my_packable_size =
        Parallel::packable_size(*range_begin, context);
      unsigned int my_packed_size =
        Parallel::packed_size (*range_begin, buffer.begin() +
                               old_size);
      libmesh_assert_equal_to (my_packable_size, my_packed_size);
      libmesh_assert_equal_to (buffer.size(), old_size + my_packable_size);
#endif
    }

  return range_stop;
}
template<>
unsigned int libMesh::Parallel::packable_size ( const Node node,
const MeshBase mesh 
)

Definition at line 58 of file parallel_node.C.

References libMesh::MeshBase::get_boundary_info(), libMesh::BoundaryInfo::n_boundary_ids(), and libMesh::DofObject::packed_indexing_size().

{
  return
#ifndef NDEBUG
    1 + // add an int for the magic header when testing
#endif
    header_size + LIBMESH_DIM*idtypes_per_Real +
    node->packed_indexing_size() +
    1 + mesh->get_boundary_info().n_boundary_ids(node);
}
template<>
unsigned int libMesh::Parallel::packable_size ( const Node node,
const ParallelMesh mesh 
)

Definition at line 103 of file parallel_node.C.

References packable_size().

{
  return packable_size(node, static_cast<const MeshBase*>(mesh));
}
template<>
unsigned int libMesh::Parallel::packable_size ( const Elem elem,
const MeshBase mesh 
)

Definition at line 130 of file parallel_elem.C.

References libMesh::MeshBase::get_boundary_info(), libMesh::Elem::level(), libMesh::BoundaryInfo::n_boundary_ids(), libMesh::BoundaryInfo::n_edge_boundary_ids(), libMesh::Elem::n_edges(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_nodes(), libMesh::Elem::n_sides(), and libMesh::DofObject::packed_indexing_size().

Referenced by pack_range(), packable_size(), and packed_range_size().

{
  unsigned int total_packed_bcs = 0;
  if (elem->level() == 0)
    {
      total_packed_bcs += elem->n_sides();
      for (unsigned short s = 0; s != elem->n_sides(); ++s)
        total_packed_bcs +=
          mesh->get_boundary_info().n_boundary_ids(elem,s);

      total_packed_bcs += elem->n_edges();
      for (unsigned short e = 0; e != elem->n_edges(); ++e)
        total_packed_bcs +=
          mesh->get_boundary_info().n_edge_boundary_ids(elem,e);
    }

  return
#ifndef NDEBUG
    1 + // add an int for the magic header when testing
#endif
    header_size + elem->n_nodes() +
    elem->n_neighbors() +
    elem->packed_indexing_size() + total_packed_bcs;
}
template<>
unsigned int libMesh::Parallel::packable_size ( const Elem elem,
const ParallelMesh mesh 
)

Definition at line 158 of file parallel_elem.C.

References packable_size().

{
  return packable_size(elem, static_cast<const MeshBase*>(mesh));
}
template<typename T , typename Context >
unsigned int libMesh::Parallel::packable_size ( const T *  ,
const Context *   
)

Output the number of integers required to encode a potentially-variable-size object into a data array.

Parallel::packable_size() has no default implementation, and must be specialized for each class which is to be communicated via packed ranges.

template<typename Context , typename Iter >
std::size_t libMesh::Parallel::packed_range_size ( const Context *  context,
Iter  range_begin,
const Iter  range_end 
) [inline]

Return the total buffer size needed to encode a range of potentially-variable-size objects to a data array.

Helper function for range packing

Definition at line 366 of file parallel_implementation.h.

References packable_size().

Referenced by libMesh::Parallel::Communicator::send_packed_range().

{
  std::size_t buffer_size = 0;
  for (Iter range_count = range_begin;
       range_count != range_end;
       ++range_count)
    {
      buffer_size += Parallel::packable_size(*range_count, context);
    }
  return buffer_size;
}
template<>
unsigned int libMesh::Parallel::packed_size ( const Elem ,
std::vector< largest_id_type >::const_iterator  in 
)

Definition at line 55 of file parallel_elem.C.

References libMesh::INVALID_ELEM, n_nodes, libMesh::Elem::type_to_n_edges_map, libMesh::Elem::type_to_n_nodes_map, libMesh::Elem::type_to_n_sides_map, and libMesh::DofObject::unpackable_indexing_size().

Referenced by pack_range(), packed_size(), unpack(), and unpack_range().

{
#ifndef NDEBUG
  const largest_id_type packed_header = *in++;
  libmesh_assert_equal_to (packed_header, elem_magic_header);
#endif

  // int 0: level
  const unsigned int level =
    cast_int<unsigned int>(*in);

  // int 4: element type
  const int typeint = cast_int<int>(*(in+4));
  libmesh_assert_greater_equal (typeint, 0);
  libmesh_assert_less (typeint, INVALID_ELEM);
  const ElemType type =
    cast_int<ElemType>(typeint);

  const unsigned int n_nodes =
    Elem::type_to_n_nodes_map[type];

  const unsigned int n_sides =
    Elem::type_to_n_sides_map[type];

  const unsigned int n_edges =
    Elem::type_to_n_edges_map[type];

  const unsigned int pre_indexing_size =
    header_size + n_nodes + n_sides;

  const unsigned int indexing_size =
    DofObject::unpackable_indexing_size(in+pre_indexing_size);

  unsigned int total_packed_bc_data = 0;
  if (level == 0)
    {
      for (unsigned int s = 0; s != n_sides; ++s)
        {
          const int n_bcs = cast_int<int>
            (*(in + pre_indexing_size + indexing_size +
               total_packed_bc_data++));
          libmesh_assert_greater_equal (n_bcs, 0);
          total_packed_bc_data += n_bcs;
        }

      for (unsigned int e = 0; e != n_edges; ++e)
        {
          const int n_bcs = cast_int<int>
            (*(in + pre_indexing_size + indexing_size +
               total_packed_bc_data++));
          libmesh_assert_greater_equal (n_bcs, 0);
          total_packed_bc_data += n_bcs;
        }
    }

  return
#ifndef NDEBUG
    1 + // Account for magic header
#endif
    pre_indexing_size + indexing_size + total_packed_bc_data;
}
template<>
unsigned int libMesh::Parallel::packed_size ( const Node ,
const std::vector< largest_id_type >::const_iterator  in 
)

Definition at line 72 of file parallel_node.C.

References libMesh::DofObject::unpackable_indexing_size().

{
  const unsigned int pre_indexing_size =
#ifndef NDEBUG
    1 + // add an int for the magic header when testing
#endif
    header_size + LIBMESH_DIM*idtypes_per_Real;

  const unsigned int indexing_size =
    DofObject::unpackable_indexing_size(in+pre_indexing_size);

  const int n_bcs = cast_int<int>
    (*(in + pre_indexing_size + indexing_size));
  libmesh_assert_greater_equal (n_bcs, 0);

  return pre_indexing_size + indexing_size + 1 + n_bcs;
}
template<>
unsigned int libMesh::Parallel::packed_size ( const Node n,
const std::vector< largest_id_type >::iterator  in 
)

Definition at line 94 of file parallel_node.C.

References packed_size().

{
  return packed_size(n, std::vector<largest_id_type>::const_iterator(in));
}
template<>
unsigned int libMesh::Parallel::packed_size ( const Elem e,
std::vector< largest_id_type >::iterator  in 
)

Definition at line 121 of file parallel_elem.C.

References packed_size().

{
  return packed_size(e, std::vector<largest_id_type>::const_iterator(in));
}
template<typename T , typename BufferIter >
unsigned int libMesh::Parallel::packed_size ( const T *  ,
BufferIter   
)

Output the number of integers that were used to encode the next variable-size object in the data array.

Parallel::packed_size() has no default implementation, and must be specialized for each class which is to be communicated via packed ranges.

The output of this method should be based *only* on the data array; the T* argument is solely for function specialization.

status libMesh::Parallel::probe ( const unsigned int  src_processor_id,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]
template<typename T >
Status libMesh::Parallel::receive ( const unsigned int  src_processor_id,
T &  buf,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 975 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ return comm.receive (src_processor_id, buf, tag); }
template<typename T >
void libMesh::Parallel::receive ( const unsigned int  src_processor_id,
T &  buf,
Request &  req,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 982 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ comm.receive (src_processor_id, buf, req, tag); }
template<typename T >
Status libMesh::Parallel::receive ( const unsigned int  src_processor_id,
T &  buf,
const DataType &  type,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 990 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ return comm.receive (src_processor_id, buf, type, tag); }
template<typename T >
void libMesh::Parallel::receive ( const unsigned int  src_processor_id,
T &  buf,
const DataType &  type,
Request &  req,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 998 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive().

{ comm.receive (src_processor_id, buf, type, req, tag); }
template<typename Context , typename OutputIter >
void libMesh::Parallel::receive_packed_range ( const unsigned int  src_processor_id,
Context *  context,
OutputIter  out,
const MessageTag &  tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1007 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::receive_packed_range().

Referenced by libMesh::Parallel::Communicator::send_receive_packed_range().

{ comm.receive_packed_range (src_processor_id, context, out, tag); }
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
T &  data,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 904 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send(dest_processor_id, data, tag); }
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
T &  data,
Request &  req,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 911 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send(dest_processor_id, data, req, tag); }
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
T &  data,
const DataType &  type,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 919 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send(dest_processor_id, data, type, tag); }
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
T &  data,
const DataType &  type,
Request &  req,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 927 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send().

{ comm.send(dest_processor_id, data, type, req, tag); }
template<typename Context , typename Iter >
void libMesh::Parallel::send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 937 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send_packed_range().

Referenced by libMesh::Parallel::Communicator::send_receive_packed_range().

{ comm.send_packed_range(dest_processor_id, context, range_begin, range_end, tag); }
template<typename Context , typename Iter >
void libMesh::Parallel::send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
Request &  req,
const MessageTag &  tag = no_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 947 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send_packed_range().

{ comm.send_packed_range(dest_processor_id, context, range_begin, range_end, req, tag); }
template<typename T1 , typename T2 >
void libMesh::Parallel::send_receive ( const unsigned int  dest_processor_id,
T1 &  send,
const unsigned int  source_processor_id,
T2 &  recv,
const MessageTag &  send_tag = no_tag,
const MessageTag &  recv_tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1041 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send_receive().

{ comm.send_receive(dest_processor_id, send, source_processor_id, recv,
                    send_tag, recv_tag); }
template<typename T1 , typename T2 >
void libMesh::Parallel::send_receive ( const unsigned int  dest_processor_id,
T1 &  send,
const DataType &  type1,
const unsigned int  source_processor_id,
T2 &  recv,
const DataType &  type2,
const MessageTag &  send_tag = no_tag,
const MessageTag &  recv_tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1066 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send_receive().

{ comm.send_receive(dest_processor_id, send, type1, source_processor_id,
                    recv, type2, send_tag, recv_tag); }
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter >
void libMesh::Parallel::send_receive_packed_range ( const unsigned int  dest_processor_id,
const Context1 *  context1,
RangeIter  send_begin,
const RangeIter  send_end,
const unsigned int  source_processor_id,
Context2 *  context2,
OutputIter  out,
const MessageTag &  send_tag = no_tag,
const MessageTag &  recv_tag = any_tag,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 1052 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::send_receive_packed_range().

{ comm.send_receive_packed_range(dest_processor_id, context1, send_begin, send_end,
                                 source_processor_id, context2, out, send_tag, recv_tag); }
template<typename T >
void libMesh::Parallel::set_union ( T &  data,
const unsigned int  root_id,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 889 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::set_union().

Referenced by libMesh::Nemesis_IO_Helper::compute_border_node_ids().

{ comm.set_union(data, root_id); }
template<typename T >
void libMesh::Parallel::set_union ( T &  data,
const Communicator &  comm = Communicator_World 
) [inline]

Definition at line 894 of file parallel_implementation.h.

References libMesh::Parallel::Communicator::set_union().

{ comm.set_union(data); }
template<typename T >
void libMesh::Parallel::sum ( T &  r,
const Communicator &  comm = Communicator_World 
) [inline]
template<typename Iterator , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_id ( const Communicator &  comm,
const Iterator &  range_begin,
const Iterator &  range_end,
SyncFunctor &  sync 
)

Request data about a range of ghost dofobjects uniquely identified by their id. Fulfill requests with sync.gather_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 261 of file parallel_ghost_sync.h.

References data, libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::DofObject::processor_id(), libMesh::Parallel::Communicator::rank(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::size().

Referenced by libMesh::MeshRefinement::make_flags_parallel_consistent(), libMesh::FEMSystem::mesh_position_set(), and libMesh::LaplaceMeshSmoother::smooth().

{
  // This function must be run on all processors at once
  libmesh_parallel_only(comm);

  // Count the objects to ask each processor about
  std::vector<dof_id_type>
    ghost_objects_from_proc(comm.size(), 0);

  for (Iterator it = range_begin; it != range_end; ++it)
    {
      DofObject *obj = *it;
      libmesh_assert (obj);
      processor_id_type obj_procid = obj->processor_id();
      if (obj_procid != DofObject::invalid_processor_id)
        ghost_objects_from_proc[obj_procid]++;
    }

  // Request sets to send to each processor
  std::vector<std::vector<dof_id_type> >
    requested_objs_id(comm.size());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (processor_id_type p=0; p != comm.size(); ++p)
    if (p != comm.rank())
      {
        requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
      }
  for (Iterator it = range_begin; it != range_end; ++it)
    {
      DofObject *obj = *it;
      processor_id_type obj_procid = obj->processor_id();
      if (obj_procid == comm.rank() ||
          obj_procid == DofObject::invalid_processor_id)
        continue;

      requested_objs_id[obj_procid].push_back(obj->id());
    }

  // Trade requests with other processors
  for (processor_id_type p=1; p != comm.size(); ++p)
    {
      // Trade my requests with processor procup and procdown
      const processor_id_type procup =
        cast_int<processor_id_type>
        ((comm.rank() + p) % comm.size());
      const processor_id_type procdown =
        cast_int<processor_id_type>
        ((comm.size() + comm.rank() - p) %
         comm.size());
      std::vector<dof_id_type> request_to_fill_id;
      comm.send_receive(procup, requested_objs_id[procup],
                        procdown, request_to_fill_id);

      // Gather whatever data the user wants
      std::vector<typename SyncFunctor::datum> data;
      sync.gather_data(request_to_fill_id, data);

      // Trade back the results
      std::vector<typename SyncFunctor::datum> received_data;
      comm.send_receive(procdown, data,
                        procup, received_data);
      libmesh_assert_equal_to (requested_objs_id[procup].size(),
                               received_data.size());

      // Let the user process the results
      sync.act_on_data(requested_objs_id[procup], received_data);
    }
}
template<typename Iterator , typename DofObjType , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_xyz ( const Communicator &  comm,
const Iterator &  range_begin,
const Iterator &  range_end,
LocationMap< DofObjType > *  location_map,
SyncFunctor &  sync 
)

Request data about a range of ghost nodes uniquely identified by their xyz location or a range of active ghost elements uniquely identified by their centroids' xyz location. Fulfill requests with sync.gather_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type. The user-provided location_map will be used and left unchanged if it is provided, or filled and cleared if it is empty.

template<typename Iterator , typename DofObjType , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_xyz ( const Communicator &  comm,
const Iterator &  range_begin,
const Iterator &  range_end,
LocationMap< DofObjType > &  location_map,
SyncFunctor &  sync 
)

Definition at line 138 of file parallel_ghost_sync.h.

References data, libMesh::LocationMap< T >::empty(), libMesh::LocationMap< T >::find(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::Parallel::Communicator::max(), libMesh::LocationMap< T >::point_of(), libMesh::Parallel::Communicator::rank(), libMesh::Parallel::Communicator::send_receive(), and libMesh::Parallel::Communicator::size().

{
  // This function must be run on all processors at once
  libmesh_parallel_only(comm);

  // We need a valid location_map
#ifdef DEBUG
  bool need_map_update = (range_begin != range_end && location_map.empty());
  comm.max(need_map_update);
  libmesh_assert(!need_map_update);
#endif

  // Count the objectss to ask each processor about
  std::vector<dof_id_type>
    ghost_objects_from_proc(comm.size(), 0);

  for (Iterator it = range_begin; it != range_end; ++it)
    {
      DofObjType *obj = *it;
      libmesh_assert (obj);
      processor_id_type obj_procid = obj->processor_id();
      if (obj_procid != DofObject::invalid_processor_id)
        ghost_objects_from_proc[obj_procid]++;
    }

  // Request sets to send to each processor
  std::vector<std::vector<Real> >
    requested_objs_x(comm.size()),
    requested_objs_y(comm.size()),
    requested_objs_z(comm.size());
  // Corresponding ids to keep track of
  std::vector<std::vector<dof_id_type> >
    requested_objs_id(comm.size());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (processor_id_type p=0; p != comm.size(); ++p)
    if (p != comm.rank())
      {
        requested_objs_x[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_y[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_z[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
      }
  for (Iterator it = range_begin; it != range_end; ++it)
    {
      DofObjType *obj = *it;
      processor_id_type obj_procid = obj->processor_id();
      if (obj_procid == comm.rank() ||
          obj_procid == DofObject::invalid_processor_id)
        continue;

      Point p = location_map.point_of(*obj);
      requested_objs_x[obj_procid].push_back(p(0));
      requested_objs_y[obj_procid].push_back(p(1));
      requested_objs_z[obj_procid].push_back(p(2));
      requested_objs_id[obj_procid].push_back(obj->id());
    }

  // Trade requests with other processors
  for (processor_id_type p=1; p != comm.size(); ++p)
    {
      // Trade my requests with processor procup and procdown
      const processor_id_type procup =
        cast_int<processor_id_type>
        ((comm.rank() + p) % comm.size());
      const processor_id_type procdown =
        cast_int<processor_id_type>
        ((comm.size() + comm.rank() - p) %
         comm.size());
      std::vector<Real> request_to_fill_x,
        request_to_fill_y,
        request_to_fill_z;
      comm.send_receive(procup, requested_objs_x[procup],
                        procdown, request_to_fill_x);
      comm.send_receive(procup, requested_objs_y[procup],
                        procdown, request_to_fill_y);
      comm.send_receive(procup, requested_objs_z[procup],
                        procdown, request_to_fill_z);

      // Find the local id of each requested object
      std::vector<dof_id_type> request_to_fill_id(request_to_fill_x.size());
      for (std::size_t i=0; i != request_to_fill_x.size(); ++i)
        {
          Point pt(request_to_fill_x[i],
                   request_to_fill_y[i],
                   request_to_fill_z[i]);

          // Look for this object in the multimap
          DofObjType *obj = location_map.find(pt);

          // We'd better find every object we're asked for
          libmesh_assert (obj);

          // Return the object's correct processor id,
          // and our (correct if it's local) id for it.
          request_to_fill_id[i] = obj->id();
        }

      // Gather whatever data the user wants
      std::vector<typename SyncFunctor::datum> data;
      sync.gather_data(request_to_fill_id, data);

      // Trade back the results
      std::vector<typename SyncFunctor::datum> received_data;
      comm.send_receive(procdown, data,
                        procup, received_data);
      libmesh_assert_equal_to (requested_objs_x[procup].size(),
                               received_data.size());

      // Let the user process the results
      sync.act_on_data(requested_objs_id[procup], received_data);
    }
}
template<typename Iterator , typename SyncFunctor >
void libMesh::Parallel::sync_element_data_by_parent_id ( MeshBase &  mesh,
const Iterator &  range_begin,
const Iterator &  range_end,
SyncFunctor &  sync 
)

Request data about a range of ghost elements uniquely identified by their parent id and which child they are. Fulfill requests with sync.gather_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 341 of file parallel_ghost_sync.h.

References libMesh::Elem::active(), libMesh::Elem::child(), libMesh::ParallelObject::comm(), data, libMesh::MeshBase::elem(), libMesh::Elem::has_children(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::Elem::parent(), libMesh::DofObject::processor_id(), and libMesh::Elem::which_child_am_i().

Referenced by libMesh::MeshCommunication::make_elems_parallel_consistent().

{
  const Communicator &comm (mesh.comm());

  // This function must be run on all processors at once
  libmesh_parallel_only(comm);

  // Count the objects to ask each processor about
  std::vector<dof_id_type>
    ghost_objects_from_proc(comm.size(), 0);

  for (Iterator it = range_begin; it != range_end; ++it)
    {
      DofObject *obj = *it;
      libmesh_assert (obj);
      processor_id_type obj_procid = obj->processor_id();
      if (obj_procid != DofObject::invalid_processor_id)
        ghost_objects_from_proc[obj_procid]++;
    }

  // Request sets to send to each processor
  std::vector<std::vector<dof_id_type> >
    requested_objs_id(comm.size()),
    requested_objs_parent_id(comm.size());
  std::vector<std::vector<unsigned char> >
    requested_objs_child_num(comm.size());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (processor_id_type p=0; p != comm.size(); ++p)
    if (p != comm.rank())
      {
        requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_parent_id[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_child_num[p].reserve(ghost_objects_from_proc[p]);
      }

  for (Iterator it = range_begin; it != range_end; ++it)
    {
      Elem *elem = *it;
      processor_id_type obj_procid = elem->processor_id();
      if (obj_procid == comm.rank() ||
          obj_procid == DofObject::invalid_processor_id)
        continue;
      const Elem *parent = elem->parent();
      if (!parent || !elem->active())
        continue;

      requested_objs_id[obj_procid].push_back(elem->id());
      requested_objs_parent_id[obj_procid].push_back(parent->id());
      requested_objs_child_num[obj_procid].push_back
        (cast_int<unsigned char>
         (parent->which_child_am_i(elem)));
    }

  // Trade requests with other processors
  for (processor_id_type p=1; p != comm.size(); ++p)
    {
      // Trade my requests with processor procup and procdown
      const processor_id_type procup =
        cast_int<processor_id_type>
        ((comm.rank() + p) % comm.size());
      const processor_id_type procdown =
        cast_int<processor_id_type>
        ((comm.size() + comm.rank() - p) %
         comm.size());
      std::vector<dof_id_type>   request_to_fill_parent_id;
      std::vector<unsigned char> request_to_fill_child_num;
      comm.send_receive(procup, requested_objs_parent_id[procup],
                        procdown, request_to_fill_parent_id);
      comm.send_receive(procup, requested_objs_child_num[procup],
                        procdown, request_to_fill_child_num);

      // Find the id of each requested element
      std::size_t request_size = request_to_fill_parent_id.size();
      std::vector<dof_id_type> request_to_fill_id(request_size);
      for (std::size_t i=0; i != request_size; ++i)
        {
          Elem *parent = mesh.elem(request_to_fill_parent_id[i]);
          libmesh_assert(parent);
          libmesh_assert(parent->has_children());
          Elem *child = parent->child(request_to_fill_child_num[i]);
          libmesh_assert(child);
          libmesh_assert(child->active());
          request_to_fill_id[i] = child->id();
        }

      // Gather whatever data the user wants
      std::vector<typename SyncFunctor::datum> data;
      sync.gather_data(request_to_fill_id, data);

      // Trade back the results
      std::vector<typename SyncFunctor::datum> received_data;
      comm.send_receive(procdown, data,
                        procup, received_data);
      libmesh_assert_equal_to (requested_objs_id[procup].size(),
                               received_data.size());

      // Let the user process the results
      sync.act_on_data(requested_objs_id[procup], received_data);
    }
}
template<typename SyncFunctor >
void libMesh::Parallel::sync_node_data_by_element_id ( MeshBase &  mesh,
const MeshBase::const_element_iterator &  range_begin,
const MeshBase::const_element_iterator &  range_end,
SyncFunctor &  sync 
)

Request data about a range of ghost nodes uniquely identified by an element id and local node id. Data for all nodes connected to elements in the given range of *element* iterators will be requested. Fulfill requests with sync.gather_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data), by resizing and setting the values of the data vector. Respond to fulfillment with sync.act_on_data(const std::vector<unsigned int>& ids, std::vector<sync::datum>& data) The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 459 of file parallel_ghost_sync.h.

References libMesh::ParallelObject::comm(), data, libMesh::MeshBase::elem(), libMesh::Elem::get_node(), libMesh::DofObject::id(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::Elem::n_nodes(), and libMesh::DofObject::processor_id().

Referenced by libMesh::MeshCommunication::make_node_ids_parallel_consistent(), and libMesh::MeshCommunication::make_node_proc_ids_parallel_consistent().

{
  const Communicator &comm (mesh.comm());

  // This function must be run on all processors at once
  libmesh_parallel_only(comm);

  // Keep track of which nodes we've asked about, so we only hit each
  // once.
  LIBMESH_BEST_UNORDERED_SET<dof_id_type> queried_nodes;

  // Count the objects to ask each processor about
  std::vector<dof_id_type>
    ghost_objects_from_proc(comm.size(), 0);

  for (MeshBase::const_element_iterator it = range_begin;
       it != range_end; ++it)
    {
      const Elem *elem = *it;
      libmesh_assert (elem);

      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        {
          const Node *node = elem->get_node(n);

          const processor_id_type proc_id = node->processor_id();
          if (proc_id == comm.rank() ||
              proc_id == DofObject::invalid_processor_id)
            continue;

          dof_id_type node_id = node->id();
          if (!queried_nodes.count(node_id))
            {
              ghost_objects_from_proc[proc_id]++;
              queried_nodes.insert(node_id);
            }
        }
    }

  // Now repeat that iteration, filling request sets this time.
  queried_nodes.clear();

  // Request sets to send to each processor
  std::vector<std::vector<dof_id_type> >
    requested_objs_elem_id(comm.size());
  std::vector<std::vector<unsigned char> >
    requested_objs_node_num(comm.size());

  // Keep track of current local ids for each too
  std::vector<std::vector<dof_id_type> >
    requested_objs_id(comm.size());

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (processor_id_type p=0; p != comm.size(); ++p)
    if (p != comm.rank())
      {
        requested_objs_elem_id[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_node_num[p].reserve(ghost_objects_from_proc[p]);
        requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
      }

  for (MeshBase::const_element_iterator it = range_begin;
       it != range_end; ++it)
    {
      const Elem *elem = *it;
      libmesh_assert (elem);

      const dof_id_type elem_id = elem->id();

      for (unsigned int n=0; n != elem->n_nodes(); ++n)
        {
          const Node *node = elem->get_node(n);
          const dof_id_type node_id = node->id();

          const processor_id_type proc_id = node->processor_id();
          if (proc_id == comm.rank() ||
              proc_id == DofObject::invalid_processor_id)
            continue;

          if (!queried_nodes.count(node_id))
            {
              requested_objs_elem_id[proc_id].push_back(elem_id);
              requested_objs_node_num[proc_id].push_back
                (cast_int<unsigned char>(n));
              requested_objs_id[proc_id].push_back(node_id);
              queried_nodes.insert(node_id);
            }
        }
    }

  // Trade requests with other processors
  for (processor_id_type p=1; p != comm.size(); ++p)
    {
      // Trade my requests with processor procup and procdown
      const processor_id_type procup =
        cast_int<processor_id_type>
        ((comm.rank() + p) % comm.size());
      const processor_id_type procdown =
        cast_int<processor_id_type>
        ((comm.size() + comm.rank() - p) %
         comm.size());

      libmesh_assert_equal_to (requested_objs_id[procup].size(),
                               ghost_objects_from_proc[procup]);
      libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
                               ghost_objects_from_proc[procup]);
      libmesh_assert_equal_to (requested_objs_node_num[procup].size(),
                               ghost_objects_from_proc[procup]);

      std::vector<dof_id_type>   request_to_fill_elem_id;
      std::vector<unsigned char> request_to_fill_node_num;
      comm.send_receive(procup, requested_objs_elem_id[procup],
                        procdown, request_to_fill_elem_id);
      comm.send_receive(procup, requested_objs_node_num[procup],
                        procdown, request_to_fill_node_num);

      // Find the id of each requested element
      std::size_t request_size = request_to_fill_elem_id.size();
      std::vector<dof_id_type> request_to_fill_id(request_size);
      for (std::size_t i=0; i != request_size; ++i)
        {
          const Elem *elem = mesh.elem(request_to_fill_elem_id[i]);
          libmesh_assert(elem);

          const unsigned int n = request_to_fill_node_num[i];
          libmesh_assert_less (n, elem->n_nodes());

          Node *node = elem->get_node(n);
          libmesh_assert(node);

          // This isn't a safe assertion in the case where we're
          // synching processor ids
          // libmesh_assert_equal_to (node->processor_id(), comm.rank());

          request_to_fill_id[i] = node->id();
        }

      // Gather whatever data the user wants
      std::vector<typename SyncFunctor::datum> data;
      sync.gather_data(request_to_fill_id, data);

      // Trade back the results
      std::vector<typename SyncFunctor::datum> received_data;
      comm.send_receive(procdown, data,
                        procup, received_data);
      libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
                               received_data.size());

      // Let the user process the results
      sync.act_on_data(requested_objs_id[procup], received_data);
    }
}
template<>
void libMesh::Parallel::unpack ( std::vector< largest_id_type >::const_iterator  in,
Node **  out,
MeshBase mesh 
)

Definition at line 187 of file parallel_node.C.

References libMesh::BoundaryInfo::add_node(), libMesh::MeshBase::get_boundary_info(), libMesh::DofObject::invalid_processor_id, libMesh::libmesh_assert(), libMesh::n_processors(), packed_size(), libMesh::processor_id(), libMesh::MeshBase::query_node_ptr(), libMesh::Real, and libMesh::DofObject::unpackable_indexing_size().

{
#ifndef NDEBUG
  const std::vector<largest_id_type>::const_iterator original_in = in;
  const largest_id_type incoming_header = *in++;
  libmesh_assert_equal_to (incoming_header, node_magic_header);
#endif

  const processor_id_type processor_id = cast_int<processor_id_type>(*in++);
  libmesh_assert(processor_id == DofObject::invalid_processor_id ||
                 processor_id < mesh->n_processors());

  const dof_id_type id = cast_int<dof_id_type>(*in++);

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  const unique_id_type unique_id = cast_int<unique_id_type>(*in++);
#endif

  Node *node = mesh->query_node_ptr(id);

  if (node)
    {
      libmesh_assert_equal_to (node->processor_id(), processor_id);

      // We currently don't communicate mesh motion via packed Nodes,
      // so it should be safe to assume (and assert) that Node
      // locations are consistent between processors
#ifndef NDEBUG
      for (unsigned int i=0; i != LIBMESH_DIM; ++i)
        {
          const Real* idtypes_as_Real = reinterpret_cast<const Real*>(&(*in));
          libmesh_assert_equal_to ((*node)(i), *idtypes_as_Real);
          in += idtypes_per_Real;
        }
#else
      in += LIBMESH_DIM * idtypes_per_Real;
#endif // !NDEBUG

      if (!node->has_dofs())
        {
          node->unpack_indexing(in);
          libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
                                   node->packed_indexing_size());
          in += node->packed_indexing_size();
        }
      else
        {
          // FIXME: We should add some debug mode tests to ensure that
          // the encoded indexing is consistent
          in += DofObject::unpackable_indexing_size(in);
        }

      *out = node;
    }
  else
    {
      // If we don't already have it, we need to allocate it
      node = new Node();

      for (unsigned int i=0; i != LIBMESH_DIM; ++i)
        {
          const Real* idtypes_as_Real = reinterpret_cast<const Real*>(&(*in));
          (*node)(i) = *idtypes_as_Real;
          in += idtypes_per_Real;
        }

      node->set_id() = id;
#ifdef LIBMESH_ENABLE_UNIQUE_ID
      node->set_unique_id() = unique_id;
#endif
      node->processor_id() = processor_id;

      node->unpack_indexing(in);
      libmesh_assert_equal_to (DofObject::unpackable_indexing_size(in),
                               node->packed_indexing_size());
      in += node->packed_indexing_size();
    }

  // FIXME: We should add some debug mode tests to ensure that the
  // encoded boundary conditions are consistent

  // Add any nodal boundary condition ids
  const largest_id_type num_bcs = *in++;
  // libmesh_assert_greater_equal (num_bcs, 0);

  for(largest_id_type bc_it=0; bc_it < num_bcs; bc_it++)
    mesh->get_boundary_info().add_node
      (node, cast_int<boundary_id_type>(*in++));

  *out = node;

#ifndef NDEBUG
  libmesh_assert (in - original_in ==
                  cast_int<int>
                  (Parallel::packed_size(node, original_in)));
#endif
}
template<>
void libMesh::Parallel::unpack ( std::vector< largest_id_type >::const_iterator  in,
Elem **  out,
MeshBase mesh 
)

Definition at line 288 of file parallel_elem.C.

References libMesh::Elem::active(), libMesh::Elem::add_child(), libMesh::BoundaryInfo::add_edge(), libMesh::BoundaryInfo::add_side(), libMesh::Elem::build(), libMesh::Elem::child(), libMesh::MeshBase::elem(), libMesh::MeshBase::get_boundary_info(), libMesh::DofObject::id(), libMesh::INVALID_ELEM, libMesh::DofObject::invalid_id, libMesh::DofObject::invalid_processor_id, libMesh::Elem::INVALID_REFINEMENTSTATE, libMesh::Elem::level(), libMesh::libmesh_assert(), libMesh::Elem::make_links_to_me_local(), libMesh::Elem::n_children(), libMesh::Elem::n_edges(), libMesh::Elem::n_neighbors(), n_nodes, libMesh::Elem::n_nodes(), libMesh::n_processors(), libMesh::Elem::n_sides(), libMesh::Elem::neighbor(), libMesh::Elem::node(), libMesh::MeshBase::node_ptr(), libMesh::Elem::p_level(), libMesh::Elem::p_refinement_flag(), libMesh::DofObject::packed_indexing_size(), libMesh::Elem::parent(), libMesh::processor_id(), libMesh::DofObject::processor_id(), libMesh::MeshBase::query_elem(), libMesh::Elem::refinement_flag(), libMesh::remote_elem, libMesh::DofObject::set_id(), libMesh::Elem::set_neighbor(), libMesh::Elem::set_node(), libMesh::Elem::set_p_level(), libMesh::Elem::set_p_refinement_flag(), libMesh::Elem::set_refinement_flag(), libMesh::DofObject::set_unique_id(), libMesh::Elem::subdomain_id(), libMesh::Elem::type(), libMesh::Elem::type_to_n_nodes_map, and libMesh::DofObject::unpack_indexing().

Referenced by unpack(), and unpack_range().

{
#ifndef NDEBUG
  const std::vector<largest_id_type>::const_iterator original_in = in;

  const largest_id_type incoming_header = *in++;
  libmesh_assert_equal_to (incoming_header, elem_magic_header);
#endif

  // int 0: level
  const unsigned int level =
    cast_int<unsigned int>(*in++);

#ifdef LIBMESH_ENABLE_AMR
  // int 1: p level
  const unsigned int p_level =
    cast_int<unsigned int>(*in++);

  // int 2: refinement flag
  const int rflag = cast_int<int>(*in++);
  libmesh_assert_greater_equal (rflag, 0);
  libmesh_assert_less (rflag, Elem::INVALID_REFINEMENTSTATE);
  const Elem::RefinementState refinement_flag =
    cast_int<Elem::RefinementState>(rflag);

  // int 3: p refinement flag
  const int pflag = cast_int<int>(*in++);
  libmesh_assert_greater_equal (pflag, 0);
  libmesh_assert_less (pflag, Elem::INVALID_REFINEMENTSTATE);
  const Elem::RefinementState p_refinement_flag =
    cast_int<Elem::RefinementState>(pflag);
#else
  in += 3;
#endif // LIBMESH_ENABLE_AMR

  // int 4: element type
  const int typeint = cast_int<int>(*in++);
  libmesh_assert_greater_equal (typeint, 0);
  libmesh_assert_less (typeint, INVALID_ELEM);
  const ElemType type =
    cast_int<ElemType>(typeint);

  const unsigned int n_nodes =
    Elem::type_to_n_nodes_map[type];

  // int 5: processor id
  const processor_id_type processor_id =
    cast_int<processor_id_type>(*in++);
  libmesh_assert (processor_id < mesh->n_processors() ||
                  processor_id == DofObject::invalid_processor_id);

  // int 6: subdomain id
  const subdomain_id_type subdomain_id =
    cast_int<subdomain_id_type>(*in++);

  // int 7: dof object id
  const dof_id_type id =
    cast_int<dof_id_type>(*in++);
  libmesh_assert_not_equal_to (id, DofObject::invalid_id);

#ifdef LIBMESH_ENABLE_UNIQUE_ID
  // int 8: dof object unique id
  const unique_id_type unique_id =
    cast_int<unique_id_type>(*in++);
#endif

#ifdef LIBMESH_ENABLE_AMR
  // int 9: parent dof object id.
  // Note: If level==0, then (*in) == (unsigned long long)(-1).  In
  // this case, the equality check in cast_int<unsigned>(*in) will
  // never succeed.  Therefore, we should only attempt the more
  // rigorous cast verification in cases where level != 0.
  const dof_id_type parent_id =
    (level == 0)
    ? static_cast<dof_id_type>(*in++)
    : cast_int<dof_id_type>(*in++);
  libmesh_assert (level == 0 || parent_id != DofObject::invalid_id);
  libmesh_assert (level != 0 || parent_id == DofObject::invalid_id);

  // int 10: local child id
  // Note: If level==0, then which_child_am_i is not valid, so don't
  // do the more rigorous cast verification.
  const unsigned int which_child_am_i =
    (level == 0)
    ? static_cast<unsigned int>(*in++)
    : cast_int<unsigned int>(*in++);
#else
  in += 2;
#endif // LIBMESH_ENABLE_AMR

  // Make sure we don't miscount above when adding the "magic" header
  // plus the real data header
  libmesh_assert_equal_to (in - original_in, header_size + 1);

  Elem *elem = mesh->query_elem(id);

  // if we already have this element, make sure its
  // properties match, and update any missing neighbor
  // links, but then go on
  if (elem)
    {
      libmesh_assert_equal_to (elem->level(), level);
      libmesh_assert_equal_to (elem->id(), id);
      //#ifdef LIBMESH_ENABLE_UNIQUE_ID
      // No check for unqiue id sanity
      //#endif
      libmesh_assert_equal_to (elem->processor_id(), processor_id);
      libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id);
      libmesh_assert_equal_to (elem->type(), type);
      libmesh_assert_equal_to (elem->n_nodes(), n_nodes);

#ifndef NDEBUG
      // All our nodes should be correct
      for (unsigned int i=0; i != n_nodes; ++i)
        libmesh_assert(elem->node(i) ==
                       cast_int<dof_id_type>(*in++));
#else
      in += n_nodes;
#endif

#ifdef LIBMESH_ENABLE_AMR
      libmesh_assert_equal_to (elem->p_level(), p_level);
      libmesh_assert_equal_to (elem->refinement_flag(), refinement_flag);
      libmesh_assert_equal_to (elem->p_refinement_flag(), p_refinement_flag);

      libmesh_assert (!level || elem->parent() != NULL);
      libmesh_assert (!level || elem->parent()->id() == parent_id);
      libmesh_assert (!level || elem->parent()->child(which_child_am_i) == elem);
#endif

      // Our neighbor links should be "close to" correct - we may have
      // to update them, but we can check for some inconsistencies.
      for (unsigned int n=0; n != elem->n_neighbors(); ++n)
        {
          // We can't cast_int here, since NULL neighbors have an ID
          // of (unsigned long long)(-1) which doesn't fit in an
          // unsigned.
          const dof_id_type neighbor_id =
            static_cast<dof_id_type>(*in++);

          // If the sending processor sees a domain boundary here,
          // we'd better agree.
          if (neighbor_id == DofObject::invalid_id)
            {
              libmesh_assert (!(elem->neighbor(n)));
              continue;
            }

          // If the sending processor has a remote_elem neighbor here,
          // then all we know is that we'd better *not* have a domain
          // boundary.
          if (neighbor_id == remote_elem->id())
            {
              libmesh_assert(elem->neighbor(n));
              continue;
            }

          Elem *neigh = mesh->query_elem(neighbor_id);

          // The sending processor sees a neighbor here, so if we
          // don't have that neighboring element, then we'd better
          // have a remote_elem signifying that fact.
          if (!neigh)
            {
              libmesh_assert_equal_to (elem->neighbor(n), remote_elem);
              continue;
            }

          // The sending processor has a neighbor here, and we have
          // that element, but that does *NOT* mean we're already
          // linking to it.  Perhaps we initially received both elem
          // and neigh from processors on which their mutual link was
          // remote?
          libmesh_assert(elem->neighbor(n) == neigh ||
                         elem->neighbor(n) == remote_elem);

          // If the link was originally remote, we should update it,
          // and make sure the appropriate parts of its family link
          // back to us.
          if (elem->neighbor(n) == remote_elem)
            {
              elem->set_neighbor(n, neigh);

              elem->make_links_to_me_local(n);
            }
        }

      // FIXME: We should add some debug mode tests to ensure that the
      // encoded indexing and boundary conditions are consistent.
    }
  else
    {
      // We don't already have the element, so we need to create it.

      // Find the parent if necessary
      Elem *parent = NULL;
#ifdef LIBMESH_ENABLE_AMR
      // Find a child element's parent
      if (level > 0)
        {
          // Note that we must be very careful to construct the send
          // connectivity so that parents are encountered before
          // children.  If we get here and can't find the parent that
          // is a fatal error.
          parent = mesh->elem(parent_id);
        }
      // Or assert that the sending processor sees no parent
      else
        libmesh_assert_equal_to (parent_id, static_cast<dof_id_type>(-1));
#else
      // No non-level-0 elements without AMR
      libmesh_assert_equal_to (level, 0);
#endif

      elem = Elem::build(type,parent).release();
      libmesh_assert (elem);

#ifdef LIBMESH_ENABLE_AMR
      if (level != 0)
        {
          // Since this is a newly created element, the parent must
          // have previously thought of this child as a remote element.
          libmesh_assert_equal_to (parent->child(which_child_am_i), remote_elem);

          parent->add_child(elem, which_child_am_i);
        }

      // Assign the refinement flags and levels
      elem->set_p_level(p_level);
      elem->set_refinement_flag(refinement_flag);
      elem->set_p_refinement_flag(p_refinement_flag);
      libmesh_assert_equal_to (elem->level(), level);

      // If this element definitely should have children, assign
      // remote_elem to all of them for now, for consistency.  Later
      // unpacked elements may overwrite that.
      if (!elem->active())
        for (unsigned int c=0; c != elem->n_children(); ++c)
          elem->add_child(const_cast<RemoteElem*>(remote_elem), c);

#endif // LIBMESH_ENABLE_AMR

      // Assign the IDs
      elem->subdomain_id()  = subdomain_id;
      elem->processor_id()  = processor_id;
      elem->set_id()        = id;
#ifdef LIBMESH_ENABLE_UNIQUE_ID
      elem->set_unique_id() = unique_id;
#endif

      // Assign the connectivity
      libmesh_assert_equal_to (elem->n_nodes(), n_nodes);

      for (unsigned int n=0; n != n_nodes; n++)
        elem->set_node(n) =
          mesh->node_ptr
          (cast_int<dof_id_type>(*in++));

      for (unsigned int n=0; n<elem->n_neighbors(); n++)
        {
          // We can't cast_int here, since NULL neighbors have an ID
          // of (unsigned long long)(-1) which doesn't fit in an
          // unsigned.
          const dof_id_type neighbor_id =
            static_cast<dof_id_type>(*in++);

          if (neighbor_id == DofObject::invalid_id)
            continue;

          // We may be unpacking an element that was a ghost element on the
          // sender, in which case the element's neighbors may not all be
          // known by the packed element.  We'll have to set such
          // neighbors to remote_elem ourselves and wait for a later
          // packed element to give us better information.
          if (neighbor_id == remote_elem->id())
            {
              elem->set_neighbor(n, const_cast<RemoteElem*>(remote_elem));
              continue;
            }

          // If we don't have the neighbor element, then it's a
          // remote_elem until we get it.
          Elem *neigh = mesh->query_elem(neighbor_id);
          if (!neigh)
            {
              elem->set_neighbor(n, const_cast<RemoteElem*>(remote_elem));
              continue;
            }

          // If we have the neighbor element, then link to it, and
          // make sure the appropriate parts of its family link back
          // to us.
          elem->set_neighbor(n, neigh);

          elem->make_links_to_me_local(n);
        }

      elem->unpack_indexing(in);
    }

  in += elem->packed_indexing_size();

  // If this is a coarse element,
  // add any element side or edge boundary condition ids
  if (level == 0)
    {
      for (unsigned short s = 0; s != elem->n_sides(); ++s)
        {
          const boundary_id_type num_bcs =
            cast_int<boundary_id_type>(*in++);

          for(boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
            mesh->get_boundary_info().add_side
              (elem, s, cast_int<boundary_id_type>(*in++));
        }

      for (unsigned short e = 0; e != elem->n_edges(); ++e)
        {
          const boundary_id_type num_bcs =
            cast_int<boundary_id_type>(*in++);

          for(boundary_id_type bc_it=0; bc_it < num_bcs; bc_it++)
            mesh->get_boundary_info().add_edge
              (elem, e, cast_int<boundary_id_type>(*in++));
        }
    }

  // Return the new element
  *out = elem;
}
template<>
void libMesh::Parallel::unpack ( std::vector< largest_id_type >::const_iterator  in,
Node **  out,
ParallelMesh mesh 
)

Definition at line 290 of file parallel_node.C.

References unpack().

{
  unpack(in, out, static_cast<MeshBase*>(mesh));
}
template<typename T , typename BufferIter , typename Context >
void libMesh::Parallel::unpack ( BufferIter  in,
T **  out,
Context *  ctx 
)

Decode a potentially-variable-size object from a subsequence of a data array.

Parallel::unpack() has no default implementation, and must be specialized for each class which is to be communicated via packed ranges.

template<>
void libMesh::Parallel::unpack ( std::vector< largest_id_type >::const_iterator  in,
Elem **  out,
ParallelMesh mesh 
)

Definition at line 624 of file parallel_elem.C.

References unpack().

{
  unpack(in, out, static_cast<MeshBase*>(mesh));
}
template<typename Context , typename buffertype , typename OutputIter >
void libMesh::Parallel::unpack_range ( const std::vector< buffertype > &  buffer,
Context *  context,
OutputIter  out 
) [inline]

Helper function for range unpacking

Definition at line 442 of file parallel_implementation.h.

References libMesh::libmesh_assert(), packed_size(), and unpack().

{
  // Our objects should be of the correct type to be assigned to the
  // output iterator
  typedef typename std::iterator_traits<OutputIter>::value_type T;

  // Loop through the buffer and unpack each object, returning the
  // object pointer via the output iterator
  typename std::vector<buffertype>::const_iterator
    next_object_start = buffer.begin();

  while (next_object_start < buffer.end())
    {
      T* obj;
      Parallel::unpack(next_object_start, &obj, context);
      libmesh_assert(obj);
      next_object_start += Parallel::packed_size(obj, next_object_start);
      *out++ = obj;
    }

  // We should have used up the exact amount of data in the buffer
  libmesh_assert (next_object_start == buffer.end());
}
template<typename Context , typename buffertype , typename OutputIter >
void libMesh::Parallel::unpack_range ( const typename std::vector< buffertype > &  buffer,
Context *  context,
OutputIter  out 
) [inline]
void libMesh::Parallel::wait ( std::vector< Request > &  r) [inline]

Wait for a non-blocking send or receive to finish

Definition at line 472 of file parallel.h.

References wait().

{ for (unsigned int i=0; i<r.size(); i++) r[i].wait(); }

Variable Documentation

const unsigned int libMesh::Parallel::any_source
Initial value:
  static_cast<unsigned int>(MPI_ANY_SOURCE)

Accept from any source

Definition at line 150 of file parallel.h.

Referenced by libMesh::Nemesis_IO::read(), libMesh::System::read_serialized_blocked_dof_objects(), and libMesh::System::write_serialized_blocked_dof_objects().

Default message tag ids

Definition at line 223 of file parallel.h.

Referenced by libMesh::Parallel::Communicator::send_receive().