16#ifndef dealii_mpi_consensus_algorithm_h
17#define dealii_mpi_consensus_algorithm_h
22#include <deal.II/base/mpi.templates.h>
131 namespace ConsensusAlgorithms
157 template <
typename RequestType,
typename AnswerType>
173 virtual std::vector<unsigned int>
202 const RequestType &buffer_recv,
203 AnswerType & request_buffer);
214 const AnswerType & recv_buffer);
232 template <
typename RequestType,
typename AnswerType>
253 DEAL_II_DEPRECATED_EARLY
272 DEAL_II_DEPRECATED_EARLY
273 std::vector<unsigned int>
284 std::vector<unsigned int>
310 virtual std::vector<unsigned int>
312 const std::vector<unsigned int> & targets,
313 const std::function<RequestType(
const unsigned int)> &create_request,
314 const std::function<AnswerType(
const unsigned int,
315 const RequestType &)> &answer_request,
316 const std::function<
void(
const unsigned int,
const AnswerType &)>
328 DEAL_II_DEPRECATED_EARLY
337 DEAL_II_DEPRECATED_EARLY
355 template <
typename RequestType,
typename AnswerType>
376 DEAL_II_DEPRECATED_EARLY
390 virtual std::vector<unsigned int>
392 const std::vector<unsigned int> & targets,
393 const std::function<RequestType(
const unsigned int)> &create_request,
394 const std::function<AnswerType(
const unsigned int,
395 const RequestType &)> &answer_request,
396 const std::function<
void(
const unsigned int,
const AnswerType &)>
401#ifdef DEAL_II_WITH_MPI
447 const std::function<
void(
const unsigned int,
const AnswerType &)>
473 const std::function<AnswerType(
const unsigned int,
474 const RequestType &)> &answer_request,
483 const std::vector<unsigned int> & targets,
484 const std::function<RequestType(
const unsigned int)> &create_request,
529 template <
typename RequestType,
typename AnswerType>
530 std::vector<unsigned int>
531 nbx(
const std::vector<unsigned int> & targets,
532 const std::function<RequestType(
const unsigned int)> &create_request,
533 const std::function<AnswerType(
const unsigned int,
534 const RequestType &)> &answer_request,
535 const std::function<
void(
const unsigned int,
const AnswerType &)>
565 template <
typename RequestType>
566 std::vector<unsigned int>
567 nbx(
const std::vector<unsigned int> & targets,
568 const std::function<RequestType(
const unsigned int)> &create_request,
569 const std::function<
void(
const unsigned int,
const RequestType &)>
598 template <
typename RequestType,
typename AnswerType>
620 DEAL_II_DEPRECATED_EARLY
634 virtual std::vector<unsigned int>
636 const std::vector<unsigned int> & targets,
637 const std::function<RequestType(
const unsigned int)> &create_request,
638 const std::function<AnswerType(
const unsigned int,
639 const RequestType &)> &answer_request,
640 const std::function<
void(
const unsigned int,
const AnswerType &)>
645#ifdef DEAL_II_WITH_MPI
682 const std::vector<unsigned int> & targets,
683 const std::function<RequestType(
const unsigned int)> &create_request,
692 const unsigned int index,
693 const std::function<AnswerType(
const unsigned int,
694 const RequestType &)> &answer_request,
703 const unsigned int n_targets,
704 const std::function<
void(
const unsigned int,
const AnswerType &)>
763 template <
typename RequestType,
typename AnswerType>
764 std::vector<unsigned int>
765 pex(
const std::vector<unsigned int> & targets,
766 const std::function<RequestType(
const unsigned int)> &create_request,
767 const std::function<AnswerType(
const unsigned int,
768 const RequestType &)> &answer_request,
769 const std::function<
void(
const unsigned int,
const AnswerType &)>
799 template <
typename RequestType>
800 std::vector<unsigned int>
801 pex(
const std::vector<unsigned int> & targets,
802 const std::function<RequestType(
const unsigned int)> &create_request,
803 const std::function<
void(
const unsigned int,
const RequestType &)>
812 template <
typename RequestType,
typename AnswerType>
833 DEAL_II_DEPRECATED_EARLY
842 virtual std::vector<unsigned int>
844 const std::vector<unsigned int> & targets,
845 const std::function<RequestType(
const unsigned int)> &create_request,
846 const std::function<AnswerType(
const unsigned int,
847 const RequestType &)> &answer_request,
848 const std::function<
void(
const unsigned int,
const AnswerType &)>
884 template <
typename RequestType,
typename AnswerType>
885 std::vector<unsigned int>
887 const std::vector<unsigned int> & targets,
888 const std::function<RequestType(
const unsigned int)> &create_request,
889 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
891 const std::function<
void(
const unsigned int,
const AnswerType &)>
921 template <
typename RequestType>
922 std::vector<unsigned int>
924 const std::vector<unsigned int> & targets,
925 const std::function<RequestType(
const unsigned int)> &create_request,
926 const std::function<
void(
const unsigned int,
const RequestType &)>
944 template <
typename RequestType,
typename AnswerType>
965 DEAL_II_DEPRECATED_EARLY
982 virtual std::vector<unsigned int>
984 const std::vector<unsigned int> & targets,
985 const std::function<RequestType(
const unsigned int)> &create_request,
986 const std::function<AnswerType(
const unsigned int,
987 const RequestType &)> &answer_request,
988 const std::function<
void(
const unsigned int,
const AnswerType &)>
1032 template <
typename RequestType,
typename AnswerType>
1033 std::vector<unsigned int>
1035 const std::vector<unsigned int> & targets,
1036 const std::function<RequestType(
const unsigned int)> &create_request,
1037 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1039 const std::function<
void(
const unsigned int,
const AnswerType &)>
1069 template <
typename RequestType>
1070 std::vector<unsigned int>
1072 const std::vector<unsigned int> & targets,
1073 const std::function<RequestType(
const unsigned int)> &create_request,
1074 const std::function<
void(
const unsigned int,
const RequestType &)>
1085 template <
typename RequestType,
typename AnswerType>
1087 :
public Process<RequestType, AnswerType>
1100 const std::function<std::vector<unsigned int>()>
1101 &function_compute_targets,
1102 const std::function<
void(
const unsigned int, RequestType &)>
1103 & function_create_request = {},
1104 const std::function<void(
const unsigned int,
1105 const RequestType &,
1106 AnswerType &)> &function_answer_request = {},
1107 const std::function<void(
const unsigned int,
const AnswerType &)>
1108 &function_read_answer = {});
1113 std::vector<unsigned int>
1121 RequestType & send_buffer)
override;
1128 const RequestType &buffer_recv,
1129 AnswerType & request_buffer)
override;
1136 const AnswerType & recv_buffer)
override;
1139 const std::function<std::vector<unsigned int>()>
1141 const std::function<void(
const int, RequestType &)>
1143 const std::function<
1144 void(
const unsigned int,
const RequestType &, AnswerType &)>
1146 const std::function<void(
const int,
const AnswerType &)>
1154 template <
typename RequestType,
typename AnswerType>
1155 std::vector<unsigned int>
1156 nbx(
const std::vector<unsigned int> & targets,
1157 const std::function<RequestType(
const unsigned int)> &create_request,
1158 const std::function<AnswerType(
const unsigned int,
1159 const RequestType &)> &answer_request,
1160 const std::function<
void(
const unsigned int,
const AnswerType &)>
1165 targets, create_request, answer_request, process_answer,
comm);
1170 template <
typename RequestType>
1171 std::vector<unsigned int>
1172 nbx(
const std::vector<unsigned int> & targets,
1173 const std::function<RequestType(
const unsigned int)> &create_request,
1174 const std::function<
void(
const unsigned int,
const RequestType &)>
1183 using EmptyType = std::tuple<>;
1185 return nbx<RequestType, EmptyType>(
1189 [&process_request](
const unsigned int source_rank,
1190 const RequestType &request) -> EmptyType {
1191 process_request(source_rank, request);
1199 [](
const unsigned int ,
1200 const EmptyType & ) {},
1206 template <
typename RequestType,
typename AnswerType>
1207 std::vector<unsigned int>
1208 pex(
const std::vector<unsigned int> & targets,
1209 const std::function<RequestType(
const unsigned int)> &create_request,
1210 const std::function<AnswerType(
const unsigned int,
1211 const RequestType &)> &answer_request,
1212 const std::function<
void(
const unsigned int,
const AnswerType &)>
1216 return PEX<RequestType, AnswerType>().run(
1217 targets, create_request, answer_request, process_answer,
comm);
1222 template <
typename RequestType>
1223 std::vector<unsigned int>
1224 pex(
const std::vector<unsigned int> & targets,
1225 const std::function<RequestType(
const unsigned int)> &create_request,
1226 const std::function<
void(
const unsigned int,
const RequestType &)>
1235 using EmptyType = std::tuple<>;
1237 return pex<RequestType, EmptyType>(
1241 [&process_request](
const unsigned int source_rank,
1242 const RequestType &request) -> EmptyType {
1243 process_request(source_rank, request);
1251 [](
const unsigned int ,
1252 const EmptyType & ) {},
1258 template <
typename RequestType,
typename AnswerType>
1259 std::vector<unsigned int>
1261 const std::vector<unsigned int> & targets,
1262 const std::function<RequestType(
const unsigned int)> &create_request,
1263 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1265 const std::function<
void(
const unsigned int,
const AnswerType &)>
1269 return Serial<RequestType, AnswerType>().run(
1270 targets, create_request, answer_request, process_answer,
comm);
1275 template <
typename RequestType>
1276 std::vector<unsigned int>
1278 const std::vector<unsigned int> & targets,
1279 const std::function<RequestType(
const unsigned int)> &create_request,
1280 const std::function<
void(
const unsigned int,
const RequestType &)>
1289 using EmptyType = std::tuple<>;
1291 return serial<RequestType, EmptyType>(
1295 [&process_request](
const unsigned int source_rank,
1296 const RequestType &request) -> EmptyType {
1297 process_request(source_rank, request);
1305 [](
const unsigned int ,
1306 const EmptyType & ) {},
1312 template <
typename RequestType,
typename AnswerType>
1313 std::vector<unsigned int>
1315 const std::vector<unsigned int> & targets,
1316 const std::function<RequestType(
const unsigned int)> &create_request,
1317 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1319 const std::function<
void(
const unsigned int,
const AnswerType &)>
1323 return Selector<RequestType, AnswerType>().run(
1324 targets, create_request, answer_request, process_answer,
comm);
1329 template <
typename RequestType>
1330 std::vector<unsigned int>
1332 const std::vector<unsigned int> & targets,
1333 const std::function<RequestType(
const unsigned int)> &create_request,
1334 const std::function<
void(
const unsigned int,
const RequestType &)>
1343 using EmptyType = std::tuple<>;
1345 return selector<RequestType, EmptyType>(
1349 [&process_request](
const unsigned int source_rank,
1350 const RequestType &request) -> EmptyType {
1351 process_request(source_rank, request);
1359 [](
const unsigned int ,
1360 const EmptyType & ) {},
1366 template <
typename RequestType,
typename AnswerType>
1368 const std::function<std::vector<unsigned int>()>
1369 &function_compute_targets,
1370 const std::function<
void(
const unsigned int, RequestType &)>
1371 & function_create_request,
1372 const std::function<
void(
const unsigned int,
1373 const RequestType &,
1374 AnswerType &)> &function_answer_request,
1375 const std::function<
void(
const unsigned int,
const AnswerType &)>
1376 &function_read_answer)
1377 : function_compute_targets(function_compute_targets)
1378 , function_create_request(function_create_request)
1379 , function_answer_request(function_answer_request)
1380 , function_read_answer(function_read_answer)
1385 template <
typename RequestType,
typename AnswerType>
1386 std::vector<unsigned int>
1389 return function_compute_targets();
1394 template <
typename RequestType,
typename AnswerType>
1397 const unsigned int other_rank,
1398 RequestType & send_buffer)
1400 if (function_create_request)
1401 function_create_request(other_rank, send_buffer);
1406 template <
typename RequestType,
typename AnswerType>
1409 const unsigned int other_rank,
1410 const RequestType &buffer_recv,
1411 AnswerType & request_buffer)
1413 if (function_answer_request)
1414 function_answer_request(other_rank, buffer_recv, request_buffer);
1419 template <
typename RequestType,
typename AnswerType>
1422 const unsigned int other_rank,
1423 const AnswerType & recv_buffer)
1425 if (function_read_answer)
1426 function_read_answer(other_rank, recv_buffer);
1446 namespace ConsensusAlgorithms
1465# ifndef DEAL_II_MSVC
1469 has_unique_elements(
const std::vector<unsigned int> &targets)
1471 std::vector<unsigned int> my_destinations = targets;
1472 std::sort(my_destinations.begin(), my_destinations.end());
1473 return (std::adjacent_find(my_destinations.begin(),
1474 my_destinations.end()) ==
1475 my_destinations.end());
1481 template <
typename RequestType,
typename AnswerType>
1484 const RequestType &,
1492 template <
typename RequestType,
typename AnswerType>
1502 template <
typename RequestType,
typename AnswerType>
1512 template <
typename RequestType,
typename AnswerType>
1514 Process<RequestType, AnswerType> &process,
1522 template <
typename RequestType,
typename AnswerType>
1525 ,
comm(MPI_COMM_NULL)
1530 template <
typename RequestType,
typename AnswerType>
1531 std::vector<unsigned int>
1534 Assert(process !=
nullptr,
1535 ExcMessage(
"This function can only be called if the "
1536 "deprecated non-default constructor of this class "
1537 "has previously been called to set the Process "
1538 "object and a communicator."));
1544 template <
typename RequestType,
typename AnswerType>
1545 std::vector<unsigned int>
1547 Process<RequestType, AnswerType> &process,
1553 process.compute_targets(),
1555 [&process](
const unsigned int target) {
1556 RequestType request;
1557 process.create_request(target, request);
1561 [&process](
const unsigned int source,
const RequestType &request) {
1563 process.answer_request(source, request, answer);
1567 [&process](
const unsigned int target,
const AnswerType &answer) {
1568 process.read_answer(target, answer);
1575 template <
typename RequestType,
typename AnswerType>
1577 Process<RequestType, AnswerType> &process,
1579 : Interface<RequestType, AnswerType>(process,
comm)
1584 template <
typename RequestType,
typename AnswerType>
1585 std::vector<unsigned int>
1587 const std::vector<unsigned int> & targets,
1588 const std::function<RequestType(
const unsigned int)> &create_request,
1589 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1591 const std::function<
void(
const unsigned int,
const AnswerType &)>
1595 Assert(has_unique_elements(targets),
1596 ExcMessage(
"The consensus algorithms expect that each process "
1597 "only sends a single message to another process, "
1598 "but the targets provided include duplicates."));
1600 static CollectiveMutex mutex;
1601 CollectiveMutex::ScopedLock lock(mutex,
comm);
1605 start_communication(targets, create_request,
comm);
1621 while (all_locally_originated_receives_are_completed(process_answer,
1623 maybe_answer_one_request(answer_request,
comm);
1627 signal_finish(
comm);
1632 while (all_remotely_originated_receives_are_completed() ==
false)
1633 maybe_answer_one_request(answer_request,
comm);
1636 clean_up_and_end_communication(
comm);
1638 return std::vector<unsigned int>(requesting_processes.begin(),
1639 requesting_processes.end());
1644 template <
typename RequestType,
typename AnswerType>
1647 const std::vector<unsigned int> & targets,
1648 const std::function<RequestType(
const unsigned int)> &create_request,
1651# ifdef DEAL_II_WITH_MPI
1653 const auto n_targets = targets.size();
1659 send_requests.resize(n_targets);
1660 send_buffers.resize(n_targets);
1664 for (
unsigned int index = 0;
index < n_targets; ++
index)
1666 const unsigned int rank = targets[
index];
1669 auto &send_buffer = send_buffers[
index];
1672 std::vector<char>());
1675 auto ierr = MPI_Isend(send_buffer.data(),
1681 &send_requests[index]);
1687 n_outstanding_answers = n_targets;
1691 (void)create_request;
1698 template <
typename RequestType,
typename AnswerType>
1702 const std::function<
void(
const unsigned int,
const AnswerType &)>
1706# ifdef DEAL_II_WITH_MPI
1714 if (n_outstanding_answers == 0)
1721 int request_is_pending;
1723 const auto ierr = MPI_Iprobe(
1724 MPI_ANY_SOURCE, tag_deliver,
comm, &request_is_pending, &status);
1730 if (request_is_pending == 0)
1737 const auto target = status.MPI_SOURCE;
1744 MPI_Get_count(&status, MPI_CHAR, &message_size);
1747 std::vector<char> recv_buffer(message_size);
1753 const int ierr = MPI_Recv(recv_buffer.data(),
1764 process_answer(target,
1765 Utilities::unpack<AnswerType>(recv_buffer,
1770 --n_outstanding_answers;
1780 return (n_outstanding_answers == 0);
1785 (void)process_answer;
1794 template <
typename RequestType,
typename AnswerType>
1797 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1801# ifdef DEAL_II_WITH_MPI
1816 int request_is_pending;
1817 const auto ierr = MPI_Iprobe(
1818 MPI_ANY_SOURCE, tag_request,
comm, &request_is_pending, &status);
1821 if (request_is_pending != 0)
1825 const auto other_rank = status.MPI_SOURCE;
1827 Assert(requesting_processes.find(other_rank) ==
1828 requesting_processes.end(),
1829 ExcMessage(
"Process is requesting a second time!"));
1830 requesting_processes.insert(other_rank);
1834 auto ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
1838 std::vector<char> buffer_recv(number_amount);
1839 ierr = MPI_Recv(buffer_recv.data(),
1850 request_buffers.emplace_back(std::make_unique<std::vector<char>>());
1851 auto &request_buffer = *request_buffers.back();
1855 Utilities::unpack<RequestType>(
1856 buffer_recv,
false)),
1860 request_requests.emplace_back(std::make_unique<MPI_Request>());
1861 ierr = MPI_Isend(request_buffer.data(),
1862 request_buffer.size(),
1867 request_requests.back().get());
1871 (void)answer_request;
1878 template <
typename RequestType,
typename AnswerType>
1882# ifdef DEAL_II_WITH_MPI
1883 const auto ierr = MPI_Ibarrier(
comm, &barrier_request);
1892 template <
typename RequestType,
typename AnswerType>
1895 AnswerType>::all_remotely_originated_receives_are_completed()
1897# ifdef DEAL_II_WITH_MPI
1898 int all_ranks_reached_barrier;
1899 const auto ierr = MPI_Test(&barrier_request,
1900 &all_ranks_reached_barrier,
1901 MPI_STATUSES_IGNORE);
1903 return all_ranks_reached_barrier != 0;
1911 template <
typename RequestType,
typename AnswerType>
1917# ifdef DEAL_II_WITH_MPI
1920 if (send_requests.size() > 0)
1922 const int ierr = MPI_Waitall(send_requests.size(),
1923 send_requests.data(),
1924 MPI_STATUSES_IGNORE);
1928 int ierr = MPI_Wait(&barrier_request, MPI_STATUS_IGNORE);
1931 for (
auto &i : request_requests)
1933 ierr = MPI_Wait(i.get(), MPI_STATUS_IGNORE);
1940 ierr = MPI_Barrier(
comm);
1949 template <
typename RequestType,
typename AnswerType>
1951 Process<RequestType, AnswerType> &process,
1953 : Interface<RequestType, AnswerType>(process,
comm)
1958 template <
typename RequestType,
typename AnswerType>
1959 std::vector<unsigned int>
1961 const std::vector<unsigned int> & targets,
1962 const std::function<RequestType(
const unsigned int)> &create_request,
1963 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
1965 const std::function<
void(
const unsigned int,
const AnswerType &)>
1969 Assert(has_unique_elements(targets),
1970 ExcMessage(
"The consensus algorithms expect that each process "
1971 "only sends a single message to another process, "
1972 "but the targets provided include duplicates."));
1974 static CollectiveMutex mutex;
1975 CollectiveMutex::ScopedLock lock(mutex,
comm);
1980 const unsigned int n_requests =
1981 start_communication(targets, create_request,
comm);
1984 for (
unsigned int request = 0; request < n_requests; ++request)
1985 answer_one_request(request, answer_request,
comm);
1988 process_incoming_answers(targets.size(), process_answer,
comm);
1991 clean_up_and_end_communication();
1993 return std::vector<unsigned int>(requesting_processes.begin(),
1994 requesting_processes.end());
1999 template <
typename RequestType,
typename AnswerType>
2002 const std::vector<unsigned int> & targets,
2003 const std::function<RequestType(
const unsigned int)> &create_request,
2006# ifdef DEAL_II_WITH_MPI
2012 const unsigned int n_targets = targets.size();
2015 const unsigned int n_sources =
2019 recv_buffers.resize(n_targets);
2020 send_buffers.resize(n_targets);
2021 send_request_requests.resize(n_targets);
2023 send_answer_requests.resize(n_sources);
2024 requests_buffers.resize(n_sources);
2027 for (
unsigned int i = 0; i < n_targets; ++i)
2029 const unsigned int rank = targets[i];
2033 auto &send_buffer = send_buffers[i];
2038 auto ierr = MPI_Isend(send_buffer.data(),
2044 &send_request_requests[i]);
2051 (void)create_request;
2059 template <
typename RequestType,
typename AnswerType>
2062 const unsigned int index,
2063 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2067# ifdef DEAL_II_WITH_MPI
2076 int ierr = MPI_Probe(MPI_ANY_SOURCE, tag_request,
comm, &status);
2080 const unsigned int other_rank = status.MPI_SOURCE;
2082 Assert(requesting_processes.find(other_rank) ==
2083 requesting_processes.end(),
2085 "A process is sending a request after a request from "
2086 "the same process has previously already been "
2087 "received. This algorithm does not expect this to happen."));
2088 requesting_processes.insert(other_rank);
2092 ierr = MPI_Get_count(&status, MPI_CHAR, &number_amount);
2095 std::vector<char> buffer_recv(number_amount);
2096 ierr = MPI_Recv(buffer_recv.data(),
2107 auto &request_buffer = requests_buffers[
index];
2111 Utilities::unpack<RequestType>(
2112 buffer_recv,
false)),
2114 std::vector<char>());
2116 ierr = MPI_Isend(request_buffer.data(),
2117 request_buffer.size(),
2122 &send_answer_requests[index]);
2125 (void)answer_request;
2133 template <
typename RequestType,
typename AnswerType>
2136 const unsigned int n_targets,
2137 const std::function<
void(
const unsigned int,
const AnswerType &)>
2141# ifdef DEAL_II_WITH_MPI
2150 for (
unsigned int i = 0; i < n_targets; ++i)
2155 MPI_Probe(MPI_ANY_SOURCE, tag_deliver,
comm, &status);
2159 const auto other_rank = status.MPI_SOURCE;
2162 const int ierr = MPI_Get_count(&status, MPI_CHAR, &message_size);
2165 std::vector<char> recv_buffer(message_size);
2171 const int ierr = MPI_Recv(recv_buffer.data(),
2182 process_answer(other_rank,
2183 Utilities::unpack<AnswerType>(recv_buffer,
false));
2187 (void)process_answer;
2194 template <
typename RequestType,
typename AnswerType>
2198# ifdef DEAL_II_WITH_MPI
2201 if (send_request_requests.size() > 0)
2203 const int ierr = MPI_Waitall(send_request_requests.size(),
2204 send_request_requests.data(),
2205 MPI_STATUSES_IGNORE);
2210 if (send_answer_requests.size() > 0)
2212 const int ierr = MPI_Waitall(send_answer_requests.size(),
2213 send_answer_requests.data(),
2214 MPI_STATUSES_IGNORE);
2222 template <
typename RequestType,
typename AnswerType>
2224 Process<RequestType, AnswerType> &process,
2226 : Interface<RequestType, AnswerType>(process,
comm)
2231 template <
typename RequestType,
typename AnswerType>
2232 std::vector<unsigned int>
2234 const std::vector<unsigned int> & targets,
2235 const std::function<RequestType(
const unsigned int)> &create_request,
2236 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2238 const std::function<
void(
const unsigned int,
const AnswerType &)>
2245 ExcMessage(
"You shouldn't use the 'Serial' class on "
2246 "communicators that have more than one process "
2247 "associated with it."));
2250 if (targets.size() != 0)
2252 Assert(targets.size() == 1,
2254 "On a single process, the only valid target "
2255 "is process zero (the process itself), which can only be "
2262 const RequestType request =
2263 (create_request ? create_request(0) : RequestType());
2264 const AnswerType answer =
2265 (answer_request ? answer_request(0, request) : AnswerType());
2268 process_answer(0, answer);
2276 template <
typename RequestType,
typename AnswerType>
2278 Process<RequestType, AnswerType> &process,
2280 : Interface<RequestType, AnswerType>(process,
comm)
2285 template <
typename RequestType,
typename AnswerType>
2286 std::vector<unsigned int>
2288 const std::vector<unsigned int> & targets,
2289 const std::function<RequestType(
const unsigned int)> &create_request,
2290 const std::function<AnswerType(
const unsigned int,
const RequestType &)>
2292 const std::function<
void(
const unsigned int,
const AnswerType &)>
2305# ifdef DEAL_II_WITH_MPI
2311 consensus_algo.reset(
new NBX<RequestType, AnswerType>());
2315 consensus_algo.reset(
new PEX<RequestType, AnswerType>());
2317 consensus_algo.reset(
new Serial<RequestType, AnswerType>());
2319 return consensus_algo->run(
2320 targets, create_request, answer_request, process_answer,
comm);
std::vector< unsigned int > compute_targets() override
const std::function< void(const unsigned int, const RequestType &, AnswerType &)> function_answer_request
const std::function< std::vector< unsigned int >()> function_compute_targets
void create_request(const unsigned int other_rank, RequestType &send_buffer) override
const std::function< void(const int, RequestType &)> function_create_request
void read_answer(const unsigned int other_rank, const AnswerType &recv_buffer) override
void answer_request(const unsigned int other_rank, const RequestType &buffer_recv, AnswerType &request_buffer) override
const std::function< void(const int, const AnswerType &)> function_read_answer
AnonymousProcess(const std::function< std::vector< unsigned int >()> &function_compute_targets, const std::function< void(const unsigned int, RequestType &)> &function_create_request={}, const std::function< void(const unsigned int, const RequestType &, AnswerType &)> &function_answer_request={}, const std::function< void(const unsigned int, const AnswerType &)> &function_read_answer={})
std::vector< unsigned int > run()
virtual ~Interface()=default
Interface(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
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
std::vector< unsigned int > run(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
Process< RequestType, AnswerType > * process
bool all_locally_originated_receives_are_completed(const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm &comm)
void maybe_answer_one_request(const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm &comm)
void signal_finish(const MPI_Comm &comm)
std::vector< std::unique_ptr< std::vector< char > > > request_buffers
std::set< unsigned int > requesting_processes
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
MPI_Request barrier_request
NBX(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
std::vector< std::unique_ptr< MPI_Request > > request_requests
std::vector< std::vector< char > > send_buffers
bool all_remotely_originated_receives_are_completed()
unsigned int n_outstanding_answers
void clean_up_and_end_communication(const MPI_Comm &comm)
void start_communication(const std::vector< unsigned int > &targets, const std::function< RequestType(const unsigned int)> &create_request, const MPI_Comm &comm)
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
void answer_one_request(const unsigned int index, const std::function< AnswerType(const unsigned int, const RequestType &)> &answer_request, const MPI_Comm &comm)
std::vector< std::vector< char > > requests_buffers
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 > > send_buffers
PEX(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
void process_incoming_answers(const unsigned int n_targets, const std::function< void(const unsigned int, const AnswerType &)> &process_answer, const MPI_Comm &comm)
std::set< unsigned int > requesting_processes
std::vector< std::vector< char > > recv_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
virtual std::vector< unsigned int > compute_targets()=0
virtual ~Process()=default
virtual void answer_request(const unsigned int other_rank, const RequestType &buffer_recv, AnswerType &request_buffer)
virtual void read_answer(const unsigned int other_rank, const AnswerType &recv_buffer)
virtual void create_request(const unsigned int other_rank, RequestType &send_buffer)
virtual ~Selector()=default
Selector(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
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
Serial(Process< RequestType, AnswerType > &process, const MPI_Comm &comm)
#define DEAL_II_NAMESPACE_OPEN
#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)
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 > 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 > 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 > 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 compute_n_point_to_point_communications(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
void run(const Iterator &begin, const typename identity< Iterator >::type &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)