libMesh::Parallel Namespace Reference

Namespaces

 Utils
 

Classes

struct  Attributes
 
struct  Attributes< unsigned long long >
 
class  BinSorter
 Parallel bin sorting object. More...
 
class  Communicator
 
struct  data_type
 
class  DataPlusInt
 
class  DataType
 
struct  dependent_false
 
class  FakeCommunicator
 
struct  false_type
 
class  Histogram
 Used in conjunction with a BinSorter for parallel sorting. More...
 
class  MessageTag
 
class  OpFunction
 
class  OpFunction< Point >
 
class  OpFunction< TypeVector< T > >
 
class  OpFunction< VectorValue< T > >
 
class  Packing
 
class  Packing< const Elem * >
 
class  Packing< const Node * >
 
class  Packing< Elem * >
 
class  Packing< Node * >
 
struct  PostWaitCopyBuffer
 
struct  PostWaitDeleteBuffer
 
struct  PostWaitUnpackBuffer
 
struct  PostWaitWork
 
struct  request
 
class  Request
 
class  Sort
 Object for performing parallel sorts using MPI. More...
 
class  StandardType
 
class  StandardType< Hilbert::HilbertIndices >
 
class  StandardType< Point >
 
class  StandardType< std::complex< T > >
 
class  StandardType< std::pair< T1, T2 > >
 
class  StandardType< TensorValue< T > >
 
class  StandardType< TypeTensor< T > >
 
class  StandardType< TypeVector< T > >
 
class  StandardType< unsigned long long >
 
class  StandardType< VectorValue< T > >
 
class  Status
 
struct  status
 
struct  SyncEverything
 
class  TypeVectorOpFunction
 

Typedefs

typedef MPI_Datatype data_type
 
typedef MPI_Request request
 
typedef MPI_Status status
 
typedef MPI_Comm communicator
 
typedef std::pair< Hilbert::HilbertIndices, unique_id_typeDofObjectKey
 

Functions

template<typename T >
data_type dataplusint_type ()
 
Status wait (Request &r)
 
void wait (std::vector< Request > &r)
 
template<typename Context , typename buffertype , typename OutputIter , typename T >
void unpack_range (const typename std::vector< buffertype > &buffer, Context *context, OutputIter out, const T *output_type)
 
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, std::size_t approx_buffer_size=1000000)
 
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 DofObjectCheckFunctor , typename SyncFunctor >
void sync_dofobject_data_by_id (const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, const DofObjectCheckFunctor &dofobj_check, 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 ElemCheckFunctor , typename NodeCheckFunctor , 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, const ElemCheckFunctor &elem_check, const NodeCheckFunctor &node_check, 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)
 
 LIBMESH_INT_TYPE (char, MPI_CHAR)
 
 LIBMESH_INT_TYPE (signed char, MPI_SIGNED_CHAR)
 
 LIBMESH_INT_TYPE (unsigned char, MPI_UNSIGNED_CHAR)
 
 LIBMESH_INT_TYPE (short int, MPI_SHORT)
 
 LIBMESH_INT_TYPE (unsigned short int, MPI_UNSIGNED_SHORT)
 
 LIBMESH_INT_TYPE (int, MPI_INT)
 
 LIBMESH_INT_TYPE (unsigned int, MPI_UNSIGNED)
 
 LIBMESH_INT_TYPE (long, MPI_LONG)
 
 LIBMESH_INT_TYPE (long long, MPI_LONG_LONG_INT)
 
 LIBMESH_INT_TYPE (unsigned long, MPI_UNSIGNED_LONG)
 
 LIBMESH_INT_TYPE (unsigned long long, MPI_UNSIGNED_LONG_LONG)
 
 LIBMESH_PARALLEL_INTEGER_OPS (unsigned long long)
 
 LIBMESH_FLOAT_TYPE (float, MPI_FLOAT)
 
 LIBMESH_FLOAT_TYPE (double, MPI_DOUBLE)
 
 LIBMESH_FLOAT_TYPE (long double, MPI_LONG_DOUBLE)
 
 LIBMESH_CONTAINER_TYPE (std::set)
 
 LIBMESH_CONTAINER_TYPE (std::vector)
 
template<typename Context , typename buffertype , typename OutputIter , typename T >
void unpack_range (const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
 
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, const T &data, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
 
template<typename T >
void send (const unsigned int dest_processor_id, const 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, const 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, const 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 , typename T >
void receive_packed_range (const unsigned int src_processor_id, Context *context, OutputIter out_iter, const T *output_type, 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 , typename T >
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_iter, const T *output_type, 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_iter, 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_iter, 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_iter, 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 177 of file parallel.h.

typedef MPI_Datatype libMesh::Parallel::data_type

Data types for communication

Definition at line 162 of file parallel.h.

typedef Hilbert::HilbertIndices libMesh::Parallel::DofObjectKey

Definition at line 67 of file parallel_hilbert.h.

typedef MPI_Request libMesh::Parallel::request

Request object for non-blocking I/O

Definition at line 167 of file parallel.h.

typedef MPI_Status libMesh::Parallel::status

Status object for querying messages

Definition at line 172 of file parallel.h.

Function Documentation

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

Definition at line 1276 of file parallel_implementation.h.

Referenced by libMesh::Parallel::Communicator::allgather(), libMesh::Parallel::Communicator::allgather_packed_range(), libMesh::Parallel::Communicator::gather(), libMesh::Parallel::Communicator::send_mode(), and libMesh::Parallel::Communicator::set_union().

1279 { comm.allgather(send, recv); }
void send(const unsigned int dest_processor_id, const T &data, const DataType &type, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
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 1282 of file parallel_implementation.h.

1285 { 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_iter,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1297 of file parallel_implementation.h.

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

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

Definition at line 1305 of file parallel_implementation.h.

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

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

Definition at line 1024 of file parallel_implementation.h.

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

1025 {
1026  comm.barrier();
1027 }
template<typename T >
void libMesh::Parallel::broadcast ( T &  data,
const unsigned int  root_id = 0,
const Communicator comm = Communicator_World 
)
inline
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_iter,
const unsigned int  root_id = 0,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1316 of file parallel_implementation.h.

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

1323 { comm.broadcast_packed_range(context1, range_begin, range_end, context2, out_iter, 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 1409 of file parallel_implementation.h.

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

Definition at line 1406 of file parallel_implementation.h.

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

Definition at line 1400 of file parallel_implementation.h.

Referenced by libMesh::Parallel::Communicator::maxloc(), and libMesh::Parallel::Communicator::minloc().

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

Definition at line 1403 of file parallel_implementation.h.

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

Definition at line 1412 of file parallel_implementation.h.

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

Definition at line 1397 of file parallel_implementation.h.

1397 { return MPI_SHORT_INT; }
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 1263 of file parallel_implementation.h.

Referenced by libMesh::MeshCommunication::gather(), libMesh::Parallel::Communicator::gather(), libMesh::Parallel::Communicator::gather_packed_range(), libMesh::Parallel::Communicator::send_mode(), and libMesh::Parallel::Communicator::set_union().

1267 { comm.gather(root_id, send, recv); }
void send(const unsigned int dest_processor_id, const T &data, const DataType &type, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
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 1270 of file parallel_implementation.h.

1273 { 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_iter,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1288 of file parallel_implementation.h.

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

1294 { comm.gather_packed_range(root_id, context, range_begin, range_end, out_iter); }
libMesh::Parallel::LIBMESH_CONTAINER_TYPE ( std::set  )
libMesh::Parallel::LIBMESH_CONTAINER_TYPE ( std::vector  )
libMesh::Parallel::LIBMESH_FLOAT_TYPE ( float  ,
MPI_FLOAT   
)
libMesh::Parallel::LIBMESH_FLOAT_TYPE ( double  ,
MPI_DOUBLE   
)
libMesh::Parallel::LIBMESH_FLOAT_TYPE ( long  double,
MPI_LONG_DOUBLE   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( char  ,
MPI_CHAR   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( signed  char,
MPI_SIGNED_CHAR   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( unsigned  char,
MPI_UNSIGNED_CHAR   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( short  int,
MPI_SHORT   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( unsigned short  int,
MPI_UNSIGNED_SHORT   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( int  ,
MPI_INT   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( unsigned  int,
MPI_UNSIGNED   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( long  ,
MPI_LONG   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( long  long,
MPI_LONG_LONG_INT   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( unsigned  long,
MPI_UNSIGNED_LONG   
)
libMesh::Parallel::LIBMESH_INT_TYPE ( unsigned long  long,
MPI_UNSIGNED_LONG_LONG   
)
libMesh::Parallel::LIBMESH_PARALLEL_INTEGER_OPS ( unsigned long  long)
template<typename T , typename U >
void libMesh::Parallel::maxloc ( T &  r,
U &  max_id,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1051 of file parallel_implementation.h.

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

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

Definition at line 1040 of file parallel_implementation.h.

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

1043 { 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 1201 of file parallel_implementation.h.

1207 { 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 1210 of file parallel_implementation.h.

1215 { 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 1131 of file parallel_implementation.h.

1137 { 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 1140 of file parallel_implementation.h.

1145 { comm.send (dest_processor_id, buf, r, tag); }
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,
std::size_t  approx_buffer_size = 1000000 
)
inline

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

The data will be buffered in vectors with lengths that do not exceed the sum of approx_buffer_size and the size of an individual packed object.

Helper function for range packing

Definition at line 540 of file parallel_implementation.h.

References libMesh::Parallel::Packing< T >::pack(), libMesh::Parallel::Packing< T >::packable_size(), and libMesh::Parallel::Packing< T >::packed_size().

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

549 {
550  typedef typename std::iterator_traits<Iter>::value_type T;
551 
552  // Count the total size of and preallocate buffer for efficiency.
553  // Prepare to stop early if the buffer would be too large.
554  std::size_t buffer_size = 0;
555  Iter range_stop = range_begin;
556  for (; range_stop != range_end && buffer_size < approx_buffer_size;
557  ++range_stop)
558  {
559  std::size_t next_buffer_size =
560  Parallel::Packing<T>::packable_size(*range_stop, context);
561  buffer_size += next_buffer_size;
562  }
563  buffer.reserve(buffer.size() + buffer_size);
564 
565  // Pack the objects into the buffer
566  for (; range_begin != range_stop; ++range_begin)
567  {
568 #ifndef NDEBUG
569  std::size_t old_size = buffer.size();
570 #endif
571 
572  Parallel::Packing<T>::pack
573  (*range_begin, back_inserter(buffer), context);
574 
575 #ifndef NDEBUG
576  unsigned int my_packable_size =
577  Parallel::Packing<T>::packable_size(*range_begin, context);
578  unsigned int my_packed_size =
579  Parallel::Packing<T>::packed_size (buffer.begin() + old_size);
580  libmesh_assert_equal_to (my_packable_size, my_packed_size);
581  libmesh_assert_equal_to (buffer.size(), old_size + my_packable_size);
582 #endif
583  }
584 
585  return range_stop;
586 }
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 519 of file parallel_implementation.h.

References libMesh::Parallel::Packing< T >::packable_size().

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

522 {
523  typedef typename std::iterator_traits<Iter>::value_type T;
524 
525  std::size_t buffer_size = 0;
526  for (Iter range_count = range_begin;
527  range_count != range_end;
528  ++range_count)
529  {
530  buffer_size += Parallel::Packing<T>::packable_size(*range_count, context);
531  }
532  return buffer_size;
533 }
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
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 1155 of file parallel_implementation.h.

1160 { 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 1163 of file parallel_implementation.h.

1168 { 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 1171 of file parallel_implementation.h.

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

Definition at line 1180 of file parallel_implementation.h.

Referenced by libMesh::Parallel::Communicator::send_mode(), and libMesh::Parallel::Communicator::send_receive_packed_range().

1186 {
1187  comm.receive_packed_range (src_processor_id, context, out_iter,
1188  output_type, tag);
1189 }
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
const T &  data,
const MessageTag tag = no_tag,
const Communicator comm = Communicator_World 
)
inline
template<typename T >
void libMesh::Parallel::send ( const unsigned int  dest_processor_id,
const T &  data,
Request req,
const MessageTag tag = no_tag,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1084 of file parallel_implementation.h.

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

Definition at line 1092 of file parallel_implementation.h.

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

Definition at line 1100 of file parallel_implementation.h.

1106 { comm.send(dest_processor_id, data, type, req, tag); }
IterBase * data
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 1110 of file parallel_implementation.h.

Referenced by libMesh::Parallel::Communicator::send_mode(), and libMesh::Parallel::Communicator::send_receive_packed_range().

1116 { 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 1120 of file parallel_implementation.h.

1127 { 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 1218 of file parallel_implementation.h.

Referenced by libMesh::Parallel::Communicator::send_mode(), and libMesh::Parallel::Communicator::send_receive().

1225 { comm.send_receive(dest_processor_id, send, source_processor_id, recv,
1226  send_tag, recv_tag); }
void send(const unsigned int dest_processor_id, const T &data, const DataType &type, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
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 1250 of file parallel_implementation.h.

1259 { comm.send_receive(dest_processor_id, send, type1, source_processor_id,
1260  recv, type2, send_tag, recv_tag); }
void send(const unsigned int dest_processor_id, const T &data, const DataType &type, Request &req, const MessageTag &tag=no_tag, const Communicator &comm=Communicator_World)
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter , typename T >
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_iter,
const T *  output_type,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1230 of file parallel_implementation.h.

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

1241 {
1242  comm.send_receive_packed_range(dest_processor_id, context1,
1243  send_begin, send_end,
1244  source_processor_id, context2,
1245  out_iter, output_type,
1246  send_tag, recv_tag);
1247 }
template<typename T >
void libMesh::Parallel::set_union ( T &  data,
const unsigned int  root_id,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1062 of file parallel_implementation.h.

Referenced by libMesh::Nemesis_IO_Helper::compute_border_node_ids(), and libMesh::Parallel::Communicator::send_mode().

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

Definition at line 1067 of file parallel_implementation.h.

1069 { comm.set_union(data); }
IterBase * data
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 303 of file parallel_ghost_sync.h.

References libMesh::Parallel::SyncEverything::SyncEverything().

Referenced by libMesh::MeshTools::correct_node_proc_ids(), libMesh::MeshCommunication::gather_neighboring_elements(), libMesh::MeshRefinement::make_coarsening_compatible(), libMesh::MeshCommunication::make_elems_parallel_consistent(), libMesh::MeshRefinement::make_flags_parallel_consistent(), libMesh::MeshCommunication::make_node_unique_ids_parallel_consistent(), libMesh::MeshCommunication::make_p_levels_parallel_consistent(), libMesh::FEMSystem::mesh_position_set(), libMesh::LaplaceMeshSmoother::smooth(), and libMesh::MeshRefinement::uniformly_coarsen().

307 {
308  sync_dofobject_data_by_id(comm, range_begin, range_end, SyncEverything(), sync);
309 }
void sync_dofobject_data_by_id(const Communicator &comm, const Iterator &range_begin, const Iterator &range_end, const DofObjectCheckFunctor &dofobj_check, SyncFunctor &sync)
template<typename Iterator , typename DofObjectCheckFunctor , typename SyncFunctor >
void libMesh::Parallel::sync_dofobject_data_by_id ( const Communicator comm,
const Iterator &  range_begin,
const Iterator &  range_end,
const DofObjectCheckFunctor &  dofobj_check,
SyncFunctor &  sync 
)

Request data about a range of ghost dofobjects uniquely identified by their id.

Elements within the range can be excluded from the request by returning false from dofobj_check(dof_object)

Definition at line 314 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().

319 {
320  // This function must be run on all processors at once
321  libmesh_parallel_only(comm);
322 
323  // Count the objects to ask each processor about
324  std::vector<dof_id_type>
325  ghost_objects_from_proc(comm.size(), 0);
326 
327  for (Iterator it = range_begin; it != range_end; ++it)
328  {
329  DofObject * obj = *it;
330  libmesh_assert (obj);
331 
332  // We may want to pass Elem* or Node* to the check function, not
333  // just DofObject*
334  if (!dofobj_check(*it))
335  continue;
336 
337  processor_id_type obj_procid = obj->processor_id();
338  if (obj_procid != DofObject::invalid_processor_id)
339  ghost_objects_from_proc[obj_procid]++;
340  }
341 
342  // Request sets to send to each processor
343  std::vector<std::vector<dof_id_type> >
344  requested_objs_id(comm.size());
345 
346  // We know how many objects live on each processor, so reserve()
347  // space for each.
348  for (processor_id_type p=0; p != comm.size(); ++p)
349  if (p != comm.rank())
350  {
351  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
352  }
353  for (Iterator it = range_begin; it != range_end; ++it)
354  {
355  DofObject * obj = *it;
356 
357  if (!dofobj_check(*it))
358  continue;
359 
360  processor_id_type obj_procid = obj->processor_id();
361  if (obj_procid == comm.rank() ||
362  obj_procid == DofObject::invalid_processor_id)
363  continue;
364 
365  requested_objs_id[obj_procid].push_back(obj->id());
366  }
367 
368  // Trade requests with other processors
369  for (processor_id_type p=1; p != comm.size(); ++p)
370  {
371  // Trade my requests with processor procup and procdown
372  const processor_id_type procup =
373  cast_int<processor_id_type>
374  ((comm.rank() + p) % comm.size());
375  const processor_id_type procdown =
376  cast_int<processor_id_type>
377  ((comm.size() + comm.rank() - p) %
378  comm.size());
379  std::vector<dof_id_type> request_to_fill_id;
380  comm.send_receive(procup, requested_objs_id[procup],
381  procdown, request_to_fill_id);
382 
383  // Gather whatever data the user wants
384  std::vector<typename SyncFunctor::datum> data;
385  sync.gather_data(request_to_fill_id, data);
386 
387  // Trade back the results
388  std::vector<typename SyncFunctor::datum> received_data;
389  comm.send_receive(procdown, data,
390  procup, received_data);
391  libmesh_assert_equal_to (requested_objs_id[procup].size(),
392  received_data.size());
393 
394  // Let the user process the results
395  sync.act_on_data(requested_objs_id[procup], received_data);
396  }
397 }
uint8_t processor_id_type
Definition: id_types.h:99
libmesh_assert(j)
IterBase * 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 180 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().

185 {
186  // This function must be run on all processors at once
187  libmesh_parallel_only(comm);
188 
189  // We need a valid location_map
190 #ifdef DEBUG
191  bool need_map_update = (range_begin != range_end && location_map.empty());
192  comm.max(need_map_update);
193  libmesh_assert(!need_map_update);
194 #endif
195 
196  // Count the objectss to ask each processor about
197  std::vector<dof_id_type>
198  ghost_objects_from_proc(comm.size(), 0);
199 
200  for (Iterator it = range_begin; it != range_end; ++it)
201  {
202  DofObjType * obj = *it;
203  libmesh_assert (obj);
204  processor_id_type obj_procid = obj->processor_id();
205  if (obj_procid != DofObject::invalid_processor_id)
206  ghost_objects_from_proc[obj_procid]++;
207  }
208 
209  // Request sets to send to each processor
210  std::vector<std::vector<Real> >
211  requested_objs_x(comm.size()),
212  requested_objs_y(comm.size()),
213  requested_objs_z(comm.size());
214  // Corresponding ids to keep track of
215  std::vector<std::vector<dof_id_type> >
216  requested_objs_id(comm.size());
217 
218  // We know how many objects live on each processor, so reserve()
219  // space for each.
220  for (processor_id_type p=0; p != comm.size(); ++p)
221  if (p != comm.rank())
222  {
223  requested_objs_x[p].reserve(ghost_objects_from_proc[p]);
224  requested_objs_y[p].reserve(ghost_objects_from_proc[p]);
225  requested_objs_z[p].reserve(ghost_objects_from_proc[p]);
226  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
227  }
228  for (Iterator it = range_begin; it != range_end; ++it)
229  {
230  DofObjType * obj = *it;
231  processor_id_type obj_procid = obj->processor_id();
232  if (obj_procid == comm.rank() ||
233  obj_procid == DofObject::invalid_processor_id)
234  continue;
235 
236  Point p = location_map.point_of(*obj);
237  requested_objs_x[obj_procid].push_back(p(0));
238  requested_objs_y[obj_procid].push_back(p(1));
239  requested_objs_z[obj_procid].push_back(p(2));
240  requested_objs_id[obj_procid].push_back(obj->id());
241  }
242 
243  // Trade requests with other processors
244  for (processor_id_type p=1; p != comm.size(); ++p)
245  {
246  // Trade my requests with processor procup and procdown
247  const processor_id_type procup =
248  cast_int<processor_id_type>
249  ((comm.rank() + p) % comm.size());
250  const processor_id_type procdown =
251  cast_int<processor_id_type>
252  ((comm.size() + comm.rank() - p) %
253  comm.size());
254  std::vector<Real> request_to_fill_x,
255  request_to_fill_y,
256  request_to_fill_z;
257  comm.send_receive(procup, requested_objs_x[procup],
258  procdown, request_to_fill_x);
259  comm.send_receive(procup, requested_objs_y[procup],
260  procdown, request_to_fill_y);
261  comm.send_receive(procup, requested_objs_z[procup],
262  procdown, request_to_fill_z);
263 
264  // Find the local id of each requested object
265  std::vector<dof_id_type> request_to_fill_id(request_to_fill_x.size());
266  for (std::size_t i=0; i != request_to_fill_x.size(); ++i)
267  {
268  Point pt(request_to_fill_x[i],
269  request_to_fill_y[i],
270  request_to_fill_z[i]);
271 
272  // Look for this object in the multimap
273  DofObjType * obj = location_map.find(pt);
274 
275  // We'd better find every object we're asked for
276  libmesh_assert (obj);
277 
278  // Return the object's correct processor id,
279  // and our (correct if it's local) id for it.
280  request_to_fill_id[i] = obj->id();
281  }
282 
283  // Gather whatever data the user wants
284  std::vector<typename SyncFunctor::datum> data;
285  sync.gather_data(request_to_fill_id, data);
286 
287  // Trade back the results
288  std::vector<typename SyncFunctor::datum> received_data;
289  comm.send_receive(procdown, data,
290  procup, received_data);
291  libmesh_assert_equal_to (requested_objs_x[procup].size(),
292  received_data.size());
293 
294  // Let the user process the results
295  sync.act_on_data(requested_objs_id[procup], received_data);
296  }
297 }
uint8_t processor_id_type
Definition: id_types.h:99
libmesh_assert(j)
IterBase * 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 405 of file parallel_ghost_sync.h.

References libMesh::Elem::active(), libMesh::Elem::child_ptr(), libMesh::ParallelObject::comm(), data, libMesh::MeshBase::elem_ref(), 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().

409 {
410  const Communicator & comm (mesh.comm());
411 
412  // This function must be run on all processors at once
413  libmesh_parallel_only(comm);
414 
415  // Count the objects to ask each processor about
416  std::vector<dof_id_type>
417  ghost_objects_from_proc(comm.size(), 0);
418 
419  for (Iterator it = range_begin; it != range_end; ++it)
420  {
421  DofObject * obj = *it;
422  libmesh_assert (obj);
423  processor_id_type obj_procid = obj->processor_id();
424  if (obj_procid != DofObject::invalid_processor_id)
425  ghost_objects_from_proc[obj_procid]++;
426  }
427 
428  // Request sets to send to each processor
429  std::vector<std::vector<dof_id_type> >
430  requested_objs_id(comm.size()),
431  requested_objs_parent_id(comm.size());
432  std::vector<std::vector<unsigned char> >
433  requested_objs_child_num(comm.size());
434 
435  // We know how many objects live on each processor, so reserve()
436  // space for each.
437  for (processor_id_type p=0; p != comm.size(); ++p)
438  if (p != comm.rank())
439  {
440  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
441  requested_objs_parent_id[p].reserve(ghost_objects_from_proc[p]);
442  requested_objs_child_num[p].reserve(ghost_objects_from_proc[p]);
443  }
444 
445  for (Iterator it = range_begin; it != range_end; ++it)
446  {
447  Elem * elem = *it;
448  processor_id_type obj_procid = elem->processor_id();
449  if (obj_procid == comm.rank() ||
450  obj_procid == DofObject::invalid_processor_id)
451  continue;
452  const Elem * parent = elem->parent();
453  if (!parent || !elem->active())
454  continue;
455 
456  requested_objs_id[obj_procid].push_back(elem->id());
457  requested_objs_parent_id[obj_procid].push_back(parent->id());
458  requested_objs_child_num[obj_procid].push_back
459  (cast_int<unsigned char>
460  (parent->which_child_am_i(elem)));
461  }
462 
463  // Trade requests with other processors
464  for (processor_id_type p=1; p != comm.size(); ++p)
465  {
466  // Trade my requests with processor procup and procdown
467  const processor_id_type procup =
468  cast_int<processor_id_type>
469  ((comm.rank() + p) % comm.size());
470  const processor_id_type procdown =
471  cast_int<processor_id_type>
472  ((comm.size() + comm.rank() - p) %
473  comm.size());
474  std::vector<dof_id_type> request_to_fill_parent_id;
475  std::vector<unsigned char> request_to_fill_child_num;
476  comm.send_receive(procup, requested_objs_parent_id[procup],
477  procdown, request_to_fill_parent_id);
478  comm.send_receive(procup, requested_objs_child_num[procup],
479  procdown, request_to_fill_child_num);
480 
481  // Find the id of each requested element
482  std::size_t request_size = request_to_fill_parent_id.size();
483  std::vector<dof_id_type> request_to_fill_id(request_size);
484  for (std::size_t i=0; i != request_size; ++i)
485  {
486  Elem & parent = mesh.elem_ref(request_to_fill_parent_id[i]);
487  libmesh_assert(parent.has_children());
488  Elem * child = parent.child_ptr(request_to_fill_child_num[i]);
489  libmesh_assert(child);
490  libmesh_assert(child->active());
491  request_to_fill_id[i] = child->id();
492  }
493 
494  // Gather whatever data the user wants
495  std::vector<typename SyncFunctor::datum> data;
496  sync.gather_data(request_to_fill_id, data);
497 
498  // Trade back the results
499  std::vector<typename SyncFunctor::datum> received_data;
500  comm.send_receive(procdown, data,
501  procup, received_data);
502  libmesh_assert_equal_to (requested_objs_id[procup].size(),
503  received_data.size());
504 
505  // Let the user process the results
506  sync.act_on_data(requested_objs_id[procup], received_data);
507  }
508 }
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
libmesh_assert(j)
IterBase * data
template<typename ElemCheckFunctor , typename NodeCheckFunctor , 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,
const ElemCheckFunctor &  elem_check,
const NodeCheckFunctor &  node_check,
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.

Elements can be further excluded from the request by returning false from element_check(elem)

Nodes can be further excluded from the request by returning false from node_check(elem, local_node_num)

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 bool sync.act_on_data(const std::vector<unsigned int> & ids, std::vector<sync::datum> & data) and return true iff the response changed any data. The user must define Parallel::StandardType<sync::datum> if sync::datum isn't a built-in type.

Definition at line 525 of file parallel_ghost_sync.h.

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

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

531 {
532  const Communicator & comm (mesh.comm());
533 
534  // This function must be run on all processors at once
535  libmesh_parallel_only(comm);
536 
537  // Keep track of which nodes we've asked about, so we only hit each
538  // once?
539  // LIBMESH_BEST_UNORDERED_SET<dof_id_type> queried_nodes;
540 
541  // No. We need to ask every neighboring processor about every node,
542  // probably repeatedly. Imagine a vertex surrounded by triangles,
543  // each on a different processor, with a ghosting policy that
544  // include only face neighbors and not point neighbors. Then the
545  // only way for authoritative information to trickle out from that
546  // vertex is by being passed along, one neighbor at a time, to
547  // processors who mostly don't even see the node's true owner!
548 
549  bool need_sync = false;
550 
551  do
552  {
553  // This is the last sync we need, unless we later discover
554  // otherwise
555  need_sync = false;
556 
557  // Count the objects to ask each processor about
558  std::vector<dof_id_type>
559  ghost_objects_from_proc(comm.size(), 0);
560 
561  for (MeshBase::const_element_iterator it = range_begin;
562  it != range_end; ++it)
563  {
564  const Elem * elem = *it;
565  libmesh_assert (elem);
566 
567  if (!elem_check(elem))
568  continue;
569 
570  const processor_id_type proc_id = elem->processor_id();
571  if (proc_id == comm.rank() ||
572  proc_id == DofObject::invalid_processor_id)
573  continue;
574 
575  for (unsigned int n=0; n != elem->n_nodes(); ++n)
576  {
577  if (!node_check(elem, n))
578  continue;
579 
580  ghost_objects_from_proc[proc_id]++;
581  }
582  }
583 
584  // Now repeat that iteration, filling request sets this time.
585 
586  // Request sets to send to each processor
587  std::vector<std::vector<dof_id_type> >
588  requested_objs_elem_id(comm.size());
589  std::vector<std::vector<unsigned char> >
590  requested_objs_node_num(comm.size());
591 
592  // Keep track of current local ids for each too
593  std::vector<std::vector<dof_id_type> >
594  requested_objs_id(comm.size());
595 
596  // We know how many objects live on each processor, so reserve()
597  // space for each.
598  for (processor_id_type p=0; p != comm.size(); ++p)
599  if (p != comm.rank())
600  {
601  requested_objs_elem_id[p].reserve(ghost_objects_from_proc[p]);
602  requested_objs_node_num[p].reserve(ghost_objects_from_proc[p]);
603  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
604  }
605 
606  for (MeshBase::const_element_iterator it = range_begin;
607  it != range_end; ++it)
608  {
609  const Elem * elem = *it;
610  libmesh_assert (elem);
611 
612  if (!elem_check(elem))
613  continue;
614 
615  const processor_id_type proc_id = elem->processor_id();
616  if (proc_id == comm.rank() ||
617  proc_id == DofObject::invalid_processor_id)
618  continue;
619 
620  const dof_id_type elem_id = elem->id();
621 
622  for (unsigned int n=0; n != elem->n_nodes(); ++n)
623  {
624  if (!node_check(elem, n))
625  continue;
626 
627  const Node & node = elem->node_ref(n);
628  const dof_id_type node_id = node.id();
629 
630  requested_objs_elem_id[proc_id].push_back(elem_id);
631  requested_objs_node_num[proc_id].push_back
632  (cast_int<unsigned char>(n));
633  requested_objs_id[proc_id].push_back(node_id);
634  }
635  }
636 
637  // Trade requests with other processors
638  for (processor_id_type p=1; p != comm.size(); ++p)
639  {
640  // Trade my requests with processor procup and procdown
641  const processor_id_type procup =
642  cast_int<processor_id_type>
643  ((comm.rank() + p) % comm.size());
644  const processor_id_type procdown =
645  cast_int<processor_id_type>
646  ((comm.size() + comm.rank() - p) %
647  comm.size());
648 
649  libmesh_assert_equal_to (requested_objs_id[procup].size(),
650  ghost_objects_from_proc[procup]);
651  libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
652  ghost_objects_from_proc[procup]);
653  libmesh_assert_equal_to (requested_objs_node_num[procup].size(),
654  ghost_objects_from_proc[procup]);
655 
656  std::vector<dof_id_type> request_to_fill_elem_id;
657  std::vector<unsigned char> request_to_fill_node_num;
658  comm.send_receive(procup, requested_objs_elem_id[procup],
659  procdown, request_to_fill_elem_id);
660  comm.send_receive(procup, requested_objs_node_num[procup],
661  procdown, request_to_fill_node_num);
662 
663  // Find the id of each requested element
664  std::size_t request_size = request_to_fill_elem_id.size();
665  std::vector<dof_id_type> request_to_fill_id(request_size);
666  for (std::size_t i=0; i != request_size; ++i)
667  {
668  const Elem & elem = mesh.elem_ref(request_to_fill_elem_id[i]);
669 
670  const unsigned int n = request_to_fill_node_num[i];
671  libmesh_assert_less (n, elem.n_nodes());
672 
673  const Node & node = elem.node_ref(n);
674 
675  // This isn't a safe assertion in the case where we're
676  // synching processor ids
677  // libmesh_assert_equal_to (node->processor_id(), comm.rank());
678 
679  request_to_fill_id[i] = node.id();
680  }
681 
682  // Gather whatever data the user wants
683  std::vector<typename SyncFunctor::datum> data;
684  sync.gather_data(request_to_fill_id, data);
685 
686  // Trade back the results
687  std::vector<typename SyncFunctor::datum> received_data;
688  comm.send_receive(procdown, data,
689  procup, received_data);
690  libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
691  received_data.size());
692 
693  // Let the user process the results. If any of the results
694  // were different than what the user expected, then we'll
695  // need to sync again just in case this processor has to
696  // pass on the changes to yet another processor.
697  bool data_changed =
698  sync.act_on_data(requested_objs_id[procup], received_data);
699 
700  if (data_changed)
701  need_sync = true;
702  }
703  comm.max(need_sync);
704  } while (need_sync);
705 }
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
libmesh_assert(j)
IterBase * data
uint8_t dof_id_type
Definition: id_types.h:64
template<typename Context , typename buffertype , typename OutputIter , typename T >
void libMesh::Parallel::unpack_range ( const std::vector< buffertype > &  buffer,
Context *  context,
OutputIter  out_iter,
const T *   
)
inline

Helper function for range unpacking

Definition at line 595 of file parallel_implementation.h.

References libMesh::libmesh_assert(), libMesh::Parallel::Packing< T >::packed_size(), and libMesh::Parallel::Packing< T >::unpack().

599 {
600  // Loop through the buffer and unpack each object, returning the
601  // object pointer via the output iterator
602  typename std::vector<buffertype>::const_iterator
603  next_object_start = buffer.begin();
604 
605  while (next_object_start < buffer.end())
606  {
607  *out_iter++ = Parallel::Packing<T>::unpack(next_object_start, context);
608  next_object_start +=
609  Parallel::Packing<T>::packed_size(next_object_start);
610  }
611 
612  // We should have used up the exact amount of data in the buffer
613  libmesh_assert (next_object_start == buffer.end());
614 }
libmesh_assert(j)
template<typename Context , typename buffertype , typename OutputIter , typename T >
void libMesh::Parallel::unpack_range ( const typename std::vector< buffertype > &  buffer,
Context *  context,
OutputIter  out,
const T *  output_type 
)
inline
void libMesh::Parallel::wait ( std::vector< Request > &  r)
inline

Wait for a non-blocking send or receive to finish

Definition at line 566 of file parallel.h.

References wait().

567 { for (std::size_t i=0; i<r.size(); i++) r[i].wait(); }
void wait(std::vector< Request > &r)
Definition: parallel.h:566

Variable Documentation

const MessageTag libMesh::Parallel::any_tag = MessageTag(MPI_ANY_TAG)

Default message tag ids

Definition at line 273 of file parallel.h.

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

Communicator & libMesh::Parallel::Communicator_World = CommWorld
const MessageTag libMesh::Parallel::no_tag = MessageTag(0)

Definition at line 278 of file parallel.h.

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