13#ifndef dealii_mpi_consensus_algorithm_h
14#define dealii_mpi_consensus_algorithm_h
19#include <deal.II/base/mpi.templates.h>
130 namespace ConsensusAlgorithms
145 template <
typename RequestType,
typename AnswerType>
183 virtual std::vector<unsigned int>
185 const std::vector<unsigned int> &targets,
186 const std::function<RequestType(
const unsigned int)> &create_request,
187 const std::function<AnswerType(
const unsigned int,
188 const RequestType &)> &answer_request,
189 const std::function<
void(
const unsigned int,
const AnswerType &)>
208 template <
typename RequestType,
typename AnswerType>
225 virtual std::vector<unsigned int>
227 const std::vector<unsigned int> &targets,
228 const std::function<RequestType(
const unsigned int)> &create_request,
229 const std::function<AnswerType(
const unsigned int,
230 const RequestType &)> &answer_request,
231 const std::function<
void(
const unsigned int,
const AnswerType &)>
236#ifdef DEAL_II_WITH_MPI
282 const std::function<
void(
const unsigned int,
const AnswerType &)>
308 const std::function<AnswerType(
const unsigned int,
309 const RequestType &)> &answer_request,
318 const std::vector<unsigned int> &targets,
319 const std::function<RequestType(
const unsigned int)> &create_request,
375 template <
typename RequestType,
typename AnswerType>
376 std::vector<unsigned int>
377 nbx(
const std::vector<unsigned int> &targets,
378 const std::function<RequestType(
const unsigned int)> &create_request,
379 const std::function<AnswerType(
const unsigned int,
380 const RequestType &)> &answer_request,
381 const std::function<
void(
const unsigned int,
const AnswerType &)>
422 template <
typename RequestType>
423 std::vector<unsigned int>
424 nbx(
const std::vector<unsigned int> &targets,
425 const std::function<RequestType(
const unsigned int)> &create_request,
426 const std::function<
void(
const unsigned int,
const RequestType &)>
455 template <
typename RequestType,
typename AnswerType>
472 virtual std::vector<unsigned int>
474 const std::vector<unsigned int> &targets,
475 const std::function<RequestType(
const unsigned int)> &create_request,
476 const std::function<AnswerType(
const unsigned int,
477 const RequestType &)> &answer_request,
478 const std::function<
void(
const unsigned int,
const AnswerType &)>
483#ifdef DEAL_II_WITH_MPI
520 const std::vector<unsigned int> &targets,
521 const std::function<RequestType(
const unsigned int)> &create_request,
530 const unsigned int index,
531 const std::function<AnswerType(
const unsigned int,
532 const RequestType &)> &answer_request,
541 const unsigned int n_targets,
542 const std::function<
void(
const unsigned int,
const AnswerType &)>
612 template <
typename RequestType,
typename AnswerType>
613 std::vector<unsigned int>
614 pex(
const std::vector<unsigned int> &targets,
615 const std::function<RequestType(
const unsigned int)> &create_request,
616 const std::function<AnswerType(
const unsigned int,
617 const RequestType &)> &answer_request,
618 const std::function<
void(
const unsigned int,
const AnswerType &)>
659 template <
typename RequestType>
660 std::vector<unsigned int>
661 pex(
const std::vector<unsigned int> &targets,
662 const std::function<RequestType(
const unsigned int)> &create_request,
663 const std::function<
void(
const unsigned int,
const RequestType &)>
672 template <
typename RequestType,
typename AnswerType>
684 virtual std::vector<unsigned int>
686 const std::vector<unsigned int> &targets,
687 const std::function<RequestType(
const unsigned int)> &create_request,
688 const std::function<AnswerType(
const unsigned int,
689 const RequestType &)> &answer_request,
690 const std::function<
void(
const unsigned int,
const AnswerType &)>
729 template <
typename RequestType,
typename AnswerType>
730 std::vector<unsigned int>
732 const std::vector<unsigned int> &targets,
733 const std::function<RequestType(
const unsigned int)> &create_request,
734 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
736 const std::function<
void(
const unsigned int,
const AnswerType &)>
769 template <
typename RequestType>
770 std::vector<unsigned int>
772 const std::vector<unsigned int> &targets,
773 const std::function<RequestType(
const unsigned int)> &create_request,
774 const std::function<
void(
const unsigned int,
const RequestType &)>
792 template <
typename RequestType,
typename AnswerType>
811 virtual std::vector<unsigned int>
813 const std::vector<unsigned int> &targets,
814 const std::function<RequestType(
const unsigned int)> &create_request,
815 const std::function<AnswerType(
const unsigned int,
816 const RequestType &)> &answer_request,
817 const std::function<
void(
const unsigned int,
const AnswerType &)>
872 template <
typename RequestType,
typename AnswerType>
873 std::vector<unsigned int>
875 const std::vector<unsigned int> &targets,
876 const std::function<RequestType(
const unsigned int)> &create_request,
877 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
879 const std::function<
void(
const unsigned int,
const AnswerType &)>
920 template <
typename RequestType>
921 std::vector<unsigned int>
923 const std::vector<unsigned int> &targets,
924 const std::function<RequestType(
const unsigned int)> &create_request,
925 const std::function<
void(
const unsigned int,
const RequestType &)>
934 template <
typename RequestType,
typename AnswerType>
935 std::vector<unsigned int>
936 nbx(
const std::vector<unsigned int> &targets,
937 const std::function<RequestType(
const unsigned int)> &create_request,
938 const std::function<AnswerType(
const unsigned int,
939 const RequestType &)> &answer_request,
940 const std::function<
void(
const unsigned int,
const AnswerType &)>
945 targets, create_request, answer_request, process_answer,
comm);
950 template <
typename RequestType>
951 std::vector<unsigned int>
952 nbx(
const std::vector<unsigned int> &targets,
953 const std::function<RequestType(
const unsigned int)> &create_request,
954 const std::function<
void(
const unsigned int,
const RequestType &)>
963 using EmptyType = std::tuple<>;
965 return nbx<RequestType, EmptyType>(
969 [&process_request](
const unsigned int source_rank,
970 const RequestType &request) -> EmptyType {
971 process_request(source_rank, request);
979 [](
const unsigned int ,
980 const EmptyType & ) {},
986 template <
typename RequestType,
typename AnswerType>
987 std::vector<unsigned int>
988 pex(
const std::vector<unsigned int> &targets,
989 const std::function<RequestType(
const unsigned int)> &create_request,
990 const std::function<AnswerType(
const unsigned int,
991 const RequestType &)> &answer_request,
992 const std::function<
void(
const unsigned int,
const AnswerType &)>
996 return PEX<RequestType, AnswerType>().run(
997 targets, create_request, answer_request, process_answer,
comm);
1002 template <
typename RequestType>
1003 std::vector<unsigned int>
1004 pex(
const std::vector<unsigned int> &targets,
1005 const std::function<RequestType(
const unsigned int)> &create_request,
1006 const std::function<
void(
const unsigned int,
const RequestType &)>
1015 using EmptyType = std::tuple<>;
1017 return pex<RequestType, EmptyType>(
1021 [&process_request](
const unsigned int source_rank,
1022 const RequestType &request) -> EmptyType {
1023 process_request(source_rank, request);
1031 [](
const unsigned int ,
1032 const EmptyType & ) {},
1038 template <
typename RequestType,
typename AnswerType>
1039 std::vector<unsigned int>
1041 const std::vector<unsigned int> &targets,
1042 const std::function<RequestType(
const unsigned int)> &create_request,
1043 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1045 const std::function<
void(
const unsigned int,
const AnswerType &)>
1049 return Serial<RequestType, AnswerType>().run(
1050 targets, create_request, answer_request, process_answer,
comm);
1055 template <
typename RequestType>
1056 std::vector<unsigned int>
1058 const std::vector<unsigned int> &targets,
1059 const std::function<RequestType(
const unsigned int)> &create_request,
1060 const std::function<
void(
const unsigned int,
const RequestType &)>
1069 using EmptyType = std::tuple<>;
1071 return serial<RequestType, EmptyType>(
1075 [&process_request](
const unsigned int source_rank,
1076 const RequestType &request) -> EmptyType {
1077 process_request(source_rank, request);
1085 [](
const unsigned int ,
1086 const EmptyType & ) {},
1092 template <
typename RequestType,
typename AnswerType>
1093 std::vector<unsigned int>
1095 const std::vector<unsigned int> &targets,
1096 const std::function<RequestType(
const unsigned int)> &create_request,
1097 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1099 const std::function<
void(
const unsigned int,
const AnswerType &)>
1103 return Selector<RequestType, AnswerType>().run(
1104 targets, create_request, answer_request, process_answer,
comm);
1109 template <
typename RequestType>
1110 std::vector<unsigned int>
1112 const std::vector<unsigned int> &targets,
1113 const std::function<RequestType(
const unsigned int)> &create_request,
1114 const std::function<
void(
const unsigned int,
const RequestType &)>
1123 using EmptyType = std::tuple<>;
1125 return selector<RequestType, EmptyType>(
1129 [&process_request](
const unsigned int source_rank,
1130 const RequestType &request) -> EmptyType {
1131 process_request(source_rank, request);
1139 [](
const unsigned int ,
1140 const EmptyType & ) {},
1161 namespace ConsensusAlgorithms
1170 has_unique_elements(
const std::vector<unsigned int> &targets)
1172 std::vector<unsigned int> my_destinations = targets;
1173 std::sort(my_destinations.begin(), my_destinations.end());
1174 return (std::adjacent_find(my_destinations.begin(),
1175 my_destinations.end()) ==
1176 my_destinations.end());
1185 handle_exception(std::exception_ptr &&exception,
const MPI_Comm comm)
1187# ifdef DEAL_II_WITH_MPI
1192 std::rethrow_exception(exception);
1200 <<
"----------------------------------------------------"
1205 <<
" on processing: " << std::endl
1206 << exc.
what() << std::endl
1207 <<
"Aborting!" << std::endl
1208 <<
"----------------------------------------------------"
1212 MPI_Abort(
comm, 255);
1214 catch (std::exception &exc)
1219 <<
"----------------------------------------------------"
1222 <<
"Exception within ConsensusAlgorithm"
1224 <<
" on processing: " << std::endl
1225 << exc.what() << std::endl
1226 <<
"Aborting!" << std::endl
1227 <<
"----------------------------------------------------"
1231 MPI_Abort(
comm, 255);
1238 <<
"----------------------------------------------------"
1241 <<
"Unknown exception within ConsensusAlgorithm!" << std::endl
1242 <<
"Aborting!" << std::endl
1243 <<
"----------------------------------------------------"
1247 MPI_Abort(
comm, 255);
1254 std::rethrow_exception(exception);
1261 template <
typename RequestType,
typename AnswerType>
1262 std::vector<unsigned int>
1264 const std::vector<unsigned int> &targets,
1265 const std::function<RequestType(
const unsigned int)> &create_request,
1266 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1268 const std::function<
void(
const unsigned int,
const AnswerType &)>
1272 Assert(internal::has_unique_elements(targets),
1273 ExcMessage(
"The consensus algorithms expect that each process "
1274 "only sends a single message to another process, "
1275 "but the targets provided include duplicates."));
1277 static CollectiveMutex mutex;
1278 CollectiveMutex::ScopedLock lock(mutex,
comm);
1284 start_communication(targets, create_request,
comm);
1300 while (all_locally_originated_receives_are_completed(process_answer,
1302 maybe_answer_one_request(answer_request,
comm);
1306 signal_finish(
comm);
1311 while (all_remotely_originated_receives_are_completed() ==
false)
1312 maybe_answer_one_request(answer_request,
comm);
1315 clean_up_and_end_communication(
comm);
1319 internal::handle_exception(std::current_exception(),
comm);
1322 return std::vector<unsigned int>(requesting_processes.begin(),
1323 requesting_processes.end());
1328 template <
typename RequestType,
typename AnswerType>
1331 const std::vector<unsigned int> &targets,
1332 const std::function<RequestType(
const unsigned int)> &create_request,
1335# ifdef DEAL_II_WITH_MPI
1337 const auto n_targets = targets.size();
1343 send_requests.resize(n_targets);
1344 send_buffers.resize(n_targets);
1348 for (
unsigned int index = 0;
index < n_targets; ++
index)
1350 const unsigned int rank = targets[
index];
1353 auto &send_buffer = send_buffers[
index];
1356 std::vector<char>());
1359 auto ierr = MPI_Isend(send_buffer.data(),
1365 &send_requests[index]);
1371 n_outstanding_answers = n_targets;
1375 (void)create_request;
1382 template <
typename RequestType,
typename AnswerType>
1386 const std::function<
void(
const unsigned int,
const AnswerType &)>
1390# ifdef DEAL_II_WITH_MPI
1398 if (n_outstanding_answers == 0)
1405 int request_is_pending;
1407 const auto ierr = MPI_Iprobe(
1408 MPI_ANY_SOURCE, tag_deliver,
comm, &request_is_pending, &status);
1414 if (request_is_pending == 0)
1420 const auto target = status.MPI_SOURCE;
1427 MPI_Get_count(&status, MPI_CHAR, &message_size);
1430 std::vector<char> recv_buffer(message_size);
1436 const int ierr = MPI_Recv(recv_buffer.data(),
1447 process_answer(target,
1448 Utilities::unpack<AnswerType>(recv_buffer,
1453 --n_outstanding_answers;
1463 return (n_outstanding_answers == 0);
1468 (void)process_answer;
1477 template <
typename RequestType,
typename AnswerType>
1480 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1484# ifdef DEAL_II_WITH_MPI
1499 int request_is_pending;
1500 const auto ierr = MPI_Iprobe(
1501 MPI_ANY_SOURCE, tag_request,
comm, &request_is_pending, &status);
1504 if (request_is_pending != 0)
1508 const auto other_rank = status.MPI_SOURCE;
1510 Assert(requesting_processes.find(other_rank) ==
1511 requesting_processes.end(),
1512 ExcMessage(
"Process is requesting a second time!"));
1513 requesting_processes.insert(other_rank);
1517 auto ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1521 std::vector<char> buffer_recv(number_amount);
1522 ierr = MPI_Recv(buffer_recv.data(),
1533 request_buffers.emplace_back(std::make_unique<std::vector<char>>());
1534 auto &request_buffer = *request_buffers.back();
1538 Utilities::unpack<RequestType>(
1539 buffer_recv,
false)),
1543 request_requests.emplace_back(std::make_unique<MPI_Request>());
1544 ierr = MPI_Isend(request_buffer.data(),
1545 request_buffer.size(),
1550 request_requests.back().get());
1554 (void)answer_request;
1561 template <
typename RequestType,
typename AnswerType>
1565# ifdef DEAL_II_WITH_MPI
1566 const auto ierr = MPI_Ibarrier(
comm, &barrier_request);
1575 template <
typename RequestType,
typename AnswerType>
1578 AnswerType>::all_remotely_originated_receives_are_completed()
1580# ifdef DEAL_II_WITH_MPI
1581 int all_ranks_reached_barrier;
1582 const auto ierr = MPI_Test(&barrier_request,
1583 &all_ranks_reached_barrier,
1586 return all_ranks_reached_barrier != 0;
1594 template <
typename RequestType,
typename AnswerType>
1600# ifdef DEAL_II_WITH_MPI
1603 if (send_requests.size() > 0)
1605 const int ierr = MPI_Waitall(send_requests.size(),
1606 send_requests.data(),
1607 MPI_STATUSES_IGNORE);
1611 int ierr = MPI_Wait(&barrier_request, MPI_STATUS_IGNORE);
1614 for (
auto &i : request_requests)
1616 ierr = MPI_Wait(i.get(), MPI_STATUS_IGNORE);
1624 ierr = MPI_Barrier(
comm);
1633 template <
typename RequestType,
typename AnswerType>
1634 std::vector<unsigned int>
1636 const std::vector<unsigned int> &targets,
1637 const std::function<RequestType(
const unsigned int)> &create_request,
1638 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1640 const std::function<
void(
const unsigned int,
const AnswerType &)>
1644 Assert(internal::has_unique_elements(targets),
1645 ExcMessage(
"The consensus algorithms expect that each process "
1646 "only sends a single message to another process, "
1647 "but the targets provided include duplicates."));
1649 static CollectiveMutex mutex;
1650 CollectiveMutex::ScopedLock lock(mutex,
comm);
1657 const unsigned int n_requests =
1658 start_communication(targets, create_request,
comm);
1661 for (
unsigned int request = 0; request < n_requests; ++request)
1662 answer_one_request(request, answer_request,
comm);
1665 process_incoming_answers(targets.size(), process_answer,
comm);
1668 clean_up_and_end_communication();
1672 internal::handle_exception(std::current_exception(),
comm);
1675 return std::vector<unsigned int>(requesting_processes.begin(),
1676 requesting_processes.end());
1681 template <
typename RequestType,
typename AnswerType>
1684 const std::vector<unsigned int> &targets,
1685 const std::function<RequestType(
const unsigned int)> &create_request,
1688# ifdef DEAL_II_WITH_MPI
1694 const unsigned int n_targets = targets.size();
1697 const unsigned int n_sources =
1701 recv_buffers.resize(n_targets);
1702 send_buffers.resize(n_targets);
1703 send_request_requests.resize(n_targets);
1705 send_answer_requests.resize(n_sources);
1706 requests_buffers.resize(n_sources);
1709 for (
unsigned int i = 0; i < n_targets; ++i)
1711 const unsigned int rank = targets[i];
1715 auto &send_buffer = send_buffers[i];
1720 auto ierr = MPI_Isend(send_buffer.data(),
1726 &send_request_requests[i]);
1733 (void)create_request;
1741 template <
typename RequestType,
typename AnswerType>
1744 const unsigned int index,
1745 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1749# ifdef DEAL_II_WITH_MPI
1758 int ierr = MPI_Probe(MPI_ANY_SOURCE, tag_request,
comm, &status);
1762 const unsigned int other_rank = status.MPI_SOURCE;
1764 Assert(requesting_processes.find(other_rank) ==
1765 requesting_processes.end(),
1767 "A process is sending a request after a request from "
1768 "the same process has previously already been "
1769 "received. This algorithm does not expect this to happen."));
1770 requesting_processes.insert(other_rank);
1774 ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1777 std::vector<char> buffer_recv(number_amount);
1778 ierr = MPI_Recv(buffer_recv.data(),
1789 auto &request_buffer = requests_buffers[
index];
1793 Utilities::unpack<RequestType>(
1794 buffer_recv,
false)),
1796 std::vector<char>());
1798 ierr = MPI_Isend(request_buffer.data(),
1799 request_buffer.size(),
1804 &send_answer_requests[index]);
1807 (void)answer_request;
1815 template <
typename RequestType,
typename AnswerType>
1818 const unsigned int n_targets,
1819 const std::function<
void(
const unsigned int,
const AnswerType &)>
1823# ifdef DEAL_II_WITH_MPI
1832 for (
unsigned int i = 0; i < n_targets; ++i)
1837 MPI_Probe(MPI_ANY_SOURCE, tag_deliver,
comm, &status);
1841 const auto other_rank = status.MPI_SOURCE;
1844 const int ierr = MPI_Get_count(&status, MPI_CHAR, &message_size);
1847 std::vector<char> recv_buffer(message_size);
1853 const int ierr = MPI_Recv(recv_buffer.data(),
1864 process_answer(other_rank,
1865 Utilities::unpack<AnswerType>(recv_buffer,
false));
1869 (void)process_answer;
1876 template <
typename RequestType,
typename AnswerType>
1880# ifdef DEAL_II_WITH_MPI
1883 if (send_request_requests.size() > 0)
1885 const int ierr = MPI_Waitall(send_request_requests.size(),
1886 send_request_requests.data(),
1887 MPI_STATUSES_IGNORE);
1892 if (send_answer_requests.size() > 0)
1894 const int ierr = MPI_Waitall(send_answer_requests.size(),
1895 send_answer_requests.data(),
1896 MPI_STATUSES_IGNORE);
1904 template <
typename RequestType,
typename AnswerType>
1905 std::vector<unsigned int>
1907 const std::vector<unsigned int> &targets,
1908 const std::function<RequestType(
const unsigned int)> &create_request,
1909 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1911 const std::function<
void(
const unsigned int,
const AnswerType &)>
1916 ExcMessage(
"You shouldn't use the 'Serial' class on "
1917 "communicators that have more than one process "
1918 "associated with it."));
1921 if (targets.size() != 0)
1923 Assert(targets.size() == 1,
1925 "On a single process, the only valid target "
1926 "is process zero (the process itself), which can only be "
1933 const RequestType request =
1934 (create_request ? create_request(0) : RequestType());
1935 const AnswerType answer =
1936 (answer_request ? answer_request(0, request) : AnswerType());
1939 process_answer(0, answer);
1947 template <
typename RequestType,
typename AnswerType>
1948 std::vector<unsigned int>
1950 const std::vector<unsigned int> &targets,
1951 const std::function<RequestType(
const unsigned int)> &create_request,
1952 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1954 const std::function<
void(
const unsigned int,
const AnswerType &)>
1967# ifdef DEAL_II_WITH_MPI
1973 consensus_algo.reset(
new NBX<RequestType, AnswerType>());
1977 consensus_algo.reset(
new PEX<RequestType, AnswerType>());
1979 consensus_algo.reset(
new Serial<RequestType, AnswerType>());
1981 return consensus_algo->run(
1982 targets, create_request, answer_request, process_answer,
comm);
const char * get_exc_name() const
virtual const char * what() const noexcept override
virtual ~Interface()=default
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)=0
void start_communication(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const MPI_Comm comm)
void maybe_answer_one_request(const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm comm)
std::vector< std::unique_ptr< std::vector< char > > > request_buffers
std::set< unsigned int > requesting_processes
MPI_Request barrier_request
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
void clean_up_and_end_communication(const MPI_Comm comm)
bool all_locally_originated_receives_are_completed(const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< std::unique_ptr< MPI_Request > > request_requests
std::vector< std::vector< char > > send_buffers
void signal_finish(const MPI_Comm comm)
bool all_remotely_originated_receives_are_completed()
unsigned int n_outstanding_answers
std::vector< MPI_Request > send_requests
void clean_up_and_end_communication()
std::vector< MPI_Request > send_answer_requests
std::vector< MPI_Request > send_request_requests
unsigned int start_communication(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const MPI_Comm comm)
std::vector< std::vector< char > > requests_buffers
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
std::vector< std::vector< char > > send_buffers
void answer_one_request(const unsigned int index, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm comm)
std::set< unsigned int > requesting_processes
std::vector< std::vector< char > > recv_buffers
void process_incoming_answers(const unsigned int n_targets, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
virtual ~Selector()=default
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
std::shared_ptr< Interface< RequestType, AnswerType > > consensus_algo
virtual std::vector< unsigned int > run(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm) override
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcMessage(std::string arg1)
const unsigned int n_procs
std::vector< unsigned int > selector(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > serial(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > nbx(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
std::vector< unsigned int > pex(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm comm)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
unsigned int compute_n_point_to_point_communications(const MPI_Comm mpi_comm, const std::vector< unsigned int > &destinations)
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)