27#include <boost/signals2.hpp>
35#if !defined(DEAL_II_WITH_MPI) && !defined(DEAL_II_WITH_PETSC)
40using MPI_Request =
int;
41using MPI_Datatype =
int;
43# ifndef MPI_COMM_WORLD
44# define MPI_COMM_WORLD 0
47# define MPI_COMM_SELF 0
50# define MPI_COMM_NULL 0
52# ifndef MPI_REQUEST_NULL
53# define MPI_REQUEST_NULL 0
84#ifdef DEAL_II_WITH_MPI
85# define DEAL_II_MPI_CONST_CAST(expr) (expr)
95template <
int rank,
int dim,
typename Number>
97template <
int rank,
int dim,
typename Number>
99template <
typename Number>
120 const unsigned int n_partitions,
140 template <
typename T>
158 std::complex<double>,
159 std::complex<long double>,
188 const std::vector<unsigned int>
213 std::vector<unsigned int>
216 const std::vector<unsigned int> &destinations);
240 const std::vector<unsigned int> &destinations);
471#ifdef DEAL_II_WITH_MPI
472 DEAL_II_DEPRECATED_EARLY
int
474 const MPI_Group &group,
487 std::vector<IndexSet>
503#ifdef DEAL_II_WITH_MPI
519 template <
class Iterator,
typename Number =
long double>
520 std::pair<Number, typename numbers::NumberTraits<Number>::real_type>
574 std::unique_ptr<MPI_Datatype, void (*)(MPI_Datatype *)>
596 template <
typename T>
609 template <
typename T,
typename U>
622 template <
typename T>
633 template <
int rank,
int dim,
typename Number>
643 template <
int rank,
int dim,
typename Number>
656 template <
typename Number>
681 template <
typename T>
694 template <
typename T,
typename U>
696 max(
const T &values,
const MPI_Comm &mpi_communicator, U &maxima);
707 template <
typename T>
732 template <
typename T>
745 template <
typename T,
typename U>
747 min(
const T &values,
const MPI_Comm &mpi_communicator, U &minima);
758 template <
typename T>
787 template <
typename T>
805 template <
typename T,
typename U>
818 template <
typename T>
913 std::vector<MinMaxAvg>
1137 template <
typename T>
1138 std::map<unsigned int, T>
1140 const std::map<unsigned int, T> &objects_to_send);
1155 template <
typename T>
1174 template <
typename T>
1177 const T & object_to_send,
1178 const unsigned int root_process = 0);
1215 template <
typename T>
1216 typename std::enable_if<is_mpi_type<T> ==
false, T>::type
1218 const T & object_to_send,
1219 const unsigned int root_process = 0);
1243 template <
typename T>
1244 typename std::enable_if<is_mpi_type<T> ==
true, T>::type
1246 const T & object_to_send,
1247 const unsigned int root_process = 0);
1265 template <
typename T>
1269 const unsigned int root,
1284 template <
typename T>
1288 const std::function<T(
const T &,
const T &)> &combiner,
1289 const unsigned int root_process = 0);
1300 template <
typename T>
1304 const std::function<T(
const T &,
const T &)> &combiner);
1348 std::vector<unsigned int>
1350 const IndexSet &indices_to_look_up,
1360 template <
typename T>
1367 template <
typename T>
1382 namespace MPIDataTypes
1384#ifdef DEAL_II_WITH_MPI
1388 return MPI_CXX_BOOL;
1404 return MPI_SIGNED_CHAR;
1444 return MPI_LONG_LONG;
1452 return MPI_UNSIGNED_CHAR;
1460 return MPI_UNSIGNED_SHORT;
1468 return MPI_UNSIGNED;
1476 return MPI_UNSIGNED_LONG;
1484 return MPI_UNSIGNED_LONG_LONG;
1508 return MPI_LONG_DOUBLE;
1524 return MPI_DOUBLE_COMPLEX;
1532#ifdef DEAL_II_WITH_MPI
1550 template <
typename T>
1553 static_cast<std::remove_cv_t<std::remove_reference_t<T>
> *>(
nullptr));
1560 template <
typename T>
1571 template <
typename T,
unsigned int N>
1573 sum(
const T (&values)[N],
const MPI_Comm &mpi_communicator, T (&sums)[N])
1575 internal::all_reduce(MPI_SUM,
1583 template <
typename T,
unsigned int N>
1585 max(
const T (&values)[N],
const MPI_Comm &mpi_communicator, T (&maxima)[N])
1587 internal::all_reduce(MPI_MAX,
1595 template <
typename T,
unsigned int N>
1597 min(
const T (&values)[N],
const MPI_Comm &mpi_communicator, T (&minima)[N])
1599 internal::all_reduce(MPI_MIN,
1607 template <
typename T,
unsigned int N>
1613 static_assert(std::is_integral<T>::value,
1614 "The MPI_LOR operation only allows integral data types.");
1616 internal::all_reduce(MPI_LOR,
1624 template <
typename T>
1625 std::map<unsigned int, T>
1627 const std::map<unsigned int, T> &objects_to_send)
1629# ifndef DEAL_II_WITH_MPI
1631 Assert(objects_to_send.size() < 2,
1632 ExcMessage(
"Cannot send to more than one processor."));
1633 Assert(objects_to_send.find(0) != objects_to_send.end() ||
1634 objects_to_send.size() == 0,
1635 ExcMessage(
"Can only send to myself or to nobody."));
1636 return objects_to_send;
1640 std::map<unsigned int, T> received_objects;
1642 std::vector<unsigned int> send_to;
1643 send_to.reserve(objects_to_send.size());
1644 for (
const auto &m : objects_to_send)
1645 if (m.first == my_proc)
1646 received_objects[my_proc] = m.second;
1648 send_to.emplace_back(m.first);
1650 const unsigned int n_expected_incoming_messages =
1654 static CollectiveMutex mutex;
1655 CollectiveMutex::ScopedLock lock(mutex,
comm);
1661 if (send_to.size() == 0 && n_expected_incoming_messages == 0)
1662 return received_objects;
1668 std::vector<std::vector<char>> buffers_to_send(send_to.size());
1669 std::vector<MPI_Request> buffer_send_requests(send_to.size());
1672 for (
const auto &rank_obj : objects_to_send)
1673 if (rank_obj.first != my_proc)
1675 const auto &rank = rank_obj.first;
1678 const int ierr = MPI_Isend(buffers_to_send[i].data(),
1679 buffers_to_send[i].size(),
1684 &buffer_send_requests[i]);
1692 std::vector<char> buffer;
1694 for (
unsigned int i = 0; i < n_expected_incoming_messages; ++i)
1698 int ierr = MPI_Probe(MPI_ANY_SOURCE, mpi_tag,
comm, &status);
1703 ierr = MPI_Get_count(&status, MPI_CHAR, &len);
1708 const unsigned int rank = status.MPI_SOURCE;
1711 ierr = MPI_Recv(buffer.data(),
1719 Assert(received_objects.find(rank) == received_objects.end(),
1721 "I should not receive again from this rank"));
1722 received_objects[rank] =
1723 Utilities::unpack<T>(buffer,
1729 const int ierr = MPI_Waitall(send_to.size(),
1730 buffer_send_requests.data(),
1731 MPI_STATUSES_IGNORE);
1734 return received_objects;
1740 template <
typename T>
1747# ifndef DEAL_II_WITH_MPI
1749 std::vector<T> v(1,
object);
1756 int n_local_data = buffer.size();
1759 std::vector<int> size_all_data(n_procs, 0);
1762 int ierr = MPI_Allgather(
1763 &n_local_data, 1, MPI_INT, size_all_data.data(), 1, MPI_INT,
comm);
1768 std::vector<int> rdispls(n_procs);
1770 for (
unsigned int i = 1; i < n_procs; ++i)
1771 rdispls[i] = rdispls[i - 1] + size_all_data[i - 1];
1774 std::vector<char> received_unrolled_buffer(rdispls.back() +
1775 size_all_data.back());
1777 ierr = MPI_Allgatherv(buffer.data(),
1780 received_unrolled_buffer.data(),
1781 size_all_data.data(),
1787 std::vector<T> received_objects(n_procs);
1788 for (
unsigned int i = 0; i < n_procs; ++i)
1790 std::vector<char> local_buffer(received_unrolled_buffer.begin() +
1792 received_unrolled_buffer.begin() +
1793 rdispls[i] + size_all_data[i]);
1794 received_objects[i] = Utilities::unpack<T>(local_buffer);
1797 return received_objects;
1803 template <
typename T>
1806 const T & object_to_send,
1807 const unsigned int root_process)
1809# ifndef DEAL_II_WITH_MPI
1812 std::vector<T> v(1, object_to_send);
1821 int n_local_data = buffer.size();
1825 std::vector<int> size_all_data;
1826 if (my_rank == root_process)
1827 size_all_data.resize(n_procs, 0);
1830 int ierr = MPI_Gather(&n_local_data,
1833 size_all_data.data(),
1842 std::vector<int> rdispls;
1843 if (my_rank == root_process)
1845 rdispls.resize(n_procs, 0);
1846 for (
unsigned int i = 1; i < n_procs; ++i)
1847 rdispls[i] = rdispls[i - 1] + size_all_data[i - 1];
1850 std::vector<char> received_unrolled_buffer;
1851 if (my_rank == root_process)
1852 received_unrolled_buffer.resize(rdispls.back() + size_all_data.back());
1854 ierr = MPI_Gatherv(buffer.data(),
1857 received_unrolled_buffer.data(),
1858 size_all_data.data(),
1865 std::vector<T> received_objects;
1867 if (my_rank == root_process)
1869 received_objects.resize(n_procs);
1871 for (
unsigned int i = 0; i < n_procs; ++i)
1873 const std::vector<char> local_buffer(
1874 received_unrolled_buffer.begin() + rdispls[i],
1875 received_unrolled_buffer.begin() + rdispls[i] +
1877 received_objects[i] = Utilities::unpack<T>(local_buffer);
1880 return received_objects;
1886 template <
typename T>
1890 const unsigned int root,
1893# ifndef DEAL_II_WITH_MPI
1904 const size_t max_send_count = std::numeric_limits<signed int>::max();
1906 size_t total_sent_count = 0;
1907 while (total_sent_count < count)
1909 const size_t current_count =
1910 std::min(count - total_sent_count, max_send_count);
1912 const int ierr = MPI_Bcast(buffer + total_sent_count,
1918 total_sent_count += current_count;
1925 template <
typename T>
1926 typename std::enable_if<is_mpi_type<T> ==
false, T>::type
1928 const T & object_to_send,
1929 const unsigned int root_process)
1931# ifndef DEAL_II_WITH_MPI
1934 return object_to_send;
1940 std::vector<char> buffer;
1948 buffer_size = buffer.size();
1952 int ierr = MPI_Bcast(&buffer_size,
1962 buffer.resize(buffer_size);
1967 return object_to_send;
1969 return Utilities::unpack<T>(buffer,
false);
1975 template <
typename T>
1976 typename std::enable_if<is_mpi_type<T> ==
true, T>::type
1978 const T & object_to_send,
1979 const unsigned int root_process)
1981# ifndef DEAL_II_WITH_MPI
1984 return object_to_send;
1987 T
object = object_to_send;
1989 MPI_Bcast(&
object, 1, mpi_type_id_for_type<T>, root_process,
comm);
1998# ifdef DEAL_II_WITH_MPI
1999 template <
class Iterator,
typename Number>
2000 std::pair<Number, typename numbers::NumberTraits<Number>::real_type>
2011 const Number
sum = std::accumulate(begin, end, Number(0.));
2018 std::for_each(begin, end, [&mean, &sq_sum](
const Number &v) {
2022 return std::make_pair(mean,
2023 std::sqrt(sq_sum /
static_cast<Std
>(size - 1)));
types::global_dof_index size_type
void sum(const SparseMatrix< Number > &local, const MPI_Comm &mpi_communicator, SparseMatrix< Number > &global)
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
Tensor< rank, dim, Number > sum(const Tensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
ScopedLock(CollectiveMutex &mutex, const MPI_Comm &comm)
void unlock(const MPI_Comm &comm)
void lock(const MPI_Comm &comm)
DuplicatedCommunicator(const DuplicatedCommunicator &)=delete
DuplicatedCommunicator(const MPI_Comm &communicator)
~DuplicatedCommunicator()
const MPI_Comm & operator*() const
DuplicatedCommunicator & operator=(const DuplicatedCommunicator &)=delete
static void unregister_request(MPI_Request &request)
static std::set< MPI_Request * > requests
static void register_request(MPI_Request &request)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcDivideByZero()
static ::ExceptionBase & ExcMessage(std::string arg1)
MPI_Datatype mpi_type_id(const bool *)
void free_communicator(MPI_Comm &mpi_communicator)
std::vector< unsigned int > compute_index_owner(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm &comm)
T logical_or(const T &t, const MPI_Comm &mpi_communicator)
std::unique_ptr< MPI_Datatype, void(*)(MPI_Datatype *)> create_mpi_data_type_n_bytes(const std::size_t n_bytes)
std::vector< T > all_gather(const MPI_Comm &comm, const T &object_to_send)
std::enable_if< is_mpi_type< T >==false, T >::type broadcast(const MPI_Comm &comm, const T &object_to_send, const unsigned int root_process=0)
unsigned int compute_n_point_to_point_communications(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
T all_reduce(const T &local_value, const MPI_Comm &comm, const std::function< T(const T &, const T &)> &combiner)
std::vector< IndexSet > create_ascending_partitioning(const MPI_Comm &comm, const IndexSet::size_type locally_owned_size)
IndexSet create_evenly_distributed_partitioning(const MPI_Comm &comm, const IndexSet::size_type total_size)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
T reduce(const T &local_value, const MPI_Comm &comm, const std::function< T(const T &, const T &)> &combiner, const unsigned int root_process=0)
MPI_Comm duplicate_communicator(const MPI_Comm &mpi_communicator)
std::vector< T > gather(const MPI_Comm &comm, const T &object_to_send, const unsigned int root_process=0)
T sum(const T &t, const MPI_Comm &mpi_communicator)
std::vector< T > compute_set_union(const std::vector< T > &vec, const MPI_Comm &comm)
const std::vector< unsigned int > mpi_processes_within_communicator(const MPI_Comm &comm_large, const MPI_Comm &comm_small)
const MPI_Datatype mpi_type_id_for_type
std::pair< Number, typename numbers::NumberTraits< Number >::real_type > mean_and_standard_deviation(const Iterator begin, const Iterator end, const MPI_Comm &comm)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
std::map< unsigned int, T > some_to_some(const MPI_Comm &comm, const std::map< unsigned int, T > &objects_to_send)
constexpr bool is_mpi_type
int create_group(const MPI_Comm &comm, const MPI_Group &group, const int tag, MPI_Comm *new_comm)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
IndexSet create_evenly_distributed_partitioning(const unsigned int my_partition_id, const unsigned int n_partitions, const IndexSet::size_type total_size)
static const unsigned int invalid_unsigned_int
const types::global_dof_index invalid_size_type
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
boost::signals2::signal< void()> at_mpi_init
boost::signals2::signal< void()> at_mpi_finalize
static constexpr std::enable_if< std::is_same< Dummy, number >::value &&is_cuda_compatible< Dummy >::value, real_type >::type abs_square(const number &x)