15#ifndef dealii_mpi_consensus_algorithm_h
16#define dealii_mpi_consensus_algorithm_h
21#include <deal.II/base/mpi.templates.h>
131 namespace ConsensusAlgorithms
157 template <
typename RequestType,
typename AnswerType>
173 virtual std::vector<unsigned int>
232 template <
typename RequestType,
typename AnswerType>
255 std::vector<unsigned int>
281 virtual std::vector<unsigned int>
283 const std::vector<unsigned int> &
targets,
284 const std::function<
RequestType(
const unsigned int)> &create_request,
285 const std::function<
AnswerType(
const unsigned int,
287 const std::function<
void(
const unsigned int,
const AnswerType &)>
306 template <
typename RequestType,
typename AnswerType>
326 virtual std::vector<unsigned int>
328 const std::vector<unsigned int> &
targets,
329 const std::function<
RequestType(
const unsigned int)> &create_request,
330 const std::function<
AnswerType(
const unsigned int,
332 const std::function<
void(
const unsigned int,
const AnswerType &)>
337#ifdef DEAL_II_WITH_MPI
383 const std::function<
void(
const unsigned int,
const AnswerType &)>
409 const std::function<
AnswerType(
const unsigned int,
419 const std::vector<unsigned int> &
targets,
420 const std::function<
RequestType(
const unsigned int)> &create_request,
476 template <
typename RequestType,
typename AnswerType>
477 std::vector<unsigned int>
479 const std::function<
RequestType(
const unsigned int)> &create_request,
480 const std::function<
AnswerType(
const unsigned int,
482 const std::function<
void(
const unsigned int,
const AnswerType &)>
523 template <
typename RequestType>
524 std::vector<unsigned int>
526 const std::function<
RequestType(
const unsigned int)> &create_request,
527 const std::function<
void(
const unsigned int,
const RequestType &)>
556 template <
typename RequestType,
typename AnswerType>
576 virtual std::vector<unsigned int>
578 const std::vector<unsigned int> &
targets,
579 const std::function<
RequestType(
const unsigned int)> &create_request,
580 const std::function<
AnswerType(
const unsigned int,
582 const std::function<
void(
const unsigned int,
const AnswerType &)>
587#ifdef DEAL_II_WITH_MPI
624 const std::vector<unsigned int> &
targets,
625 const std::function<
RequestType(
const unsigned int)> &create_request,
634 const unsigned int index,
635 const std::function<
AnswerType(
const unsigned int,
645 const unsigned int n_targets,
646 const std::function<
void(
const unsigned int,
const AnswerType &)>
716 template <
typename RequestType,
typename AnswerType>
717 std::vector<unsigned int>
719 const std::function<
RequestType(
const unsigned int)> &create_request,
720 const std::function<
AnswerType(
const unsigned int,
722 const std::function<
void(
const unsigned int,
const AnswerType &)>
763 template <
typename RequestType>
764 std::vector<unsigned int>
766 const std::function<
RequestType(
const unsigned int)> &create_request,
767 const std::function<
void(
const unsigned int,
const RequestType &)>
776 template <
typename RequestType,
typename AnswerType>
791 virtual std::vector<unsigned int>
793 const std::vector<unsigned int> &
targets,
794 const std::function<
RequestType(
const unsigned int)> &create_request,
795 const std::function<
AnswerType(
const unsigned int,
797 const std::function<
void(
const unsigned int,
const AnswerType &)>
836 template <
typename RequestType,
typename AnswerType>
837 std::vector<unsigned int>
839 const std::vector<unsigned int> &
targets,
840 const std::function<
RequestType(
const unsigned int)> &create_request,
843 const std::function<
void(
const unsigned int,
const AnswerType &)>
876 template <
typename RequestType>
877 std::vector<unsigned int>
879 const std::vector<unsigned int> &
targets,
880 const std::function<
RequestType(
const unsigned int)> &create_request,
881 const std::function<
void(
const unsigned int,
const RequestType &)>
899 template <
typename RequestType,
typename AnswerType>
921 virtual 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<
AnswerType(
const unsigned int,
927 const std::function<
void(
const unsigned int,
const AnswerType &)>
982 template <
typename RequestType,
typename AnswerType>
983 std::vector<unsigned int>
985 const std::vector<unsigned int> &
targets,
986 const std::function<
RequestType(
const unsigned int)> &create_request,
989 const std::function<
void(
const unsigned int,
const AnswerType &)>
1030 template <
typename RequestType>
1031 std::vector<unsigned int>
1033 const std::vector<unsigned int> &
targets,
1034 const std::function<
RequestType(
const unsigned int)> &create_request,
1035 const std::function<
void(
const unsigned int,
const RequestType &)>
1044 template <
typename RequestType,
typename AnswerType>
1045 std::vector<unsigned int>
1046 nbx(
const std::vector<unsigned int> &
targets,
1047 const std::function<
RequestType(
const unsigned int)> &create_request,
1048 const std::function<
AnswerType(
const unsigned int,
1050 const std::function<
void(
const unsigned int,
const AnswerType &)>
1060 template <
typename RequestType>
1061 std::vector<unsigned int>
1062 nbx(
const std::vector<unsigned int> &
targets,
1063 const std::function<
RequestType(
const unsigned int)> &create_request,
1064 const std::function<
void(
const unsigned int,
const RequestType &)>
1089 [](
const unsigned int ,
1096 template <
typename RequestType,
typename AnswerType>
1097 std::vector<unsigned int>
1098 pex(
const std::vector<unsigned int> &
targets,
1099 const std::function<
RequestType(
const unsigned int)> &create_request,
1100 const std::function<
AnswerType(
const unsigned int,
1102 const std::function<
void(
const unsigned int,
const AnswerType &)>
1112 template <
typename RequestType>
1113 std::vector<unsigned int>
1114 pex(
const std::vector<unsigned int> &
targets,
1115 const std::function<
RequestType(
const unsigned int)> &create_request,
1116 const std::function<
void(
const unsigned int,
const RequestType &)>
1141 [](
const unsigned int ,
1148 template <
typename RequestType,
typename AnswerType>
1149 std::vector<unsigned int>
1151 const std::vector<unsigned int> &
targets,
1152 const std::function<
RequestType(
const unsigned int)> &create_request,
1155 const std::function<
void(
const unsigned int,
const AnswerType &)>
1165 template <
typename RequestType>
1166 std::vector<unsigned int>
1168 const std::vector<unsigned int> &
targets,
1169 const std::function<
RequestType(
const unsigned int)> &create_request,
1170 const std::function<
void(
const unsigned int,
const RequestType &)>
1195 [](
const unsigned int ,
1202 template <
typename RequestType,
typename AnswerType>
1203 std::vector<unsigned int>
1205 const std::vector<unsigned int> &
targets,
1206 const std::function<
RequestType(
const unsigned int)> &create_request,
1209 const std::function<
void(
const unsigned int,
const AnswerType &)>
1219 template <
typename RequestType>
1220 std::vector<unsigned int>
1222 const std::vector<unsigned int> &
targets,
1223 const std::function<
RequestType(
const unsigned int)> &create_request,
1224 const std::function<
void(
const unsigned int,
const RequestType &)>
1249 [](
const unsigned int ,
1271 namespace ConsensusAlgorithms
1297# ifdef DEAL_II_WITH_MPI
1302 std::rethrow_exception(exception);
1310 <<
"----------------------------------------------------"
1315 <<
" on processing: " << std::endl
1316 << exc.
what() << std::endl
1317 <<
"Aborting!" << std::endl
1318 <<
"----------------------------------------------------"
1324 catch (std::exception &exc)
1329 <<
"----------------------------------------------------"
1332 <<
"Exception within ConsensusAlgorithm"
1334 <<
" on processing: " << std::endl
1335 << exc.what() << std::endl
1336 <<
"Aborting!" << std::endl
1337 <<
"----------------------------------------------------"
1348 <<
"----------------------------------------------------"
1351 <<
"Unknown exception within ConsensusAlgorithm!" << std::endl
1352 <<
"Aborting!" << std::endl
1353 <<
"----------------------------------------------------"
1364 std::rethrow_exception(exception);
1371 template <
typename RequestType,
typename AnswerType>
1382 template <
typename RequestType,
typename AnswerType>
1392 template <
typename RequestType,
typename AnswerType>
1402 template <
typename RequestType,
typename AnswerType>
1403 std::vector<unsigned int>
1411 process.compute_targets(),
1413 [&process](
const unsigned int target) {
1414 RequestType request;
1415 process.create_request(target, request);
1421 process.answer_request(source, request, answer);
1426 process.read_answer(target, answer);
1433 template <
typename RequestType,
typename AnswerType>
1434 std::vector<unsigned int>
1436 const std::vector<unsigned int> &
targets,
1437 const std::function<
RequestType(
const unsigned int)> &create_request,
1440 const std::function<
void(
const unsigned int,
const AnswerType &)>
1445 ExcMessage(
"The consensus algorithms expect that each process "
1446 "only sends a single message to another process, "
1447 "but the targets provided include duplicates."));
1449 static CollectiveMutex mutex;
1450 CollectiveMutex::ScopedLock lock(mutex,
comm);
1456 start_communication(
targets, create_request,
comm);
1472 while (all_locally_originated_receives_are_completed(
process_answer,
1474 maybe_answer_one_request(answer_request,
comm);
1478 signal_finish(
comm);
1483 while (all_remotely_originated_receives_are_completed() ==
false)
1484 maybe_answer_one_request(answer_request,
comm);
1487 clean_up_and_end_communication(
comm);
1494 return std::vector<unsigned int>(requesting_processes.begin(),
1495 requesting_processes.end());
1500 template <
typename RequestType,
typename AnswerType>
1503 const std::vector<unsigned int> &
targets,
1504 const std::function<
RequestType(
const unsigned int)> &create_request,
1507# ifdef DEAL_II_WITH_MPI
1509 const auto n_targets =
targets.size();
1515 send_requests.resize(n_targets);
1516 send_buffers.resize(n_targets);
1520 for (
unsigned int index = 0;
index < n_targets; ++
index)
1528 std::vector<char>());
1537 &send_requests[index]);
1543 n_outstanding_answers = n_targets;
1547 (void)create_request;
1554 template <
typename RequestType,
typename AnswerType>
1558 const std::function<
void(
const unsigned int,
const AnswerType &)>
1562# ifdef DEAL_II_WITH_MPI
1570 if (n_outstanding_answers == 0)
1592 const auto target = status.MPI_SOURCE;
1625 --n_outstanding_answers;
1635 return (n_outstanding_answers == 0);
1649 template <
typename RequestType,
typename AnswerType>
1656# ifdef DEAL_II_WITH_MPI
1683 requesting_processes.end(),
1684 ExcMessage(
"Process is requesting a second time!"));
1705 request_buffers.emplace_back(std::make_unique<std::vector<char>>());
1710 Utilities::unpack<RequestType>(
1715 request_requests.emplace_back(std::make_unique<MPI_Request>());
1722 request_requests.back().get());
1726 (void)answer_request;
1733 template <
typename RequestType,
typename AnswerType>
1737# ifdef DEAL_II_WITH_MPI
1747 template <
typename RequestType,
typename AnswerType>
1750 AnswerType>::all_remotely_originated_receives_are_completed()
1752# ifdef DEAL_II_WITH_MPI
1766 template <
typename RequestType,
typename AnswerType>
1772# ifdef DEAL_II_WITH_MPI
1775 if (send_requests.size() > 0)
1778 send_requests.data(),
1786 for (
auto &i : request_requests)
1804 template <
typename RequestType,
typename AnswerType>
1805 std::vector<unsigned int>
1807 const std::vector<unsigned int> &
targets,
1808 const std::function<
RequestType(
const unsigned int)> &create_request,
1811 const std::function<
void(
const unsigned int,
const AnswerType &)>
1816 ExcMessage(
"The consensus algorithms expect that each process "
1817 "only sends a single message to another process, "
1818 "but the targets provided include duplicates."));
1820 static CollectiveMutex mutex;
1821 CollectiveMutex::ScopedLock lock(mutex,
comm);
1829 start_communication(
targets, create_request,
comm);
1832 for (
unsigned int request = 0; request <
n_requests; ++request)
1833 answer_one_request(request, answer_request,
comm);
1839 clean_up_and_end_communication();
1846 return std::vector<unsigned int>(requesting_processes.begin(),
1847 requesting_processes.end());
1852 template <
typename RequestType,
typename AnswerType>
1855 const std::vector<unsigned int> &
targets,
1856 const std::function<
RequestType(
const unsigned int)> &create_request,
1859# ifdef DEAL_II_WITH_MPI
1865 const unsigned int n_targets =
targets.size();
1872 recv_buffers.resize(n_targets);
1873 send_buffers.resize(n_targets);
1874 send_request_requests.resize(n_targets);
1880 for (
unsigned int i = 0; i < n_targets; ++i)
1882 const unsigned int rank =
targets[i];
1897 &send_request_requests[i]);
1904 (void)create_request;
1912 template <
typename RequestType,
typename AnswerType>
1915 const unsigned int index,
1920# ifdef DEAL_II_WITH_MPI
1933 const unsigned int other_rank = status.MPI_SOURCE;
1936 requesting_processes.end(),
1938 "A process is sending a request after a request from "
1939 "the same process has previously already been "
1940 "received. This algorithm does not expect this to happen."));
1964 Utilities::unpack<RequestType>(
1967 std::vector<char>());
1975 &send_answer_requests[index]);
1978 (void)answer_request;
1986 template <
typename RequestType,
typename AnswerType>
1989 const unsigned int n_targets,
1990 const std::function<
void(
const unsigned int,
const AnswerType &)>
1994# ifdef DEAL_II_WITH_MPI
2003 for (
unsigned int i = 0; i < n_targets; ++i)
2036 Utilities::unpack<AnswerType>(
recv_buffer,
false));
2047 template <
typename RequestType,
typename AnswerType>
2051# ifdef DEAL_II_WITH_MPI
2054 if (send_request_requests.size() > 0)
2057 send_request_requests.data(),
2063 if (send_answer_requests.size() > 0)
2066 send_answer_requests.data(),
2075 template <
typename RequestType,
typename AnswerType>
2076 std::vector<unsigned int>
2078 const std::vector<unsigned int> &
targets,
2079 const std::function<
RequestType(
const unsigned int)> &create_request,
2082 const std::function<
void(
const unsigned int,
const AnswerType &)>
2088 ExcMessage(
"You shouldn't use the 'Serial' class on "
2089 "communicators that have more than one process "
2090 "associated with it."));
2097 "On a single process, the only valid target "
2098 "is process zero (the process itself), which can only be "
2106 (create_request ? create_request(0) :
RequestType());
2108 (answer_request ? answer_request(0, request) :
AnswerType());
2119 template <
typename RequestType,
typename AnswerType>
2120 std::vector<unsigned int>
2122 const std::vector<unsigned int> &
targets,
2123 const std::function<
RequestType(
const unsigned int)> &create_request,
2126 const std::function<
void(
const unsigned int,
const AnswerType &)>
2139# ifdef DEAL_II_WITH_MPI
2153 return consensus_algo->run(
const char * get_exc_name() const
virtual const char * what() const noexcept override
virtual ~Interface()=default
std::vector< unsigned int > run(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
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 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
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
#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 > 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)
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &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)
*braid_SplitCommworld & comm