$extrastylesheet
libMesh::Parallel::Communicator Class Reference

#include <parallel.h>

List of all members.

Public Types

enum  SendMode { DEFAULT = 0, SYNCHRONOUS }

Public Member Functions

 Communicator ()
 Communicator (const communicator &comm)
 ~Communicator ()
void split (int color, int key, Communicator &target) const
void duplicate (const Communicator &comm)
void duplicate (const communicator &comm)
communicatorget ()
const communicatorget () const
MessageTag get_unique_tag (int tagvalue) const
void reference_unique_tag (int tagvalue) const
void dereference_unique_tag (int tagvalue) const
void clear ()
Communicatoroperator= (const communicator &comm)
unsigned int rank () const
unsigned int size () const
void send_mode (const SendMode sm)
SendMode send_mode () const
void barrier () const
template<typename T >
bool verify (const T &r) const
template<typename T >
bool semiverify (const T *r) const
template<typename T >
void min (T &r) const
template<typename T >
void minloc (T &r, unsigned int &min_id) const
template<typename T >
void minloc (std::vector< T > &r, std::vector< unsigned int > &min_id) const
template<typename T >
void max (T &r) const
template<typename T >
void maxloc (T &r, unsigned int &max_id) const
template<typename T >
void maxloc (std::vector< T > &r, std::vector< unsigned int > &max_id) const
template<typename T >
void sum (T &r) const
template<typename T >
void set_union (T &data, const unsigned int root_id) const
template<typename T >
void set_union (T &data) const
status probe (const unsigned int src_processor_id, const MessageTag &tag=any_tag) const
template<typename T >
void send (const unsigned int dest_processor_id, T &buf, const MessageTag &tag=no_tag) const
template<typename T >
void send (const unsigned int dest_processor_id, T &buf, Request &req, const MessageTag &tag=no_tag) const
template<typename T >
void send (const unsigned int dest_processor_id, T &buf, const DataType &type, const MessageTag &tag=no_tag) const
template<typename T >
void send (const unsigned int dest_processor_id, T &buf, const DataType &type, Request &req, const MessageTag &tag=no_tag) const
template<typename T >
Status receive (const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
template<typename T >
void receive (const unsigned int dest_processor_id, T &buf, Request &req, const MessageTag &tag=any_tag) const
template<typename T >
Status receive (const unsigned int dest_processor_id, T &buf, const DataType &type, const MessageTag &tag=any_tag) const
template<typename T >
void receive (const unsigned int dest_processor_id, T &buf, const DataType &type, Request &req, const MessageTag &tag=any_tag) const
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
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
template<typename Context , typename OutputIter >
void receive_packed_range (const unsigned int dest_processor_id, Context *context, OutputIter out, const MessageTag &tag=any_tag) const
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
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter >
void send_receive_packed_range (const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
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
template<typename T >
void gather (const unsigned int root_id, T send, std::vector< T > &recv) const
template<typename T >
void gather (const unsigned int root_id, std::vector< T > &r) const
template<typename T >
void allgather (T send, std::vector< T > &recv) const
template<typename T >
void allgather (std::vector< T > &r, const bool identical_buffer_sizes=false) const
template<typename Context , typename Iter , typename OutputIter >
void gather_packed_range (const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out) const
template<typename Context , typename Iter , typename OutputIter >
void allgather_packed_range (Context *context, Iter range_begin, const Iter range_end, OutputIter out) const
template<typename T >
void alltoall (std::vector< T > &r) const
template<typename T >
void broadcast (T &data, const unsigned int root_id=0) const
template<typename Context , typename OutputContext , typename Iter , typename OutputIter >
void broadcast_packed_range (const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out, const unsigned int root_id=0) const
template<typename T >
bool semiverify (const std::vector< T > *r) const
template<typename T >
void min (std::vector< T > &r) const
template<typename T >
void max (std::vector< T > &r) const
template<typename T >
void sum (std::vector< T > &r) const
template<typename T >
void sum (std::complex< T > &r) const
template<typename T >
void sum (std::vector< std::complex< T > > &r) const
template<typename T >
void set_union (std::set< T > &data, const unsigned int root_id) const
template<typename T >
void set_union (std::set< T > &data) const
template<typename T >
void send (const unsigned int dest_processor_id, std::basic_string< T > &buf, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::basic_string< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::set< T > &buf, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::set< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::set< T > &buf, const DataType &type, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::set< T > &buf, const DataType &type, Request &req, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::vector< T > &buf, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::vector< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::vector< T > &buf, const DataType &type, const MessageTag &tag) const
template<typename T >
void send (const unsigned int dest_processor_id, std::vector< T > &buf, const DataType &type, Request &req, const MessageTag &tag) const
template<typename T >
Status receive (const unsigned int src_processor_id, std::basic_string< T > &buf, const MessageTag &tag) const
template<typename T >
void receive (const unsigned int src_processor_id, std::basic_string< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
Status receive (const unsigned int src_processor_id, std::set< T > &buf, const MessageTag &tag) const
template<typename T >
void receive (const unsigned int src_processor_id, std::set< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
Status receive (const unsigned int src_processor_id, std::set< T > &buf, const DataType &type, const MessageTag &tag) const
template<typename T >
void receive (const unsigned int src_processor_id, std::set< T > &buf, const DataType &type, Request &req, const MessageTag &tag) const
template<typename T >
Status receive (const unsigned int src_processor_id, std::vector< T > &buf, const MessageTag &tag) const
template<typename T >
void receive (const unsigned int src_processor_id, std::vector< T > &buf, Request &req, const MessageTag &tag) const
template<typename T >
Status receive (const unsigned int src_processor_id, std::vector< T > &buf, const DataType &type, const MessageTag &tag) const
template<typename T >
void receive (const unsigned int src_processor_id, std::vector< T > &buf, const DataType &type, Request &req, const MessageTag &tag) const
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, std::vector< T1 > &sendvec, const DataType &type1, const unsigned int source_processor_id, std::vector< T2 > &recv, const DataType &type2, const MessageTag &send_tag, const MessageTag &recv_tag) const
template<typename T >
void send_receive (const unsigned int dest_processor_id, std::vector< T > &sendvec, const unsigned int source_processor_id, std::vector< T > &recv, const MessageTag &send_tag, const MessageTag &recv_tag) const
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, std::vector< T1 > &sendvec, const unsigned int source_processor_id, std::vector< T2 > &recv, const MessageTag &send_tag, const MessageTag &recv_tag) const
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, std::vector< std::vector< T1 > > &sendvec, const unsigned int source_processor_id, std::vector< std::vector< T2 > > &recv, const MessageTag &, const MessageTag &) const
template<typename T >
void send_receive (const unsigned int dest_processor_id, std::vector< std::vector< T > > &sendvec, const unsigned int source_processor_id, std::vector< std::vector< T > > &recv, const MessageTag &, const MessageTag &) const
template<typename T >
void broadcast (std::basic_string< T > &data, const unsigned int root_id) const
template<typename T >
void broadcast (std::vector< T > &data, const unsigned int root_id) const
template<typename T >
void broadcast (std::vector< std::basic_string< T > > &data, const unsigned int root_id) const
template<typename T >
void broadcast (std::set< T > &data, const unsigned int root_id) const

Private Member Functions

 Communicator (const Communicator &)
void assign (const communicator &comm)

Private Attributes

communicator _communicator
unsigned int _rank
unsigned int _size
SendMode _send_mode
std::map< int, unsigned int > used_tag_values
bool _I_duped_it

Detailed Description

Encapsulates the MPI_Comm object. Allows the size of the group and this process's position in the group to be determined.

Methods of this object are the preferred way to perform distributed-memory parallel operations.

Definition at line 579 of file parallel.h.


Member Enumeration Documentation

Whether to use default or synchronous sends?

Enumerator:
DEFAULT 
SYNCHRONOUS 

Definition at line 652 of file parallel.h.


Constructor & Destructor Documentation

Default Constructor.

Definition at line 469 of file parallel_implementation.h.

                                   :
#ifdef LIBMESH_HAVE_MPI
  _communicator(MPI_COMM_SELF),
#endif
  _rank(0),
  _size(1),
  _send_mode(DEFAULT),
  used_tag_values(),
  _I_duped_it(false) {}
libMesh::Parallel::Communicator::Communicator ( const communicator comm) [inline, explicit]

Definition at line 479 of file parallel_implementation.h.

References assign().

                                                           :
#ifdef LIBMESH_HAVE_MPI
  _communicator(MPI_COMM_SELF),
#endif
  _rank(0),
  _size(1),
  _send_mode(DEFAULT),
  used_tag_values(),
  _I_duped_it(false)
{
  this->assign(comm);
}

Definition at line 492 of file parallel_implementation.h.

References clear().

                                    {
  this->clear();
}
libMesh::Parallel::Communicator::Communicator ( const Communicator ) [inline, explicit, private]

Definition at line 547 of file parallel_implementation.h.

                                                       :
#ifdef LIBMESH_HAVE_MPI
  _communicator(MPI_COMM_NULL),
#endif
  _rank(0),
  _size(1),
  _send_mode(DEFAULT),
  used_tag_values(),
  _I_duped_it(false)
{
  libmesh_not_implemented();
}

Member Function Documentation

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

Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that processor

Definition at line 2892 of file parallel_implementation.h.

References libMesh::libmesh_assert(), size(), and libMesh::START_LOG().

Referenced by libMesh::Parallel::allgather(), libMesh::LaplaceMeshSmoother::allgather_graph(), libMesh::Nemesis_IO_Helper::compute_num_global_elem_blocks(), libMesh::DofMap::distribute_dofs(), libMesh::MeshCommunication::find_global_indices(), libMesh::MeshRefinement::flag_elements_by_elem_fraction(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), gather(), libMesh::ParmetisPartitioner::initialize(), libMesh::Nemesis_IO::read(), libMesh::DofMap::set_nonlocal_dof_objects(), and set_union().

{
  START_LOG ("allgather()","Parallel");

  libmesh_assert(this->size());
  recv.resize(this->size());

  unsigned int comm_size = this->size();
  if (comm_size > 1)
    {
      StandardType<T> send_type(&sendval);

      MPI_Allgather (&sendval,
                     1,
                     send_type,
                     &recv[0],
                     1,
                     send_type,
                     this->get());
    }
  else if (comm_size > 0)
    recv[0] = sendval;

  STOP_LOG ("allgather()","Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::allgather ( std::vector< T > &  r,
const bool  identical_buffer_sizes = false 
) const [inline]

Take a vector of local variables and expand it to include values from all processors. By default, each processor is allowed to have its own unique input buffer length. If it is known that all processors have the same input sizes additional communication can be avoided.

Specifically, this function transforms this:

   * Processor 0: [ ... N_0 ]
   * Processor 1: [ ....... N_1 ]
   * ...
   * Processor M: [ .. N_M]
   * 

into this:

   * [ [ ... N_0 ] [ ....... N_1 ] ... [ .. N_M] ]
   * 

on each processor. This function is collective and therefore must be called by all processors in the Communicator.

Definition at line 2923 of file parallel_implementation.h.

References libMesh::Parallel::allgather(), libMesh::ierr, libMesh::libmesh_assert(), libMesh::START_LOG(), and libMesh::Parallel::verify().

{
  if (this->size() < 2)
    return;

  START_LOG("allgather()", "Parallel");

  if (identical_buffer_sizes)
    {
      if (r.empty())
        return;

      libmesh_assert(this->verify(r.size()));

      std::vector<T> r_src(r.size()*this->size());
      r_src.swap(r);
      StandardType<T> send_type(&r_src[0]);

      MPI_Allgather (&r_src[0],
                     cast_int<int>(r_src.size()),
                     send_type,
                     &r[0],
                     cast_int<int>(r_src.size()),
                     send_type,
                     this->get());
      libmesh_assert(this->verify(r));
      STOP_LOG("allgather()", "Parallel");
      return;
    }

  std::vector<int>
    sendlengths  (this->size(), 0),
    displacements(this->size(), 0);

  const int mysize = static_cast<int>(r.size());
  this->allgather(mysize, sendlengths);

  // Find the total size of the final array and
  // set up the displacement offsets for each processor.
  unsigned int globalsize = 0;
  for (unsigned int i=0; i != this->size(); ++i)
    {
      displacements[i] = globalsize;
      globalsize += sendlengths[i];
    }

  // Check for quick return
  if (globalsize == 0)
    {
      STOP_LOG("allgather()", "Parallel");
      return;
    }

  // copy the input buffer
  std::vector<T> r_src(globalsize);
  r_src.swap(r);

  StandardType<T> send_type(&r[0]);

  // and get the data from the remote processors.
  // Pass NULL if our vector is empty.
#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Allgatherv (r_src.empty() ? NULL : &r_src[0], mysize, send_type,
                    &r[0], &sendlengths[0],
                    &displacements[0], send_type, this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("allgather()", "Parallel");
}
template<typename Context , typename Iter , typename OutputIter >
void libMesh::Parallel::Communicator::allgather_packed_range ( Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out 
) const [inline]

Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator.

Definition at line 3033 of file parallel_implementation.h.

References libMesh::Parallel::allgather(), libMesh::libmesh_assert(), libMesh::Parallel::max(), libMesh::Parallel::pack_range(), and libMesh::Parallel::unpack_range().

Referenced by libMesh::Parallel::allgather_packed_range().

{
  typedef typename std::iterator_traits<Iter>::value_type T;
  typedef typename Parallel::BufferType<T>::type buffer_t;

  bool nonempty_range = (range_begin != range_end);
  this->max(nonempty_range);

  while (nonempty_range)
    {
      // We will serialize variable size objects from *range_begin to
      // *range_end as a sequence of ints in this buffer
      std::vector<buffer_t> buffer;

      range_begin = Parallel::pack_range(context, range_begin, range_end, buffer);

      this->allgather(buffer, false);

      libmesh_assert(buffer.size());

      Parallel::unpack_range(buffer, context, out);

      nonempty_range = (range_begin != range_end);
      this->max(nonempty_range);
    }
}
template<typename T >
void libMesh::Parallel::Communicator::alltoall ( std::vector< T > &  r) const [inline]

Effectively transposes the input vector across all processors. The jth entry on processor i is replaced with the ith entry from processor j.

Definition at line 3065 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), size(), libMesh::START_LOG(), and verify().

Referenced by libMesh::Parallel::alltoall(), and libMesh::Nemesis_IO::read().

{
  if (this->size() < 2 || buf.empty())
    return;

  START_LOG("alltoall()", "Parallel");

  // the per-processor size.  this is the same for all
  // processors using MPI_Alltoall, could be variable
  // using MPI_Alltoallv
  const int size_per_proc =
    cast_int<int>(buf.size()/this->size());

  libmesh_assert_equal_to (buf.size()%this->size(), 0);

  libmesh_assert(this->verify(size_per_proc));

  std::vector<T> tmp(buf);

  StandardType<T> send_type(&tmp[0]);

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Alltoall (&tmp[0],
                  size_per_proc,
                  send_type,
                  &buf[0],
                  size_per_proc,
                  send_type,
                  this->get());
  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("alltoall()", "Parallel");
}
void libMesh::Parallel::Communicator::assign ( const communicator comm) [inline, private]

Utility function for setting our member variables from an MPI communicator

Definition at line 560 of file parallel_implementation.h.

References _communicator, _rank, _send_mode, _size, and DEFAULT.

Referenced by Communicator(), duplicate(), operator=(), and split().

{
  _communicator = comm;
#ifdef LIBMESH_HAVE_MPI
  if (_communicator != MPI_COMM_NULL)
    {
      int i;
      MPI_Comm_size(_communicator, &i);
      libmesh_assert_greater_equal (i, 0);
      _size = static_cast<unsigned int>(i);

      MPI_Comm_rank(_communicator, &i);
      libmesh_assert_greater_equal (i, 0);
      _rank = static_cast<unsigned int>(i);
    }
  else
    {
      _rank = 0;
      _size = 1;
    }
#endif
  _send_mode = DEFAULT;
}

Pause execution until all processors reach a certain point.

Definition at line 832 of file parallel_implementation.h.

References size(), and libMesh::START_LOG().

Referenced by libMesh::Parallel::barrier(), libMesh::NameBasedIO::write(), libMesh::CheckpointIO::write(), and libMesh::XdrIO::write().

{
  if (this->size() > 1)
    {
      START_LOG("barrier()", "Parallel");

      MPI_Barrier (this->get());

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

Take a local value and broadcast it to all processors. Optionally takes the root_id processor, which specifies the processor initiating the broadcast. If data is a vector, the user is responsible for resizing it on all processors, except in the case when data is a vector of strings.

Definition at line 3105 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

Referenced by libMesh::MetisPartitioner::_do_partition(), libMesh::EquationSystems::_read_impl(), libMesh::Parallel::broadcast(), broadcast(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), libMesh::XdrIO::read(), libMesh::System::read_header(), libMesh::System::read_legacy_data(), libMesh::XdrIO::read_serialized_bc_names(), libMesh::XdrIO::read_serialized_bcs(), libMesh::XdrIO::read_serialized_connectivity(), libMesh::XdrIO::read_serialized_nodes(), libMesh::XdrIO::read_serialized_nodesets(), libMesh::XdrIO::read_serialized_subdomain_names(), libMesh::System::read_serialized_vector(), libMesh::NameBasedIO::write(), and libMesh::System::write_serialized_blocked_dof_objects().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  START_LOG("broadcast()", "Parallel");

  // Spread data to remote processors.
#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Bcast (&data, 1, StandardType<T>(&data), root_id, this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("broadcast()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::broadcast ( std::basic_string< T > &  data,
const unsigned int  root_id 
) const [inline]

Definition at line 3132 of file parallel_implementation.h.

References broadcast(), libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  START_LOG("broadcast()", "Parallel");

  std::size_t data_size = data.size();
  this->broadcast(data_size, root_id);

  std::vector<T> data_c(data_size);
#ifndef NDEBUG
  std::string orig(data);
#endif

  if (this->rank() == root_id)
    for(std::size_t i=0; i<data.size(); i++)
      data_c[i] = data[i];

  this->broadcast (data_c, root_id);

  data.assign(data_c.begin(), data_c.end());

#ifndef NDEBUG
  if (this->rank() == root_id)
    libmesh_assert_equal_to (data, orig);
#endif

  STOP_LOG("broadcast()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::broadcast ( std::vector< T > &  data,
const unsigned int  root_id 
) const [inline]

Definition at line 3173 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  START_LOG("broadcast()", "Parallel");

  // and get the data from the remote processors.
  // Pass NULL if our vector is empty.
  T *data_ptr = data.empty() ? NULL : &data[0];

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Bcast (data_ptr, cast_int<int>(data.size()),
               StandardType<T>(data_ptr), root_id, this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("broadcast()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::broadcast ( std::vector< std::basic_string< T > > &  data,
const unsigned int  root_id 
) const [inline]

The strings will be packed in one long array with the size of each string preceeding the actual characters

Definition at line 3205 of file parallel_implementation.h.

References broadcast(), libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  START_LOG("broadcast()", "Parallel");

  std::size_t bufsize=0;
  if (root_id == this->rank())
    {
      for (std::size_t i=0; i<data.size(); ++i)
        bufsize += data[i].size() + 1;  // Add one for the string length word
    }
  this->broadcast(bufsize, root_id);

  // Here we use unsigned int to store up to 32-bit characters
  std::vector<unsigned int> temp; temp.reserve(bufsize);
  // Pack the strings
  if (root_id == this->rank())
    {
      for (unsigned int i=0; i<data.size(); ++i)
        {
          temp.push_back(cast_int<unsigned int>(data[i].size()));
          for (std::size_t j=0; j != data[i].size(); ++j)
            temp.push_back(data[i][j]);
        }
    }
  else
    temp.resize(bufsize);

  // broad cast the packed strings
  this->broadcast(temp, root_id);

  // Unpack the strings
  if (root_id != this->rank())
    {
      data.clear();
      std::vector<unsigned int>::const_iterator iter = temp.begin();
      while (iter != temp.end())
        {
          std::size_t curr_len = *iter++;
          data.push_back(std::string(iter, iter+curr_len));
          iter += curr_len;
        }
    }

  STOP_LOG("broadcast()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::broadcast ( std::set< T > &  data,
const unsigned int  root_id 
) const [inline]

Definition at line 3269 of file parallel_implementation.h.

References broadcast(), libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  START_LOG("broadcast()", "Parallel");

  std::vector<T> vecdata;
  if (this->rank() == root_id)
    vecdata.assign(data.begin(), data.end());

  std::size_t vecsize = vecdata.size();
  this->broadcast(vecsize, root_id);
  if (this->rank() != root_id)
    vecdata.resize(vecsize);

  this->broadcast(vecdata, root_id);
  if (this->rank() != root_id)
    {
      data.clear();
      data.insert(vecdata.begin(), vecdata.end());
    }

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

Blocking-broadcast range-of-pointers to one processor. This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void Parallel::pack(const T*, vector<int>& data, const Context*) is used to serialize type T onto the end of a data vector.

unsigned int Parallel::packable_size(const T*, const Context*) is used to allow data vectors to reserve memory, and for additional error checking

unsigned int Parallel::packed_size(const T*, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

Definition at line 3359 of file parallel_implementation.h.

References libMesh::Parallel::broadcast(), libMesh::Parallel::pack_range(), and libMesh::Parallel::unpack_range().

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

{
  typedef typename std::iterator_traits<Iter>::value_type T;
  typedef typename Parallel::BufferType<T>::type buffer_t;

  do
    {
      // We will serialize variable size objects from *range_begin to
      // *range_end as a sequence of ints in this buffer
      std::vector<buffer_t> buffer;

      if (this->rank() == root_id)
        range_begin = Parallel::pack_range(context1, range_begin, range_end, buffer);

      // this->broadcast(vector) requires the receiving vectors to
      // already be the appropriate size
      std::size_t buffer_size = buffer.size();
      this->broadcast (buffer_size, root_id);

      // We continue until there's nothing left to broadcast
      if (!buffer_size)
        break;

      buffer.resize(buffer_size);

      // Broadcast the packed data
      this->broadcast (buffer, root_id);

      if (this->rank() != root_id)
        Parallel::unpack_range(buffer, context2, out);
    } while (true);  // break above when we reach buffer_size==0
}

Free and reset this communicator

Definition at line 528 of file parallel_implementation.h.

References _communicator, _I_duped_it, and libMesh::libmesh_assert().

Referenced by operator=(), split(), ~Communicator(), and libMesh::LibMeshInit::~LibMeshInit().

                                {
#ifdef LIBMESH_HAVE_MPI
  if (_I_duped_it)
    {
      libmesh_assert (_communicator != MPI_COMM_NULL);
      MPI_Comm_free(&_communicator);
      _communicator = MPI_COMM_NULL;
    }
  _I_duped_it = false;
#endif
}
void libMesh::Parallel::Communicator::dereference_unique_tag ( int  tagvalue) const [inline]

Dereference an already-acquired tag, and see if we can re-release it.

Definition at line 1197 of file parallel_implementation.h.

References libMesh::libmesh_assert(), and used_tag_values.

Referenced by libMesh::Parallel::MessageTag::~MessageTag().

{
  // This has better be an already-acquired tag.
  libmesh_assert(used_tag_values.count(tagvalue));

  used_tag_values[tagvalue]--;
  // If we don't have any more outstanding references, we
  // don't even need to keep this tag in our "used" set.
  if (!used_tag_values[tagvalue])
    used_tag_values.erase(tagvalue);
}

Definition at line 510 of file parallel_implementation.h.

References _communicator, and send_mode().

                                                            {
  this->duplicate(comm._communicator);
  this->send_mode(comm.send_mode());
}

Definition at line 516 of file parallel_implementation.h.

References _communicator, _I_duped_it, and assign().

                                                            {
  if (_communicator != MPI_COMM_NULL)
    {
      MPI_Comm_dup(comm, &_communicator);
      _I_duped_it = true;
    }
  this->assign(_communicator);
}
template<typename T >
void libMesh::Parallel::Communicator::gather ( const unsigned int  root_id,
send_val,
std::vector< T > &  recv_val 
) const [inline]

Take a vector of length comm.size(), and on processor root_id fill in recv[processor_id] = the value of send on processor processor_id

Gather-to-root on one processor.

Definition at line 2796 of file parallel_implementation.h.

References rank(), size(), and libMesh::START_LOG().

Referenced by libMesh::Parallel::gather(), set_union(), libMesh::XdrIO::write_serialized_bcs(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

{
  libmesh_assert_less (root_id, this->size());

  if (this->rank() == root_id)
    recv.resize(this->size());

  if (this->size() > 1)
    {
      START_LOG("gather()", "Parallel");

      StandardType<T> send_type(&sendval);

      MPI_Gather(&sendval,
                 1,
                 send_type,
                 recv.empty() ? NULL : &recv[0],
                 1,
                 send_type,
                 root_id,
                 this->get());

      STOP_LOG("gather()", "Parallel");
    }
  else
    recv[0] = sendval;
}
template<typename T >
void libMesh::Parallel::Communicator::gather ( const unsigned int  root_id,
std::vector< T > &  r 
) const [inline]

Take a vector of local variables and expand it on processor root_id to include values from all processors

This handles the case where the lengths of the vectors may vary. Specifically, this function transforms this:

   * Processor 0: [ ... N_0 ]
   * Processor 1: [ ....... N_1 ]
   * ...
   * Processor M: [ .. N_M]
   * 

into this:

   * [ [ ... N_0 ] [ ....... N_1 ] ... [ .. N_M] ]
   * 

on processor root_id. This function is collective and therefore must be called by all processors in the Communicator.

Definition at line 2829 of file parallel_implementation.h.

References allgather(), libMesh::ierr, libMesh::libmesh_assert(), rank(), size(), and libMesh::START_LOG().

{
  if (this->size() == 1)
    {
      libmesh_assert (!this->rank());
      libmesh_assert (!root_id);
      return;
    }

  libmesh_assert_less (root_id, this->size());

  std::vector<int>
    sendlengths  (this->size(), 0),
    displacements(this->size(), 0);

  const int mysize = static_cast<int>(r.size());
  this->allgather(mysize, sendlengths);

  START_LOG("gather()", "Parallel");

  // Find the total size of the final array and
  // set up the displacement offsets for each processor.
  unsigned int globalsize = 0;
  for (unsigned int i=0; i != this->size(); ++i)
    {
      displacements[i] = globalsize;
      globalsize += sendlengths[i];
    }

  // Check for quick return
  if (globalsize == 0)
    {
      STOP_LOG("gather()", "Parallel");
      return;
    }

  // copy the input buffer
  std::vector<T> r_src(r);

  // now resize it to hold the global data
  // on the receiving processor
  if (root_id == this->rank())
    r.resize(globalsize);

  // and get the data from the remote processors
#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Gatherv (r_src.empty() ? NULL : &r_src[0], mysize, StandardType<T>(),
                 r.empty() ? NULL : &r[0], &sendlengths[0],
                 &displacements[0], StandardType<T>(),
                 root_id,
                 this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("gather()", "Parallel");
}
template<typename Context , typename Iter , typename OutputIter >
void libMesh::Parallel::Communicator::gather_packed_range ( const unsigned int  root_id,
Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out 
) const [inline]

Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator on rank root.

Definition at line 3001 of file parallel_implementation.h.

References libMesh::Parallel::gather(), libMesh::Parallel::max(), libMesh::Parallel::pack_range(), and libMesh::Parallel::unpack_range().

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

{
  typedef typename std::iterator_traits<Iter>::value_type T;
  typedef typename Parallel::BufferType<T>::type buffer_t;

  bool nonempty_range = (range_begin != range_end);
  this->max(nonempty_range);

  while (nonempty_range)
    {
      // We will serialize variable size objects from *range_begin to
      // *range_end as a sequence of ints in this buffer
      std::vector<buffer_t> buffer;

      range_begin = Parallel::pack_range(context, range_begin, range_end, buffer);

      this->gather(root_id, buffer);

      Parallel::unpack_range(buffer, context, out);

      nonempty_range = (range_begin != range_end);
      this->max(nonempty_range);
    }
}

Definition at line 616 of file parallel.h.

References _communicator.

{ return _communicator; }

Get a tag that is unique to this Communicator. Note that if people are also using magic numbers or copying communicators around then we can't guarantee the tag is unique to this MPI_Comm.

Definition at line 1163 of file parallel_implementation.h.

References libMesh::libmesh_assert(), and used_tag_values.

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

{
  if (used_tag_values.count(tagvalue))
    {
      // Get the largest value in the used values, and pick one
      // larger
      tagvalue = used_tag_values.rbegin()->first+1;
      libmesh_assert(!used_tag_values.count(tagvalue));
    }
  used_tag_values[tagvalue] = 1;

  // #ifndef NDEBUG
  //   // Make sure everyone called get_unique_tag and make sure
  //   // everyone got the same value
  //   int maxval = tagvalue;
  //   this->max(maxval);
  //   libmesh_assert_equal_to (tagvalue, maxval);
  // #endif

  return MessageTag(tagvalue, this);
}
template<typename T >
void libMesh::Parallel::Communicator::max ( T &  r) const [inline]

Take a local variable and replace it with the maximum of it's values on all processors. Containers are replaced element-wise.

Definition at line 1576 of file parallel_implementation.h.

References size(), and libMesh::START_LOG().

Referenced by libMesh::MeshRefinement::_coarsen_elements(), libMesh::MeshRefinement::_refine_elements(), libMesh::UnstructuredMesh::all_second_order(), libMesh::DofMap::attach_matrix(), libMesh::MeshTools::bounding_box(), libMesh::System::calculate_norm(), libMesh::EpetraVector< T >::close(), libMesh::MeshRefinement::coarsen_elements(), libMesh::MeshRefinement::eliminate_unrefined_patches(), libMesh::MeshRefinement::flag_elements_by_error_fraction(), libMesh::MeshRefinement::flag_elements_by_nelem_target(), libMesh::LocationMap< T >::init(), libMesh::MeshTools::libmesh_assert_valid_dof_ids(), libMesh::MeshTools::libmesh_assert_valid_procids< Elem >(), libMesh::MeshTools::libmesh_assert_valid_procids< Node >(), libMesh::MeshRefinement::limit_level_mismatch_at_edge(), libMesh::MeshRefinement::limit_level_mismatch_at_node(), libMesh::Parallel::max(), libMesh::MeshTools::n_active_levels(), libMesh::MeshTools::n_levels(), libMesh::MeshTools::n_p_levels(), libMesh::ParallelMesh::parallel_max_elem_id(), libMesh::ParallelMesh::parallel_max_node_id(), libMesh::Nemesis_IO::read(), libMesh::MeshBase::recalculate_n_partitions(), libMesh::MeshRefinement::refine_and_coarsen_elements(), libMesh::MeshRefinement::refine_elements(), semiverify(), libMesh::Parallel::sync_dofobject_data_by_xyz(), libMesh::MeshRefinement::test_level_one(), libMesh::MeshRefinement::test_unflagged(), and verify().

{
  if (this->size() > 1)
    {
      START_LOG("max(scalar)", "Parallel");

      T temp;
      MPI_Allreduce (&r,
                     &temp,
                     1,
                     StandardType<T>(&r),
                     MPI_MAX,
                     this->get());
      r = temp;

      STOP_LOG("max(scalar)", "Parallel");
    }
}
template<typename T >
void libMesh::Parallel::Communicator::max ( std::vector< T > &  r) const [inline]

Definition at line 1618 of file parallel_implementation.h.

References libMesh::libmesh_assert(), size(), libMesh::START_LOG(), and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("max(vector)", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<T> temp(r);
      MPI_Allreduce (&temp[0],
                     &r[0],
                     cast_int<int>(r.size()),
                     StandardType<T>(&temp[0]),
                     MPI_MAX,
                     this->get());

      STOP_LOG("max(vector)", "Parallel");
    }
}
template<typename T >
void libMesh::Parallel::Communicator::maxloc ( T &  r,
unsigned int &  max_id 
) const [inline]

Take a local variable and replace it with the maximum of it's values on all processors, returning the minimum rank of a processor which originally held the maximum value.

Definition at line 1664 of file parallel_implementation.h.

References libMesh::out, libMesh::Parallel::DataPlusInt< T >::rank, rank(), size(), libMesh::START_LOG(), and libMesh::Parallel::DataPlusInt< T >::val.

Referenced by libMesh::Parallel::maxloc().

{
  if (this->size() > 1)
    {
      START_LOG("maxloc(scalar)", "Parallel");

      DataPlusInt<T> in;
      in.val = r;
      in.rank = this->rank();
      DataPlusInt<T> out;
      MPI_Allreduce (&in,
                     &out,
                     1,
                     dataplusint_type<T>(),
                     MPI_MAXLOC,
                     this->get());
      r = out.val;
      max_id = out.rank;

      STOP_LOG("maxloc(scalar)", "Parallel");
    }
  else
    max_id = this->rank();
}
template<typename T >
void libMesh::Parallel::Communicator::maxloc ( std::vector< T > &  r,
std::vector< unsigned int > &  max_id 
) const [inline]

Take a vector of local variables and replace each entry with the maximum of it's values on all processors. Set each min_id entry to the minimum rank where a corresponding maximum was found.

Definition at line 1719 of file parallel_implementation.h.

References libMesh::libmesh_assert(), libMesh::out, libMesh::Parallel::DataPlusInt< T >::rank, rank(), size(), libMesh::START_LOG(), libMesh::Parallel::DataPlusInt< T >::val, and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("maxloc(vector)", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<DataPlusInt<T> > in(r.size());
      for (std::size_t i=0; i != r.size(); ++i)
        {
          in[i].val  = r[i];
          in[i].rank = this->rank();
        }
      std::vector<DataPlusInt<T> > out(r.size());
      MPI_Allreduce (&in[0],
                     &out[0],
                     cast_int<int>(r.size()),
                     dataplusint_type<T>(),
                     MPI_MAXLOC,
                     this->get());
      for (std::size_t i=0; i != r.size(); ++i)
        {
          r[i]      = out[i].val;
          max_id[i] = out[i].rank;
        }

      STOP_LOG("maxloc(vector)", "Parallel");
    }
  else if (!r.empty())
    {
      for (std::size_t i=0; i != r.size(); ++i)
        max_id[i] = this->rank();
    }
}
template<typename T >
void libMesh::Parallel::Communicator::min ( std::vector< T > &  r) const [inline]

Definition at line 1398 of file parallel_implementation.h.

References libMesh::libmesh_assert(), size(), libMesh::START_LOG(), and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("min(vector)", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<T> temp(r);
      MPI_Allreduce (&temp[0],
                     &r[0],
                     cast_int<int>(r.size()),
                     StandardType<T>(&temp[0]),
                     MPI_MIN,
                     this->get());

      STOP_LOG("min(vector)", "Parallel");
    }
}
template<typename T >
void libMesh::Parallel::Communicator::minloc ( T &  r,
unsigned int &  min_id 
) const [inline]

Take a local variable and replace it with the minimum of it's values on all processors, returning the minimum rank of a processor which originally held the minimum value.

Definition at line 1444 of file parallel_implementation.h.

References libMesh::out, libMesh::Parallel::DataPlusInt< T >::rank, rank(), size(), libMesh::START_LOG(), and libMesh::Parallel::DataPlusInt< T >::val.

Referenced by libMesh::Parallel::minloc().

{
  if (this->size() > 1)
    {
      START_LOG("minloc(scalar)", "Parallel");

      DataPlusInt<T> in;
      in.val = r;
      in.rank = this->rank();
      DataPlusInt<T> out;
      MPI_Allreduce (&in,
                     &out,
                     1,
                     dataplusint_type<T>(),
                     MPI_MINLOC,
                     this->get());
      r = out.val;
      min_id = out.rank;

      STOP_LOG("minloc(scalar)", "Parallel");
    }
  else
    min_id = this->rank();
}
template<typename T >
void libMesh::Parallel::Communicator::minloc ( std::vector< T > &  r,
std::vector< unsigned int > &  min_id 
) const [inline]

Take a vector of local variables and replace each entry with the minimum of it's values on all processors. Set each min_id entry to the minimum rank where a corresponding minimum was found.

Definition at line 1499 of file parallel_implementation.h.

References libMesh::libmesh_assert(), libMesh::out, libMesh::Parallel::DataPlusInt< T >::rank, rank(), size(), libMesh::START_LOG(), libMesh::Parallel::DataPlusInt< T >::val, and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("minloc(vector)", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<DataPlusInt<T> > in(r.size());
      for (std::size_t i=0; i != r.size(); ++i)
        {
          in[i].val  = r[i];
          in[i].rank = this->rank();
        }
      std::vector<DataPlusInt<T> > out(r.size());
      MPI_Allreduce (&in[0],
                     &out[0],
                     cast_int<int>(r.size()),
                     dataplusint_type<T>(),
                     MPI_MINLOC,
                     this->get());
      for (std::size_t i=0; i != r.size(); ++i)
        {
          r[i]      = out[i].val;
          min_id[i] = out[i].rank;
        }

      STOP_LOG("minloc(vector)", "Parallel");
    }
  else if (!r.empty())
    {
      for (std::size_t i=0; i != r.size(); ++i)
        min_id[i] = this->rank();
    }
}
Communicator & libMesh::Parallel::Communicator::operator= ( const communicator comm) [inline]

Definition at line 540 of file parallel_implementation.h.

References assign(), and clear().

                                                                      {
  this->clear();
  this->assign(comm);
  return *this;
}
status libMesh::Parallel::Communicator::probe ( const unsigned int  src_processor_id,
const MessageTag tag = any_tag 
) const [inline]

Blocking message probe. Allows information about a message to be examined before the message is actually received.

We do not currently support probes on one processor without MPI.

Definition at line 1925 of file parallel_implementation.h.

References libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

Referenced by libMesh::Parallel::probe(), and receive().

{
  START_LOG("probe()", "Parallel");

  status stat;

  MPI_Probe (src_processor_id,
             tag.value(),
             this->get(),
             &stat);

  STOP_LOG("probe()", "Parallel");

  return stat;
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
const MessageTag tag = any_tag 
) const [inline]

Blocking-receive from one processor with data-defined type.

We do not currently support receives on one processor without MPI.

Definition at line 2341 of file parallel_implementation.h.

References libMesh::Parallel::Status::get(), libMesh::ierr, libMesh::libmesh_assert(), probe(), libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

Referenced by libMesh::SystemSubsetBySubdomain::init(), libMesh::Parallel::nonblocking_receive(), libMesh::Nemesis_IO::read(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::Parallel::receive(), receive(), receive_packed_range(), send_receive(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

{
  START_LOG("receive()", "Parallel");

  // Get the status of the message, explicitly provide the
  // datatype so we can later query the size
  Status stat(this->probe(src_processor_id, tag), StandardType<T>(&buf));

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Recv (&buf,
              1,
              StandardType<T>(&buf),
              src_processor_id,
              tag.value(),
              this->get(),
              stat.get());
  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("receive()", "Parallel");

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

Nonblocking-receive from one processor with data-defined type.

Definition at line 2372 of file parallel_implementation.h.

References libMesh::Parallel::Request::get(), libMesh::ierr, libMesh::libmesh_assert(), libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

{
  START_LOG("receive()", "Parallel");

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Irecv (&buf,
               1,
               StandardType<T>(&buf),
               src_processor_id,
               tag.value(),
               this->get(),
               req.get());
  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("receive()", "Parallel");
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
const DataType type,
const MessageTag tag = any_tag 
) const [inline]

Blocking-receive from one processor with user-defined type.

Definition at line 3492 of file parallel_implementation.h.

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

Nonblocking-receive from one processor with user-defined type.

Definition at line 3497 of file parallel_implementation.h.

{ libmesh_not_implemented(); }
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::basic_string< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 2297 of file parallel_implementation.h.

References receive().

{
  std::vector<T> tempbuf;  // Officially C++ won't let us get a
                           // modifiable array from a string

  Status stat = this->receive(src_processor_id, tempbuf, tag);
  buf.assign(tempbuf.begin(), tempbuf.end());
  return stat;
}
template<typename T >
void libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::basic_string< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2312 of file parallel_implementation.h.

References libMesh::Parallel::Request::add_post_wait_work(), and receive().

{
  // Officially C++ won't let us get a modifiable array from a
  // string, and we can't even put one on the stack for the
  // non-blocking case.
  std::vector<T> *tempbuf = new std::vector<T>();

  // We can clear the string, but the Request::wait() will need to
  // handle copying our temporary buffer to it
  buf.clear();

  req.add_post_wait_work
    (new Parallel::PostWaitCopyBuffer<std::vector<T>,
     std::back_insert_iterator<std::basic_string<T> > >
     (tempbuf, std::back_inserter(buf)));

  // Make the Request::wait() then handle deleting the buffer
  req.add_post_wait_work
    (new Parallel::PostWaitDeleteBuffer<std::vector<T> >(tempbuf));

  this->receive(src_processor_id, tempbuf, req, tag);
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::set< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 2398 of file parallel_implementation.h.

References receive().

{
  return this->receive
    (src_processor_id, buf,
     StandardType<T>(buf.empty() ? NULL : &buf.front()), tag);
}
template<typename T >
void libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::set< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2410 of file parallel_implementation.h.

References receive().

{
  this->receive (src_processor_id, buf,
                 StandardType<T>(buf.empty() ? NULL : &buf.front()), req, tag);
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::set< T > &  buf,
const DataType type,
const MessageTag tag 
) const [inline]

Definition at line 2422 of file parallel_implementation.h.

References receive(), and libMesh::START_LOG().

{
  START_LOG("receive()", "Parallel");

  std::vector<T> vecbuf;
  Status stat = this->receive(src_processor_id, vecbuf, type, tag);
  buf.clear();
  buf.insert(vecbuf.begin(), vecbuf.end());

  STOP_LOG("receive()", "Parallel");

  return stat;
}
template<typename T >
void libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::set< T > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2442 of file parallel_implementation.h.

References libMesh::Parallel::Request::add_post_wait_work(), receive(), and libMesh::START_LOG().

{
  START_LOG("receive()", "Parallel");

  // Allocate temporary buffer on the heap so it lives until after
  // the non-blocking send completes
  std::vector<T> *vecbuf = new std::vector<T>();

  // We can clear the set, but the Request::wait() will need to
  // handle copying our temporary buffer to it
  buf.clear();

  req.add_post_wait_work
    (new Parallel::PostWaitCopyBuffer<std::vector<T>,
     std::back_insert_iterator<std::set<T> > >
     (vecbuf, std::back_inserter(buf)));

  // Make the Request::wait() then handle deleting the buffer
  req.add_post_wait_work
    (new Parallel::PostWaitDeleteBuffer<std::vector<T> >(vecbuf));

  this->receive(src_processor_id, *vecbuf, type, req, tag);

  STOP_LOG("receive()", "Parallel");
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::vector< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 2475 of file parallel_implementation.h.

References receive().

{
  return this->receive
    (src_processor_id, buf,
     StandardType<T>(buf.empty() ? NULL : &buf.front()), tag);
}
template<typename T >
void libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::vector< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2487 of file parallel_implementation.h.

References receive().

{
  this->receive (src_processor_id, buf,
                 StandardType<T>(buf.empty() ? NULL : &buf.front()), req, tag);
}
template<typename T >
Status libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::vector< T > &  buf,
const DataType type,
const MessageTag tag 
) const [inline]

Definition at line 2499 of file parallel_implementation.h.

References libMesh::Parallel::Status::get(), libMesh::ierr, libMesh::libmesh_assert(), probe(), libMesh::Parallel::Status::size(), libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

{
  START_LOG("receive()", "Parallel");

  // Get the status of the message, explicitly provide the
  // datatype so we can later query the size
  Status stat(this->probe(src_processor_id, tag), type);

  buf.resize(stat.size());

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Recv (buf.empty() ? NULL : &buf[0],
              cast_int<int>(buf.size()),
              type,
              src_processor_id,
              tag.value(),
              this->get(),
              stat.get());
  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("receive()", "Parallel");

  return stat;
}
template<typename T >
void libMesh::Parallel::Communicator::receive ( const unsigned int  src_processor_id,
std::vector< T > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2533 of file parallel_implementation.h.

References libMesh::Parallel::Request::get(), libMesh::ierr, libMesh::libmesh_assert(), libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

{
  START_LOG("receive()", "Parallel");

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    MPI_Irecv (buf.empty() ? NULL : &buf[0],
               cast_int<int>(buf.size()),
               type,
               src_processor_id,
               tag.value(),
               this->get(),
               req.get());
  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("receive()", "Parallel");
}
template<typename Context , typename OutputIter >
void libMesh::Parallel::Communicator::receive_packed_range ( const unsigned int  dest_processor_id,
Context *  context,
OutputIter  out,
const MessageTag tag = any_tag 
) const [inline]

Blocking-receive range-of-pointers from one processor. This function does not receive raw pointers, but rather constructs new objects whose contents match the objects pointed to by the sender.

The objects will be of type T = iterator_traits<OutputIter>::value_type.

Using std::back_inserter as the output iterator allows receive to fill any container type. Using libMesh::null_output_iterator allows the receive to be dealt with solely by Parallel::unpack(), for objects whose unpack() is written so as to not leak memory when used in this fashion.

A future version of this method should be created to preallocate memory when receiving vectors...

void Parallel::unpack(vector<int>::iterator in, T** out, Context*) is used to unserialize type T, typically into a new heap-allocated object whose pointer is returned as *out.

unsigned int Parallel::packed_size(const T*, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

Definition at line 2559 of file parallel_implementation.h.

References receive(), and libMesh::Parallel::unpack_range().

Referenced by libMesh::Parallel::receive_packed_range().

{
  typedef typename std::iterator_traits<OutputIter>::value_type T;
  typedef typename Parallel::BufferType<T>::type buffer_t;

  // Receive serialized variable size objects as sequences of buffer_t
  std::size_t total_buffer_size = 0;
  this->receive(src_processor_id, total_buffer_size, tag);

  std::size_t received_buffer_size = 0;
  while (received_buffer_size < total_buffer_size)
    {
      std::vector<buffer_t> buffer;
      this->receive(src_processor_id, buffer, tag);
      received_buffer_size += buffer.size();
      Parallel::unpack_range(buffer, context, out);
    }
}
void libMesh::Parallel::Communicator::reference_unique_tag ( int  tagvalue) const [inline]

Reference an already-acquired tag, so that we know it will be dereferenced multiple times before we can re-release it.

Definition at line 1187 of file parallel_implementation.h.

References libMesh::libmesh_assert(), and used_tag_values.

Referenced by libMesh::Parallel::MessageTag::MessageTag().

{
  // This has better be an already-acquired tag.
  libmesh_assert(used_tag_values.count(tagvalue));

  used_tag_values[tagvalue]++;
}
template<typename T >
bool libMesh::Parallel::Communicator::semiverify ( const T *  r) const [inline]

Verify that a local pointer points to the same value on all processors where it is not NULL. Containers must have the same value in every entry.

Definition at line 1248 of file parallel_implementation.h.

References max(), min(), and size().

Referenced by semiverify().

{
  if (this->size() > 1 && Attributes<T>::has_min_max == true)
    {
      T tempmin, tempmax;
      if (r)
        tempmin = tempmax = *r;
      else
        {
          Attributes<T>::set_highest(tempmin);
          Attributes<T>::set_lowest(tempmax);
        }
      this->min(tempmin);
      this->max(tempmax);
      bool invalid = r && ((*r != tempmin) &&
                           (*r != tempmax));
      this->max(invalid);
      return !invalid;
    }
  return true;
}
template<typename T >
bool libMesh::Parallel::Communicator::semiverify ( const std::vector< T > *  r) const [inline]

Definition at line 1273 of file parallel_implementation.h.

References max(), min(), semiverify(), and size().

{
  if (this->size() > 1 && Attributes<T>::has_min_max == true)
    {
      std::size_t rsize = r ? r->size() : 0;
      std::size_t *psize = r ? &rsize : NULL;

      if (!this->semiverify(psize))
        return false;

      this->max(rsize);

      std::vector<T> tempmin, tempmax;
      if (r)
        {
          tempmin = tempmax = *r;
        }
      else
        {
          tempmin.resize(rsize);
          tempmax.resize(rsize);
          Attributes<std::vector<T> >::set_highest(tempmin);
          Attributes<std::vector<T> >::set_lowest(tempmax);
        }
      this->min(tempmin);
      this->max(tempmax);
      bool invalid = r && ((*r != tempmin) &&
                           (*r != tempmax));
      this->max(invalid);
      return !invalid;
    }
  return true;
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
T &  buf,
const MessageTag tag = no_tag 
) const [inline]

Blocking-send to one processor with data-defined type.

We do not currently support sends on one processor without MPI.

Definition at line 2003 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

Referenced by libMesh::SystemSubsetBySubdomain::init(), libMesh::Parallel::nonblocking_send(), libMesh::Nemesis_IO::read(), libMesh::System::read_SCALAR_dofs(), libMesh::System::read_serialized_blocked_dof_objects(), libMesh::Parallel::send(), send(), send_packed_range(), send_receive(), libMesh::System::write_SCALAR_dofs(), libMesh::XdrIO::write_serialized_bcs(), libMesh::System::write_serialized_blocked_dof_objects(), libMesh::XdrIO::write_serialized_connectivity(), libMesh::XdrIO::write_serialized_nodes(), and libMesh::XdrIO::write_serialized_nodesets().

{
  START_LOG("send()", "Parallel");

  T* dataptr = &buf;

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Ssend : MPI_Send) (dataptr,
                            1,
                            StandardType<T>(dataptr),
                            dest_processor_id,
                            tag.value(),
                            this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
T &  buf,
Request req,
const MessageTag tag = no_tag 
) const [inline]

Nonblocking-send to one processor with data-defined type.

Definition at line 2031 of file parallel_implementation.h.

References libMesh::Parallel::Request::get(), libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

{
  START_LOG("send()", "Parallel");

  T* dataptr = &buf;

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Issend : MPI_Isend) (dataptr,
                              1,
                              StandardType<T>(dataptr),
                              dest_processor_id,
                              tag.value(),
                              this->get(),
                              req.get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
T &  buf,
const DataType type,
const MessageTag tag = no_tag 
) const [inline]

Blocking-send to one processor with user-defined type.

Definition at line 3458 of file parallel_implementation.h.

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

Nonblocking-send to one processor with user-defined type.

Definition at line 3463 of file parallel_implementation.h.

{ libmesh_not_implemented(); }
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::basic_string< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 1945 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

{
  START_LOG("send()", "Parallel");

  T* dataptr = buf.empty() ? NULL : const_cast<T*>(buf.data());

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Ssend : MPI_Send) (dataptr,
                            cast_int<int>(buf.size()),
                            StandardType<T>(dataptr),
                            dest_processor_id,
                            tag.value(),
                            this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::basic_string< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 1973 of file parallel_implementation.h.

References libMesh::Parallel::Request::get(), libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

{
  START_LOG("send()", "Parallel");

  T* dataptr = buf.empty() ? NULL : const_cast<T*>(buf.data());

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Issend : MPI_Isend) (dataptr,
                              cast_int<int>(buf.size()),
                              StandardType<T>(dataptr),
                              dest_processor_id,
                              tag.value(),
                              this->get(),
                              req.get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::set< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 2061 of file parallel_implementation.h.

References send().

{
  this->send(dest_processor_id,
             StandardType<T>(buf.empty() ? NULL : &buf.front()), tag);
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::set< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2072 of file parallel_implementation.h.

References send().

{
  this->send(dest_processor_id,
             StandardType<T>(buf.empty() ? NULL : &buf.front()), req, tag);
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::set< T > &  buf,
const DataType type,
const MessageTag tag 
) const [inline]

Definition at line 2084 of file parallel_implementation.h.

References send(), and libMesh::START_LOG().

{
  START_LOG("send()", "Parallel");

  std::vector<T> vecbuf(buf.begin(), buf.end());
  this->send(dest_processor_id, vecbuf, type, tag);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::set< T > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2100 of file parallel_implementation.h.

References libMesh::Parallel::Request::add_post_wait_work(), send(), and libMesh::START_LOG().

{
  START_LOG("send()", "Parallel");

  // Allocate temporary buffer on the heap so it lives until after
  // the non-blocking send completes
  std::vector<T> *vecbuf =
    new std::vector<T>(buf.begin(), buf.end());

  // Make the Request::wait() handle deleting the buffer
  req.add_post_wait_work
    (new Parallel::PostWaitDeleteBuffer<std::vector<T> >(vecbuf));

  this->send(dest_processor_id, *vecbuf, type, req, tag);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::vector< T > &  buf,
const MessageTag tag 
) const [inline]

Definition at line 2125 of file parallel_implementation.h.

References send().

{
  this->send(dest_processor_id, buf,
             StandardType<T>(buf.empty() ? NULL : &buf.front()), tag);
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::vector< T > &  buf,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2136 of file parallel_implementation.h.

References send().

{
  this->send(dest_processor_id, buf,
             StandardType<T>(buf.empty() ? NULL : &buf.front()), req, tag);
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::vector< T > &  buf,
const DataType type,
const MessageTag tag 
) const [inline]

Definition at line 2148 of file parallel_implementation.h.

References libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

{
  START_LOG("send()", "Parallel");

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Ssend : MPI_Send) (buf.empty() ? NULL : &buf[0],
                            cast_int<int>(buf.size()),
                            type,
                            dest_processor_id,
                            tag.value(),
                            this->get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send ( const unsigned int  dest_processor_id,
std::vector< T > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const [inline]

Definition at line 2175 of file parallel_implementation.h.

References libMesh::Parallel::Request::get(), libMesh::ierr, libMesh::libmesh_assert(), send_mode(), libMesh::START_LOG(), SYNCHRONOUS, and libMesh::Parallel::MessageTag::value().

{
  START_LOG("send()", "Parallel");

#ifndef NDEBUG
  // Only catch the return value when asserts are active.
  const int ierr =
#endif
    ((this->send_mode() == SYNCHRONOUS) ?
     MPI_Issend : MPI_Isend) (buf.empty() ? NULL : &buf[0],
                              cast_int<int>(buf.size()),
                              type,
                              dest_processor_id,
                              tag.value(),
                              this->get(),
                              req.get());

  libmesh_assert (ierr == MPI_SUCCESS);

  STOP_LOG("send()", "Parallel");
}

Explicitly sets the SendMode type used for send operations.

Definition at line 682 of file parallel.h.

References _send_mode.

Referenced by duplicate(), and split().

{ _send_mode = sm; }

Gets the user-requested SendMode.

Definition at line 687 of file parallel.h.

References _send_mode.

Referenced by duplicate(), send(), and split().

{ return _send_mode; }
template<typename Context , typename Iter >
void libMesh::Parallel::Communicator::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 [inline]

Blocking-send range-of-pointers to one processor. This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void Parallel::pack(const T*, vector<int>& data, const Context*) is used to serialize type T onto the end of a data vector.

unsigned int Parallel::packable_size(const T*, const Context*) is used to allow data vectors to reserve memory, and for additional error checking

Definition at line 2203 of file parallel_implementation.h.

References libMesh::Parallel::pack_range(), libMesh::Parallel::packed_range_size(), and send().

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

{
  // We will serialize variable size objects from *range_begin to
  // *range_end as a sequence of plain data (e.g. ints) in this buffer
  typedef typename std::iterator_traits<Iter>::value_type T;

  std::size_t total_buffer_size =
    Parallel::packed_range_size(context, range_begin, range_end);

  this->send(dest_processor_id, total_buffer_size, tag);

#ifdef DEBUG
  std::size_t used_buffer_size = 0;
#endif

  while (range_begin != range_end)
    {
      std::vector<typename Parallel::BufferType<T>::type> buffer;

      range_begin = Parallel::pack_range(context, range_begin, range_end, buffer);

#ifdef DEBUG
      used_buffer_size += buffer.size();
#endif

      // Blocking send of the buffer
      this->send(dest_processor_id, buffer, tag);
    }

#ifdef DEBUG
  libmesh_assert_equal_to(used_buffer_size, total_buffer_size);
#endif
}
template<typename Context , typename Iter >
void libMesh::Parallel::Communicator::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 [inline]

Nonblocking-send range-of-pointers to one processor. This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void Parallel::pack(const T*, vector<int>& data, const Context*) is used to serialize type T onto the end of a data vector.

unsigned int Parallel::packable_size(const T*, const Context*) is used to allow data vectors to reserve memory, and for additional error checking

Definition at line 2243 of file parallel_implementation.h.

References libMesh::Parallel::Request::add_post_wait_work(), libMesh::Parallel::Request::add_prior_request(), libMesh::Parallel::pack_range(), libMesh::Parallel::packed_range_size(), and send().

{
  // Allocate a buffer on the heap so we don't have to free it until
  // after the Request::wait()
  typedef typename std::iterator_traits<Iter>::value_type T;
  typedef typename Parallel::BufferType<T>::type buffer_t;

  std::size_t total_buffer_size =
    Parallel::packed_range_size(context, range_begin, range_end);

  Request intermediate_req = request();
  this->send(dest_processor_id, total_buffer_size, intermediate_req, tag);

  req.add_prior_request(intermediate_req);

#ifdef DEBUG
  std::size_t used_buffer_size = 0;
#endif

  while (range_begin != range_end)
    {
      std::vector<buffer_t> *buffer = new std::vector<buffer_t>();

      range_begin = Parallel::pack_range(context, range_begin, range_end, *buffer);

#ifdef DEBUG
      used_buffer_size += buffer->size();
#endif

      Request next_intermediate_req;

      Request *my_req = (range_begin == range_end) ? &req : &next_intermediate_req;

      // Make the Request::wait() handle deleting the buffer
      my_req->add_post_wait_work
        (new Parallel::PostWaitDeleteBuffer<std::vector<buffer_t> >
         (buffer));

      // Non-blocking send of the buffer
      this->send(dest_processor_id, *buffer, *my_req, tag);

      if (range_begin != range_end)
        req.add_prior_request(*my_req);
    }
}
template<typename T1 , typename T2 >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  send_tgt,
T1 &  send_val,
const unsigned int  recv_source,
T2 &  recv_val,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag 
) const [inline]

Nonblocking-receive range-of-pointers from one processor. Not yet implemented. Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor.

Send-receive data from one processor.

Definition at line 2646 of file parallel_implementation.h.

References rank(), libMesh::START_LOG(), and libMesh::Parallel::MessageTag::value().

Referenced by libMesh::ParmetisPartitioner::assign_partitioning(), libMesh::MeshCommunication::find_global_indices(), libMesh::Parallel::send_receive(), send_receive(), libMesh::Partitioner::set_node_processor_ids(), libMesh::DofMap::set_nonlocal_dof_objects(), libMesh::Parallel::sync_dofobject_data_by_id(), libMesh::Parallel::sync_dofobject_data_by_xyz(), and libMesh::XdrIO::write_serialized_connectivity().

{
  START_LOG("send_receive()", "Parallel");

  if (dest_processor_id   == this->rank() &&
      source_processor_id == this->rank())
    {
      recv = sendvec;
      STOP_LOG("send_receive()", "Parallel");
      return;
    }

  MPI_Sendrecv(&sendvec, 1, StandardType<T1>(&sendvec),
               dest_processor_id, send_tag.value(),
               &recv, 1, StandardType<T2>(&recv),
               source_processor_id, recv_tag.value(),
               this->get(),
               MPI_STATUS_IGNORE);

  STOP_LOG("send_receive()", "Parallel");
}
template<typename T1 , typename T2 >
void libMesh::Parallel::Communicator::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

Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor, using a user-specified MPI Dataype.

template<typename T1 , typename T2 >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  dest_processor_id,
std::vector< T1 > &  sendvec,
const DataType type1,
const unsigned int  source_processor_id,
std::vector< T2 > &  recv,
const DataType type2,
const MessageTag send_tag,
const MessageTag recv_tag 
) const [inline]

Definition at line 2613 of file parallel_implementation.h.

References rank(), receive(), send(), libMesh::START_LOG(), and libMesh::Parallel::Request::wait().

{
  START_LOG("send_receive()", "Parallel");

  if (dest_processor_id   == this->rank() &&
      source_processor_id == this->rank())
    {
      recv = sendvec;
      STOP_LOG("send_receive()", "Parallel");
      return;
    }

  Parallel::Request req;

  this->send (dest_processor_id, sendvec, type1, req, send_tag);

  this->receive (source_processor_id, recv, type2, recv_tag);

  req.wait();

  STOP_LOG("send_receive()", "Parallel");
}
template<typename T >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  dest_processor_id,
std::vector< T > &  sendvec,
const unsigned int  source_processor_id,
std::vector< T > &  recv,
const MessageTag send_tag,
const MessageTag recv_tag 
) const [inline]

Definition at line 2683 of file parallel_implementation.h.

References rank(), send_receive(), and libMesh::START_LOG().

{
  if (dest_processor_id   == this->rank() &&
      source_processor_id == this->rank())
    {
      START_LOG("send_receive()", "Parallel");
      recv = sendvec;
      STOP_LOG("send_receive()", "Parallel");
      return;
    }

  // Call the user-defined type version with automatic
  // type conversion based on template argument:
  this->send_receive (dest_processor_id, sendvec,
                      StandardType<T>(sendvec.empty() ? NULL : &sendvec[0]),
                      source_processor_id, recv,
                      StandardType<T>(recv.empty() ? NULL : &recv[0]),
                      send_tag, recv_tag);
}
template<typename T1 , typename T2 >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  dest_processor_id,
std::vector< T1 > &  sendvec,
const unsigned int  source_processor_id,
std::vector< T2 > &  recv,
const MessageTag send_tag,
const MessageTag recv_tag 
) const [inline]

Definition at line 2712 of file parallel_implementation.h.

References send_receive().

{
  // Call the user-defined type version with automatic
  // type conversion based on template argument:
  this->send_receive (dest_processor_id, sendvec,
                      StandardType<T1>(sendvec.empty() ? NULL : &sendvec[0]),
                      source_processor_id, recv,
                      StandardType<T2>(recv.empty() ? NULL : &recv[0]),
                      send_tag, recv_tag);
}
template<typename T1 , typename T2 >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  dest_processor_id,
std::vector< std::vector< T1 > > &  sendvec,
const unsigned int  source_processor_id,
std::vector< std::vector< T2 > > &  recv,
const MessageTag ,
const MessageTag  
) const [inline]

Definition at line 2732 of file parallel_implementation.h.

References libMesh::Parallel::any_tag, and libMesh::Parallel::no_tag.

{
  // FIXME - why aren't we honoring send_tag and recv_tag here?
  send_receive_vec_of_vec
    (dest_processor_id, sendvec, source_processor_id, recv,
     no_tag, any_tag, *this);
}
template<typename T >
void libMesh::Parallel::Communicator::send_receive ( const unsigned int  dest_processor_id,
std::vector< std::vector< T > > &  sendvec,
const unsigned int  source_processor_id,
std::vector< std::vector< T > > &  recv,
const MessageTag ,
const MessageTag  
) const [inline]

Definition at line 2750 of file parallel_implementation.h.

References libMesh::Parallel::any_tag, and libMesh::Parallel::no_tag.

{
  // FIXME - why aren't we honoring send_tag and recv_tag here?
  send_receive_vec_of_vec
    (dest_processor_id, sendvec, source_processor_id, recv,
     no_tag, any_tag, *this);
}
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter >
void libMesh::Parallel::Communicator::send_receive_packed_range ( const unsigned int  dest_processor_id,
const Context1 *  context1,
RangeIter  send_begin,
const RangeIter  send_end,
const unsigned int  source_processor_id,
Context2 *  context2,
OutputIter  out,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag 
) const [inline]

Send a range-of-pointers to one processor while simultaneously receiving another range from a (potentially different) processor. This function does not send or receive raw pointers, but rather constructs new objects at each receiver whose contents match the objects pointed to by the sender.

The objects being sent will be of type T1 = iterator_traits<RangeIter>::value_type, and the objects being received will be of type T2 = iterator_traits<OutputIter>::value_type

void Parallel::pack(const T1*, vector<int>& data, const Context1*) is used to serialize type T1 onto the end of a data vector.

Using std::back_inserter as the output iterator allows send_receive to fill any container type. Using libMesh::null_output_iterator allows the receive to be dealt with solely by Parallel::unpack(), for objects whose unpack() is written so as to not leak memory when used in this fashion.

A future version of this method should be created to preallocate memory when receiving vectors...

void Parallel::unpack(vector<int>::iterator in, T2** out, Context*) is used to unserialize type T2, typically into a new heap-allocated object whose pointer is returned as *out.

unsigned int Parallel::packable_size(const T1*, const Context1*) is used to allow data vectors to reserve memory, and for additional error checking.

unsigned int Parallel::packed_size(const T2*, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

Send-receive range-of-pointers from one processor.

We do not currently support this operation on one processor without MPI.

Definition at line 2768 of file parallel_implementation.h.

References libMesh::Parallel::receive_packed_range(), libMesh::Parallel::send_packed_range(), libMesh::START_LOG(), and libMesh::Parallel::Request::wait().

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

{
  START_LOG("send_receive()", "Parallel");

  Parallel::Request req;

  this->send_packed_range (dest_processor_id, context1, send_begin, send_end,
                           req, send_tag);

  this->receive_packed_range (source_processor_id, context2, out, recv_tag);

  req.wait();

  STOP_LOG("send_receive()", "Parallel");

}
template<typename T >
void libMesh::Parallel::Communicator::set_union ( T &  data,
const unsigned int  root_id 
) const [inline]

Take a container of local variables on each processor, and collect their union over all processors, replacing the set on processor 0.

Definition at line 3435 of file parallel_implementation.h.

Referenced by libMesh::MeshBase::cache_elem_dims(), libMesh::Nemesis_IO_Helper::compute_num_global_nodesets(), libMesh::Nemesis_IO_Helper::compute_num_global_sidesets(), libMesh::Parallel::set_union(), libMesh::MeshBase::subdomain_ids(), and libMesh::BoundaryInfo::sync().

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

Take a container of local variables on each processor, and replace it with their union over all processors.

Definition at line 3432 of file parallel_implementation.h.

{}
template<typename T >
void libMesh::Parallel::Communicator::set_union ( std::set< T > &  data,
const unsigned int  root_id 
) const [inline]

Definition at line 1882 of file parallel_implementation.h.

References gather(), and rank().

{
  std::vector<T> vecdata(data.begin(), data.end());
  this->gather(root_id, vecdata);
  if (this->rank() == root_id)
    data.insert(vecdata.begin(), vecdata.end());
}
template<typename T >
void libMesh::Parallel::Communicator::set_union ( std::set< T > &  data) const [inline]

Definition at line 1894 of file parallel_implementation.h.

References allgather().

{
  std::vector<T> vecdata(data.begin(), data.end());
  this->allgather(vecdata, false);
  data.insert(vecdata.begin(), vecdata.end());
}
void libMesh::Parallel::Communicator::split ( int  color,
int  key,
Communicator target 
) const [inline]

Definition at line 497 of file parallel_implementation.h.

References assign(), clear(), and send_mode().

                                                                              {
  target.clear();
  MPI_Comm newcomm;
  MPI_Comm_split(this->get(), color, key, &newcomm);
  target.assign(newcomm);
  target.send_mode(this->send_mode());
}
template<typename T >
void libMesh::Parallel::Communicator::sum ( std::vector< T > &  r) const [inline]

Definition at line 1816 of file parallel_implementation.h.

References libMesh::libmesh_assert(), size(), libMesh::START_LOG(), and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("sum()", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<T> temp(r);
      MPI_Allreduce (&temp[0],
                     &r[0],
                     cast_int<int>(r.size()),
                     StandardType<T>(&temp[0]),
                     MPI_SUM,
                     this->get());

      STOP_LOG("sum()", "Parallel");
    }
}
template<typename T >
void libMesh::Parallel::Communicator::sum ( std::complex< T > &  r) const [inline]

Definition at line 1840 of file parallel_implementation.h.

References size(), and libMesh::START_LOG().

{
  if (this->size() > 1)
    {
      START_LOG("sum()", "Parallel");

      std::complex<T> temp(r);
      MPI_Allreduce (&temp,
                     &r,
                     2,
                     StandardType<T>(),
                     MPI_SUM,
                     this->get());

      STOP_LOG("sum()", "Parallel");
    }
}
template<typename T >
void libMesh::Parallel::Communicator::sum ( std::vector< std::complex< T > > &  r) const [inline]

Definition at line 1860 of file parallel_implementation.h.

References libMesh::libmesh_assert(), size(), libMesh::START_LOG(), and verify().

{
  if (this->size() > 1 && !r.empty())
    {
      START_LOG("sum()", "Parallel");

      libmesh_assert(this->verify(r.size()));

      std::vector<std::complex<T> > temp(r);
      MPI_Allreduce (&temp[0],
                     &r[0],
                     cast_int<int>(r.size() * 2),
                     StandardType<T>(NULL),
                     MPI_SUM,
                     this->get());

      STOP_LOG("sum()", "Parallel");
    }
}
template<typename T >
bool libMesh::Parallel::Communicator::verify ( const T &  r) const [inline]

Verify that a local variable has the same value on all processors. Containers must have the same value in every entry.

Definition at line 1230 of file parallel_implementation.h.

References max(), min(), and size().

Referenced by alltoall(), libMesh::MeshCommunication::delete_remote_elements(), max(), maxloc(), min(), minloc(), libMesh::System::point_gradient(), libMesh::System::point_hessian(), libMesh::System::point_value(), sum(), and libMesh::Parallel::verify().

{
  if (this->size() > 1 && Attributes<T>::has_min_max == true)
    {
      T tempmin = r, tempmax = r;
      this->min(tempmin);
      this->max(tempmax);
      bool verified = (r == tempmin) &&
        (r == tempmax);
      this->min(verified);
      return verified;
    }
  return true;
}

Member Data Documentation

Definition at line 674 of file parallel.h.

Referenced by clear(), and duplicate().

Definition at line 668 of file parallel.h.

Referenced by assign(), and rank().

Definition at line 669 of file parallel.h.

Referenced by assign(), and send_mode().

Definition at line 668 of file parallel.h.

Referenced by assign(), and size().

std::map<int, unsigned int> libMesh::Parallel::Communicator::used_tag_values [mutable, private]

Definition at line 673 of file parallel.h.

Referenced by dereference_unique_tag(), get_unique_tag(), and reference_unique_tag().


The documentation for this class was generated from the following files: