libMesh::Parallel Namespace Reference

Namespaces

 Utils
 

Classes

struct  Attributes
 
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  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
 

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 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)
 
static void set_lowest (unsigned long long &x)
 
static void set_highest (unsigned long long &x)
 
 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)
 
libMesh::Parallel::StandardType< unsigned long long > has_min_max = true
 
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 1226 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().

1229 { 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 1232 of file parallel_implementation.h.

1235 { 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 1247 of file parallel_implementation.h.

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

1252 { 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 1255 of file parallel_implementation.h.

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

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

Definition at line 974 of file parallel_implementation.h.

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

975 {
976  comm.barrier();
977 }
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 1266 of file parallel_implementation.h.

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

1273 { 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 1359 of file parallel_implementation.h.

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

Definition at line 1356 of file parallel_implementation.h.

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

Definition at line 1350 of file parallel_implementation.h.

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

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

Definition at line 1353 of file parallel_implementation.h.

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

Definition at line 1362 of file parallel_implementation.h.

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

Definition at line 1347 of file parallel_implementation.h.

1347 { 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 1213 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().

1217 { 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 1220 of file parallel_implementation.h.

1223 { 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 1238 of file parallel_implementation.h.

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

1244 { comm.gather_packed_range(root_id, context, range_begin, range_end, out_iter); }
libMesh::Parallel::LIBMESH_CONTAINER_TYPE ( std::set  )

Referenced by set_highest().

libMesh::Parallel::LIBMESH_CONTAINER_TYPE ( std::vector  )
libMesh::Parallel::LIBMESH_FLOAT_TYPE ( float  ,
MPI_FLOAT   
)

Referenced by set_highest().

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   
)
template<typename T , typename U >
void libMesh::Parallel::maxloc ( T &  r,
U &  max_id,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1001 of file parallel_implementation.h.

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

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

Definition at line 990 of file parallel_implementation.h.

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

993 { 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 1151 of file parallel_implementation.h.

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

1165 { 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 1081 of file parallel_implementation.h.

1087 { 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 1090 of file parallel_implementation.h.

1095 { 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 490 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().

499 {
500  typedef typename std::iterator_traits<Iter>::value_type T;
501 
502  // Count the total size of and preallocate buffer for efficiency.
503  // Prepare to stop early if the buffer would be too large.
504  std::size_t buffer_size = 0;
505  Iter range_stop = range_begin;
506  for (; range_stop != range_end && buffer_size < approx_buffer_size;
507  ++range_stop)
508  {
509  std::size_t next_buffer_size =
510  Parallel::Packing<T>::packable_size(*range_stop, context);
511  buffer_size += next_buffer_size;
512  }
513  buffer.reserve(buffer.size() + buffer_size);
514 
515  // Pack the objects into the buffer
516  for (; range_begin != range_stop; ++range_begin)
517  {
518 #ifndef NDEBUG
519  std::size_t old_size = buffer.size();
520 #endif
521 
522  Parallel::Packing<T>::pack
523  (*range_begin, back_inserter(buffer), context);
524 
525 #ifndef NDEBUG
526  unsigned int my_packable_size =
527  Parallel::Packing<T>::packable_size(*range_begin, context);
528  unsigned int my_packed_size =
529  Parallel::Packing<T>::packed_size (buffer.begin() + old_size);
530  libmesh_assert_equal_to (my_packable_size, my_packed_size);
531  libmesh_assert_equal_to (buffer.size(), old_size + my_packable_size);
532 #endif
533  }
534 
535  return range_stop;
536 }
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 469 of file parallel_implementation.h.

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

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

472 {
473  typedef typename std::iterator_traits<Iter>::value_type T;
474 
475  std::size_t buffer_size = 0;
476  for (Iter range_count = range_begin;
477  range_count != range_end;
478  ++range_count)
479  {
480  buffer_size += Parallel::Packing<T>::packable_size(*range_count, context);
481  }
482  return buffer_size;
483 }
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 1105 of file parallel_implementation.h.

1110 { 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 1113 of file parallel_implementation.h.

1118 { 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 1121 of file parallel_implementation.h.

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

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

1136 {
1137  comm.receive_packed_range (src_processor_id, context, out_iter,
1138  output_type, tag);
1139 }
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 1034 of file parallel_implementation.h.

1039 { 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 1042 of file parallel_implementation.h.

1047 { 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 1050 of file parallel_implementation.h.

1056 { 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 1060 of file parallel_implementation.h.

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

1066 { 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 1070 of file parallel_implementation.h.

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

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

1175 { comm.send_receive(dest_processor_id, send, source_processor_id, recv,
1176  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 1200 of file parallel_implementation.h.

1209 { comm.send_receive(dest_processor_id, send, type1, source_processor_id,
1210  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 1180 of file parallel_implementation.h.

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

1191 {
1192  comm.send_receive_packed_range(dest_processor_id, context1,
1193  send_begin, send_end,
1194  source_processor_id, context2,
1195  out_iter, output_type,
1196  send_tag, recv_tag);
1197 }
static void libMesh::Parallel::set_highest ( unsigned long long &  x)
static

Definition at line 132 of file parallel_implementation.h.

References LIBMESH_CONTAINER_TYPE(), LIBMESH_FLOAT_TYPE(), and max().

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

PetscErrorCode Vec x
void max(T &r, const Communicator &comm=Communicator_World)
static void libMesh::Parallel::set_lowest ( unsigned long long &  x)
static

Definition at line 131 of file parallel_implementation.h.

References min().

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

PetscErrorCode Vec x
void min(T &r, const Communicator &comm=Communicator_World)
template<typename T >
void libMesh::Parallel::set_union ( T &  data,
const unsigned int  root_id,
const Communicator comm = Communicator_World 
)
inline

Definition at line 1012 of file parallel_implementation.h.

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

1014 { 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 1017 of file parallel_implementation.h.

1019 { comm.set_union(data); }
IterBase * 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 273 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::MeshTools::correct_node_proc_ids(), libMesh::MeshCommunication::gather_neighboring_elements(), 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(), and libMesh::LaplaceMeshSmoother::smooth().

277 {
278  // This function must be run on all processors at once
279  libmesh_parallel_only(comm);
280 
281  // Count the objects to ask each processor about
282  std::vector<dof_id_type>
283  ghost_objects_from_proc(comm.size(), 0);
284 
285  for (Iterator it = range_begin; it != range_end; ++it)
286  {
287  DofObject * obj = *it;
288  libmesh_assert (obj);
289  processor_id_type obj_procid = obj->processor_id();
290  if (obj_procid != DofObject::invalid_processor_id)
291  ghost_objects_from_proc[obj_procid]++;
292  }
293 
294  // Request sets to send to each processor
295  std::vector<std::vector<dof_id_type> >
296  requested_objs_id(comm.size());
297 
298  // We know how many objects live on each processor, so reserve()
299  // space for each.
300  for (processor_id_type p=0; p != comm.size(); ++p)
301  if (p != comm.rank())
302  {
303  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
304  }
305  for (Iterator it = range_begin; it != range_end; ++it)
306  {
307  DofObject * obj = *it;
308  processor_id_type obj_procid = obj->processor_id();
309  if (obj_procid == comm.rank() ||
310  obj_procid == DofObject::invalid_processor_id)
311  continue;
312 
313  requested_objs_id[obj_procid].push_back(obj->id());
314  }
315 
316  // Trade requests with other processors
317  for (processor_id_type p=1; p != comm.size(); ++p)
318  {
319  // Trade my requests with processor procup and procdown
320  const processor_id_type procup =
321  cast_int<processor_id_type>
322  ((comm.rank() + p) % comm.size());
323  const processor_id_type procdown =
324  cast_int<processor_id_type>
325  ((comm.size() + comm.rank() - p) %
326  comm.size());
327  std::vector<dof_id_type> request_to_fill_id;
328  comm.send_receive(procup, requested_objs_id[procup],
329  procdown, request_to_fill_id);
330 
331  // Gather whatever data the user wants
332  std::vector<typename SyncFunctor::datum> data;
333  sync.gather_data(request_to_fill_id, data);
334 
335  // Trade back the results
336  std::vector<typename SyncFunctor::datum> received_data;
337  comm.send_receive(procdown, data,
338  procup, received_data);
339  libmesh_assert_equal_to (requested_objs_id[procup].size(),
340  received_data.size());
341 
342  // Let the user process the results
343  sync.act_on_data(requested_objs_id[procup], received_data);
344  }
345 }
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 150 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().

155 {
156  // This function must be run on all processors at once
157  libmesh_parallel_only(comm);
158 
159  // We need a valid location_map
160 #ifdef DEBUG
161  bool need_map_update = (range_begin != range_end && location_map.empty());
162  comm.max(need_map_update);
163  libmesh_assert(!need_map_update);
164 #endif
165 
166  // Count the objectss to ask each processor about
167  std::vector<dof_id_type>
168  ghost_objects_from_proc(comm.size(), 0);
169 
170  for (Iterator it = range_begin; it != range_end; ++it)
171  {
172  DofObjType * obj = *it;
173  libmesh_assert (obj);
174  processor_id_type obj_procid = obj->processor_id();
175  if (obj_procid != DofObject::invalid_processor_id)
176  ghost_objects_from_proc[obj_procid]++;
177  }
178 
179  // Request sets to send to each processor
180  std::vector<std::vector<Real> >
181  requested_objs_x(comm.size()),
182  requested_objs_y(comm.size()),
183  requested_objs_z(comm.size());
184  // Corresponding ids to keep track of
185  std::vector<std::vector<dof_id_type> >
186  requested_objs_id(comm.size());
187 
188  // We know how many objects live on each processor, so reserve()
189  // space for each.
190  for (processor_id_type p=0; p != comm.size(); ++p)
191  if (p != comm.rank())
192  {
193  requested_objs_x[p].reserve(ghost_objects_from_proc[p]);
194  requested_objs_y[p].reserve(ghost_objects_from_proc[p]);
195  requested_objs_z[p].reserve(ghost_objects_from_proc[p]);
196  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
197  }
198  for (Iterator it = range_begin; it != range_end; ++it)
199  {
200  DofObjType * obj = *it;
201  processor_id_type obj_procid = obj->processor_id();
202  if (obj_procid == comm.rank() ||
203  obj_procid == DofObject::invalid_processor_id)
204  continue;
205 
206  Point p = location_map.point_of(*obj);
207  requested_objs_x[obj_procid].push_back(p(0));
208  requested_objs_y[obj_procid].push_back(p(1));
209  requested_objs_z[obj_procid].push_back(p(2));
210  requested_objs_id[obj_procid].push_back(obj->id());
211  }
212 
213  // Trade requests with other processors
214  for (processor_id_type p=1; p != comm.size(); ++p)
215  {
216  // Trade my requests with processor procup and procdown
217  const processor_id_type procup =
218  cast_int<processor_id_type>
219  ((comm.rank() + p) % comm.size());
220  const processor_id_type procdown =
221  cast_int<processor_id_type>
222  ((comm.size() + comm.rank() - p) %
223  comm.size());
224  std::vector<Real> request_to_fill_x,
225  request_to_fill_y,
226  request_to_fill_z;
227  comm.send_receive(procup, requested_objs_x[procup],
228  procdown, request_to_fill_x);
229  comm.send_receive(procup, requested_objs_y[procup],
230  procdown, request_to_fill_y);
231  comm.send_receive(procup, requested_objs_z[procup],
232  procdown, request_to_fill_z);
233 
234  // Find the local id of each requested object
235  std::vector<dof_id_type> request_to_fill_id(request_to_fill_x.size());
236  for (std::size_t i=0; i != request_to_fill_x.size(); ++i)
237  {
238  Point pt(request_to_fill_x[i],
239  request_to_fill_y[i],
240  request_to_fill_z[i]);
241 
242  // Look for this object in the multimap
243  DofObjType * obj = location_map.find(pt);
244 
245  // We'd better find every object we're asked for
246  libmesh_assert (obj);
247 
248  // Return the object's correct processor id,
249  // and our (correct if it's local) id for it.
250  request_to_fill_id[i] = obj->id();
251  }
252 
253  // Gather whatever data the user wants
254  std::vector<typename SyncFunctor::datum> data;
255  sync.gather_data(request_to_fill_id, data);
256 
257  // Trade back the results
258  std::vector<typename SyncFunctor::datum> received_data;
259  comm.send_receive(procdown, data,
260  procup, received_data);
261  libmesh_assert_equal_to (requested_objs_x[procup].size(),
262  received_data.size());
263 
264  // Let the user process the results
265  sync.act_on_data(requested_objs_id[procup], received_data);
266  }
267 }
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 353 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().

357 {
358  const Communicator & comm (mesh.comm());
359 
360  // This function must be run on all processors at once
361  libmesh_parallel_only(comm);
362 
363  // Count the objects to ask each processor about
364  std::vector<dof_id_type>
365  ghost_objects_from_proc(comm.size(), 0);
366 
367  for (Iterator it = range_begin; it != range_end; ++it)
368  {
369  DofObject * obj = *it;
370  libmesh_assert (obj);
371  processor_id_type obj_procid = obj->processor_id();
372  if (obj_procid != DofObject::invalid_processor_id)
373  ghost_objects_from_proc[obj_procid]++;
374  }
375 
376  // Request sets to send to each processor
377  std::vector<std::vector<dof_id_type> >
378  requested_objs_id(comm.size()),
379  requested_objs_parent_id(comm.size());
380  std::vector<std::vector<unsigned char> >
381  requested_objs_child_num(comm.size());
382 
383  // We know how many objects live on each processor, so reserve()
384  // space for each.
385  for (processor_id_type p=0; p != comm.size(); ++p)
386  if (p != comm.rank())
387  {
388  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
389  requested_objs_parent_id[p].reserve(ghost_objects_from_proc[p]);
390  requested_objs_child_num[p].reserve(ghost_objects_from_proc[p]);
391  }
392 
393  for (Iterator it = range_begin; it != range_end; ++it)
394  {
395  Elem * elem = *it;
396  processor_id_type obj_procid = elem->processor_id();
397  if (obj_procid == comm.rank() ||
398  obj_procid == DofObject::invalid_processor_id)
399  continue;
400  const Elem * parent = elem->parent();
401  if (!parent || !elem->active())
402  continue;
403 
404  requested_objs_id[obj_procid].push_back(elem->id());
405  requested_objs_parent_id[obj_procid].push_back(parent->id());
406  requested_objs_child_num[obj_procid].push_back
407  (cast_int<unsigned char>
408  (parent->which_child_am_i(elem)));
409  }
410 
411  // Trade requests with other processors
412  for (processor_id_type p=1; p != comm.size(); ++p)
413  {
414  // Trade my requests with processor procup and procdown
415  const processor_id_type procup =
416  cast_int<processor_id_type>
417  ((comm.rank() + p) % comm.size());
418  const processor_id_type procdown =
419  cast_int<processor_id_type>
420  ((comm.size() + comm.rank() - p) %
421  comm.size());
422  std::vector<dof_id_type> request_to_fill_parent_id;
423  std::vector<unsigned char> request_to_fill_child_num;
424  comm.send_receive(procup, requested_objs_parent_id[procup],
425  procdown, request_to_fill_parent_id);
426  comm.send_receive(procup, requested_objs_child_num[procup],
427  procdown, request_to_fill_child_num);
428 
429  // Find the id of each requested element
430  std::size_t request_size = request_to_fill_parent_id.size();
431  std::vector<dof_id_type> request_to_fill_id(request_size);
432  for (std::size_t i=0; i != request_size; ++i)
433  {
434  Elem & parent = mesh.elem_ref(request_to_fill_parent_id[i]);
435  libmesh_assert(parent.has_children());
436  Elem * child = parent.child_ptr(request_to_fill_child_num[i]);
437  libmesh_assert(child);
438  libmesh_assert(child->active());
439  request_to_fill_id[i] = child->id();
440  }
441 
442  // Gather whatever data the user wants
443  std::vector<typename SyncFunctor::datum> data;
444  sync.gather_data(request_to_fill_id, data);
445 
446  // Trade back the results
447  std::vector<typename SyncFunctor::datum> received_data;
448  comm.send_receive(procdown, data,
449  procup, received_data);
450  libmesh_assert_equal_to (requested_objs_id[procup].size(),
451  received_data.size());
452 
453  // Let the user process the results
454  sync.act_on_data(requested_objs_id[procup], received_data);
455  }
456 }
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 484 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().

490 {
491  const Communicator & comm (mesh.comm());
492 
493  // This function must be run on all processors at once
494  libmesh_parallel_only(comm);
495 
496  // Keep track of which nodes we've asked about, so we only hit each
497  // once?
498  // LIBMESH_BEST_UNORDERED_SET<dof_id_type> queried_nodes;
499 
500  // No. We need to ask every neighboring processor about every node,
501  // probably repeatedly. Imagine a vertex surrounded by triangles,
502  // each on a different processor, with a ghosting policy that
503  // include only face neighbors and not point neighbors. Then the
504  // only way for authoritative information to trickle out from that
505  // vertex is by being passed along, one neighbor at a time, to
506  // processors who mostly don't even see the node's true owner!
507 
508  bool need_sync = false;
509 
510  do
511  {
512  // This is the last sync we need, unless we later discover
513  // otherwise
514  need_sync = false;
515 
516  // Count the objects to ask each processor about
517  std::vector<dof_id_type>
518  ghost_objects_from_proc(comm.size(), 0);
519 
520  for (MeshBase::const_element_iterator it = range_begin;
521  it != range_end; ++it)
522  {
523  const Elem * elem = *it;
524  libmesh_assert (elem);
525 
526  if (!elem_check(elem))
527  continue;
528 
529  const processor_id_type proc_id = elem->processor_id();
530  if (proc_id == comm.rank() ||
531  proc_id == DofObject::invalid_processor_id)
532  continue;
533 
534  for (unsigned int n=0; n != elem->n_nodes(); ++n)
535  {
536  if (!node_check(elem, n))
537  continue;
538 
539  ghost_objects_from_proc[proc_id]++;
540  }
541  }
542 
543  // Now repeat that iteration, filling request sets this time.
544 
545  // Request sets to send to each processor
546  std::vector<std::vector<dof_id_type> >
547  requested_objs_elem_id(comm.size());
548  std::vector<std::vector<unsigned char> >
549  requested_objs_node_num(comm.size());
550 
551  // Keep track of current local ids for each too
552  std::vector<std::vector<dof_id_type> >
553  requested_objs_id(comm.size());
554 
555  // We know how many objects live on each processor, so reserve()
556  // space for each.
557  for (processor_id_type p=0; p != comm.size(); ++p)
558  if (p != comm.rank())
559  {
560  requested_objs_elem_id[p].reserve(ghost_objects_from_proc[p]);
561  requested_objs_node_num[p].reserve(ghost_objects_from_proc[p]);
562  requested_objs_id[p].reserve(ghost_objects_from_proc[p]);
563  }
564 
565  for (MeshBase::const_element_iterator it = range_begin;
566  it != range_end; ++it)
567  {
568  const Elem * elem = *it;
569  libmesh_assert (elem);
570 
571  if (!elem_check(elem))
572  continue;
573 
574  const processor_id_type proc_id = elem->processor_id();
575  if (proc_id == comm.rank() ||
576  proc_id == DofObject::invalid_processor_id)
577  continue;
578 
579  const dof_id_type elem_id = elem->id();
580 
581  for (unsigned int n=0; n != elem->n_nodes(); ++n)
582  {
583  if (!node_check(elem, n))
584  continue;
585 
586  const Node & node = elem->node_ref(n);
587  const dof_id_type node_id = node.id();
588 
589  requested_objs_elem_id[proc_id].push_back(elem_id);
590  requested_objs_node_num[proc_id].push_back
591  (cast_int<unsigned char>(n));
592  requested_objs_id[proc_id].push_back(node_id);
593  }
594  }
595 
596  // Trade requests with other processors
597  for (processor_id_type p=1; p != comm.size(); ++p)
598  {
599  // Trade my requests with processor procup and procdown
600  const processor_id_type procup =
601  cast_int<processor_id_type>
602  ((comm.rank() + p) % comm.size());
603  const processor_id_type procdown =
604  cast_int<processor_id_type>
605  ((comm.size() + comm.rank() - p) %
606  comm.size());
607 
608  libmesh_assert_equal_to (requested_objs_id[procup].size(),
609  ghost_objects_from_proc[procup]);
610  libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
611  ghost_objects_from_proc[procup]);
612  libmesh_assert_equal_to (requested_objs_node_num[procup].size(),
613  ghost_objects_from_proc[procup]);
614 
615  std::vector<dof_id_type> request_to_fill_elem_id;
616  std::vector<unsigned char> request_to_fill_node_num;
617  comm.send_receive(procup, requested_objs_elem_id[procup],
618  procdown, request_to_fill_elem_id);
619  comm.send_receive(procup, requested_objs_node_num[procup],
620  procdown, request_to_fill_node_num);
621 
622  // Find the id of each requested element
623  std::size_t request_size = request_to_fill_elem_id.size();
624  std::vector<dof_id_type> request_to_fill_id(request_size);
625  for (std::size_t i=0; i != request_size; ++i)
626  {
627  const Elem & elem = mesh.elem_ref(request_to_fill_elem_id[i]);
628 
629  const unsigned int n = request_to_fill_node_num[i];
630  libmesh_assert_less (n, elem.n_nodes());
631 
632  const Node & node = elem.node_ref(n);
633 
634  // This isn't a safe assertion in the case where we're
635  // synching processor ids
636  // libmesh_assert_equal_to (node->processor_id(), comm.rank());
637 
638  request_to_fill_id[i] = node.id();
639  }
640 
641  // Gather whatever data the user wants
642  std::vector<typename SyncFunctor::datum> data;
643  sync.gather_data(request_to_fill_id, data);
644 
645  // Trade back the results
646  std::vector<typename SyncFunctor::datum> received_data;
647  comm.send_receive(procdown, data,
648  procup, received_data);
649  libmesh_assert_equal_to (requested_objs_elem_id[procup].size(),
650  received_data.size());
651 
652  // Let the user process the results. If any of the results
653  // were different than what the user expected, then we'll
654  // need to sync again just in case this processor has to
655  // pass on the changes to yet another processor.
656  bool data_changed =
657  sync.act_on_data(requested_objs_id[procup], received_data);
658 
659  if (data_changed)
660  need_sync = true;
661  }
662  comm.max(need_sync);
663  } while (need_sync);
664 }
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 545 of file parallel_implementation.h.

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

549 {
550  // Loop through the buffer and unpack each object, returning the
551  // object pointer via the output iterator
552  typename std::vector<buffertype>::const_iterator
553  next_object_start = buffer.begin();
554 
555  while (next_object_start < buffer.end())
556  {
557  *out_iter++ = Parallel::Packing<T>::unpack(next_object_start, context);
558  next_object_start +=
559  Parallel::Packing<T>::packed_size(next_object_start);
560  }
561 
562  // We should have used up the exact amount of data in the buffer
563  libmesh_assert (next_object_start == buffer.end());
564 }
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 524 of file parallel.h.

References wait().

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

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
libMesh::Parallel::StandardType< unsigned long long > libMesh::Parallel::has_min_max = true
const MessageTag libMesh::Parallel::no_tag = MessageTag(0)

Definition at line 278 of file parallel.h.

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