18#include <deal.II/base/mpi.templates.h>
26#include <boost/serialization/utility.hpp>
36 namespace MatrixFreeFunctions
38 namespace VectorDataExchange
41 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner)
42 : partitioner(partitioner)
89 const unsigned int communication_channel,
94 std::vector<MPI_Request> & requests)
const
97#ifndef DEAL_II_WITH_MPI
98 (void)communication_channel;
99 (void)locally_owned_array;
101 (void)temporary_storage;
104 partitioner->export_to_ghosted_array_start(communication_channel,
119 std::vector<MPI_Request> & requests)
const
121 (void)locally_owned_array;
123#ifndef DEAL_II_WITH_MPI
127 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
136 const unsigned int communication_channel,
141 std::vector<MPI_Request> & requests)
const
143 (void)locally_owned_array;
145#ifndef DEAL_II_WITH_MPI
146 (void)vector_operation;
147 (void)communication_channel;
149 (void)temporary_storage;
152 partitioner->import_from_ghosted_array_start(vector_operation,
153 communication_channel,
169 std::vector<MPI_Request> & requests)
const
172#ifndef DEAL_II_WITH_MPI
173 (void)vector_operation;
174 (void)locally_owned_storage;
176 (void)temporary_storage;
179 partitioner->import_from_ghosted_array_finish(vector_operation,
181 locally_owned_storage,
200 const unsigned int communication_channel,
205 std::vector<MPI_Request> & requests)
const
208#ifndef DEAL_II_WITH_MPI
209 (void)communication_channel;
210 (void)locally_owned_array;
212 (void)temporary_storage;
215 partitioner->export_to_ghosted_array_start(communication_channel,
230 std::vector<MPI_Request> & requests)
const
232 (void)locally_owned_array;
234#ifndef DEAL_II_WITH_MPI
238 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
247 const unsigned int communication_channel,
252 std::vector<MPI_Request> & requests)
const
254 (void)locally_owned_array;
256#ifndef DEAL_II_WITH_MPI
257 (void)vector_operation;
258 (void)communication_channel;
260 (void)temporary_storage;
263 partitioner->import_from_ghosted_array_start(vector_operation,
264 communication_channel,
280 std::vector<MPI_Request> & requests)
const
283#ifndef DEAL_II_WITH_MPI
284 (void)vector_operation;
285 (void)locally_owned_storage;
287 (void)temporary_storage;
290 partitioner->import_from_ghosted_array_finish(vector_operation,
292 locally_owned_storage,
309 template <
typename Number>
314 for (
const auto &my_ghosts :
315 partitioner->ghost_indices_within_larger_ghost_set())
316 for (
unsigned int j = my_ghosts.first; j < my_ghosts.second; ++j)
324 std::pair<std::vector<unsigned int>,
325 std::vector<std::pair<unsigned int, unsigned int>>>
327 const std::vector<unsigned int> &sm_export_ptr,
328 const std::vector<unsigned int> &sm_export_indices)
330 std::vector<unsigned int> recv_ptr = {0};
331 std::vector<unsigned int> recv_indices;
332 std::vector<unsigned int> recv_len;
334 for (
unsigned int i = 0; i + 1 < sm_export_ptr.size(); ++i)
336 if (sm_export_ptr[i] != sm_export_ptr[i + 1])
338 recv_indices.push_back(sm_export_indices[sm_export_ptr[i]]);
339 recv_len.push_back(1);
341 for (
unsigned int j = sm_export_ptr[i] + 1;
342 j < sm_export_ptr[i + 1];
344 if (recv_indices.back() + recv_len.back() !=
345 sm_export_indices[j])
347 recv_indices.push_back(sm_export_indices[j]);
348 recv_len.push_back(1);
353 recv_ptr.push_back(recv_indices.size());
356 std::pair<std::vector<unsigned int>,
357 std::vector<std::pair<unsigned int, unsigned int>>>
360 result.first = recv_ptr;
362 for (
unsigned int i = 0; i < recv_indices.size(); ++i)
363 result.second.emplace_back(recv_indices[i], recv_len[i]);
373 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
375 :
comm(partitioner->get_mpi_communicator())
376 , comm_sm(communicator_sm)
377 , n_local_elements(partitioner->locally_owned_range().n_elements())
378 , n_ghost_elements(partitioner->ghost_indices().n_elements())
379 , n_global_elements(partitioner->locally_owned_range().size())
381#ifndef DEAL_II_WITH_MPI
387 const auto &is_locally_owned = partitioner->locally_owned_range();
388 const auto &is_locally_ghost = partitioner->ghost_indices();
389 const auto &ghost_indices_within_larger_ghost_set =
390 partitioner->ghost_indices_within_larger_ghost_set();
404 std::vector<unsigned int> ghost_indices_subset_data_ptr = {0};
405 std::vector<unsigned int> ghost_indices_subset_data_indices;
408 std::vector<unsigned int> import_indices_data_ptr = {0};
409 std::vector<unsigned int> import_indices_data_indices;
412 std::vector<unsigned int> sm_export_data_ptr = {0};
413 std::vector<unsigned int> sm_export_data_indices;
416 std::vector<unsigned int> sm_export_data_this_ptr = {0};
417 std::vector<unsigned int> sm_export_data_this_indices;
420 std::vector<unsigned int> sm_import_data_ptr = {};
421 std::vector<unsigned int> sm_import_data_indices;
424 std::vector<unsigned int> sm_import_data_this_ptr = {0};
425 std::vector<unsigned int> sm_import_data_this_indices;
428 const auto sm_ranks =
432 std::vector<unsigned int> owning_ranks_of_ghosts(
433 is_locally_ghost.n_elements());
436 process(is_locally_owned,
439 owning_ranks_of_ghosts,
444 std::pair<types::global_dof_index, types::global_dof_index>>,
445 std::vector<unsigned int>>
447 consensus_algorithm.
run(process,
comm);
451 std::vector<unsigned int> shifts_indices;
452 for (
const auto &pair : ghost_indices_within_larger_ghost_set)
453 for (
unsigned int k = pair.first; k < pair.second; ++k)
454 shifts_indices.push_back(k);
459 std::map<unsigned int, std::vector<types::global_dof_index>>
460 rank_to_local_indices;
462 for (
unsigned int i = 0; i < owning_ranks_of_ghosts.size(); ++i)
463 rank_to_local_indices[owning_ranks_of_ghosts[i]].push_back(i);
465 unsigned int compressed_offset = 0;
467 for (
const auto &rank_and_local_indices : rank_to_local_indices)
469 const auto sm_ranks_ptr = std::find(sm_ranks.begin(),
471 rank_and_local_indices.first);
473 if (sm_ranks_ptr == sm_ranks.end())
476 rank_and_local_indices.first,
477 shifts_indices[compressed_offset],
478 static_cast<unsigned int>(
479 rank_and_local_indices.second.size())
482 for (
unsigned int i = 0;
483 i < rank_and_local_indices.second.size();
485 ghost_indices_subset_data_indices.push_back(
486 shifts_indices[i + compressed_offset]);
488 ghost_indices_subset_data_ptr.push_back(
489 ghost_indices_subset_data_indices.size());
505 std::distance(sm_ranks.begin(), sm_ranks_ptr));
507 sm_export_data_ptr.push_back(
508 sm_export_data_ptr.back() +
509 rank_and_local_indices.second.size());
511 for (
unsigned int i = compressed_offset;
513 rank_and_local_indices.second.size() + compressed_offset;
515 sm_export_data_this_indices.push_back(
516 shifts_indices[i] + is_locally_owned.n_elements());
518 sm_export_data_this_ptr.push_back(
519 sm_export_data_this_indices.size());
521 compressed_offset += rank_and_local_indices.second.size();
524 sm_export_data_indices.resize(sm_export_data_ptr.back());
531 for (
const auto &rank_and_global_indices : rank_to_global_indices)
533 const auto sm_ranks_ptr =
534 std::find(sm_ranks.begin(),
536 rank_and_global_indices.first);
538 if (sm_ranks_ptr == sm_ranks.end())
541 rank_and_global_indices.first,
542 static_cast<unsigned int>(
543 import_indices_data_indices.size()),
544 static_cast<unsigned int>(
545 rank_and_global_indices.second.n_elements())
548 for (
const auto i : rank_and_global_indices.second)
549 import_indices_data_indices.push_back(
550 is_locally_owned.index_within_set(i));
552 import_indices_data_ptr.push_back(
553 import_indices_data_indices.size());
558 std::distance(sm_ranks.begin(), sm_ranks_ptr));
560 for (
const auto i : rank_and_global_indices.second)
561 sm_import_data_this_indices.push_back(
562 is_locally_owned.index_within_set(i));
564 sm_import_data_this_ptr.push_back(
565 sm_import_data_this_indices.size());
569 sm_import_data_ptr = sm_import_data_this_ptr;
570 sm_import_data_indices.resize(sm_import_data_this_ptr.back());
580 const int ierr = MPI_Isend(sm_export_data_this_indices.data() +
581 sm_export_data_this_ptr[i],
582 sm_export_data_this_ptr[i + 1] -
583 sm_export_data_this_ptr[i],
588 requests.data() + i);
595 MPI_Irecv(sm_import_data_indices.data() + sm_import_data_ptr[i],
596 sm_import_data_ptr[i + 1] - sm_import_data_ptr[i],
606 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
617 const int ierr = MPI_Isend(sm_import_data_this_indices.data() +
618 sm_import_data_this_ptr[i],
619 sm_import_data_this_ptr[i + 1] -
620 sm_import_data_this_ptr[i],
625 requests.data() + i);
632 MPI_Irecv(sm_export_data_indices.data() + sm_export_data_ptr[i],
633 sm_export_data_ptr[i + 1] - sm_export_data_ptr[i],
643 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
648 this->n_ghost_indices_in_larger_set_by_remote_rank =
653 ghost_indices_subset_data_ptr, ghost_indices_subset_data_indices);
661 import_indices_data_indices);
667 sm_export_data_indices);
671 sm_export_data_this_indices);
677 sm_import_data_indices);
681 sm_import_data_this_indices);
690 const unsigned int communication_channel,
695 std::vector<MPI_Request> & requests)
const
712 std::vector<MPI_Request> & requests)
const
725 const unsigned int communication_channel,
730 std::vector<MPI_Request> & requests)
const
733 communication_channel,
750 std::vector<MPI_Request> & requests)
const
753 locally_owned_storage,
764 const unsigned int communication_channel,
769 std::vector<MPI_Request> & requests)
const
786 std::vector<MPI_Request> & requests)
const
799 const unsigned int communication_channel,
804 std::vector<MPI_Request> & requests)
const
807 communication_channel,
824 std::vector<MPI_Request> & requests)
const
827 locally_owned_storage,
836 template <
typename Number>
839 const unsigned int communication_channel,
844 std::vector<MPI_Request> & requests)
const
846#ifndef DEAL_II_WITH_MPI
849 (void)communication_channel;
853 (void)temporary_storage;
870 communication_channel + 0,
879 const int ierr = MPI_Isend(&dummy,
883 communication_channel + 0,
885 requests.data() + i);
892 const unsigned int offset =
896 const int ierr = MPI_Irecv(
901 communication_channel + 1,
916 temporary_storage[k] =
920 const int ierr = MPI_Isend(
925 communication_channel + 1,
936 template <
typename Number>
942 std::vector<MPI_Request> & requests)
const
946#ifndef DEAL_II_WITH_MPI
960 [&](
const unsigned int i) -> std::pair<unsigned int, unsigned int> {
970 for (
unsigned int c = 0;
982 const auto s = split(i);
1020 const unsigned int offset =
1024 for (
unsigned int c = 0,
1033 const unsigned int idx_1 =
1035 const unsigned int idx_2 =
1045 else if (idx_1 < idx_2)
1047 ghost_array[idx_1] = ghost_array[idx_2];
1048 ghost_array[idx_2] = 0.0;
1067 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1075 template <
typename Number>
1079 const unsigned int communication_channel,
1084 std::vector<MPI_Request> & requests)
const
1088#ifndef DEAL_II_WITH_MPI
1092 (void)communication_channel;
1095 (void)temporary_storage;
1111 const int ierr = MPI_Isend(&dummy,
1115 communication_channel + 1,
1117 requests.data() + i);
1128 communication_channel + 1,
1136 for (
unsigned int c = 0,
1144 const unsigned int idx_1 =
1155 else if (idx_2 < idx_1)
1157 buffer[idx_2] = buffer[idx_1];
1158 buffer[idx_1] = 0.0;
1172 const int ierr = MPI_Isend(
1177 communication_channel + 0,
1190 *temporary_storage.
data())>,
1192 communication_channel + 0,
1204 template <
typename Number>
1212 std::vector<MPI_Request> & requests)
const
1214#ifndef DEAL_II_WITH_MPI
1221 (void)temporary_storage;
1235 [&](
const unsigned int i) -> std::pair<unsigned int, unsigned int> {
1248 for (
unsigned int c = 0;
1262 const auto &s = split(i);
1301 else if (s.first == 1)
1307 for (
unsigned int l = 0;
1311 temporary_storage[k++];
1322 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1395 template <
typename Number>
1404 sizeof(Number) * i.second);
1408 std::memset(ghost_array.
data() + i.first,
1410 sizeof(Number) * i.second);
value_type * data() const noexcept
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::map< unsigned int, IndexSet > get_requesters()
void export_to_ghosted_array_start(const unsigned int communication_channel, const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< double > &temporary_storage, std::vector< MPI_Request > &requests) const override
std::vector< unsigned int > n_ghost_indices_in_larger_set_by_remote_rank
unsigned int locally_owned_size() const override
unsigned int n_ghost_indices() const override
void reset_ghost_values(const ArrayView< double > &ghost_array) const override
std::vector< unsigned int > sm_import_ranks
std::vector< std::array< unsigned int, 3 > > ghost_targets_data
const unsigned int n_ghost_elements
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > sm_export_data_this
virtual unsigned int n_import_sm_procs() const override
void export_to_ghosted_array_finish(const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, std::vector< MPI_Request > &requests) const override
void import_from_ghosted_array_start(const VectorOperation::values vector_operation, const unsigned int communication_channel, const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< double > &temporary_storage, std::vector< MPI_Request > &requests) const override
const unsigned int n_local_elements
void export_to_ghosted_array_start_impl(const unsigned int communication_channel, const ArrayView< const Number > &locally_owned_array, const std::vector< ArrayView< const Number > > &shared_arrays, const ArrayView< Number > &ghost_array, const ArrayView< Number > &temporary_storage, std::vector< MPI_Request > &requests) const
unsigned int n_import_indices() const override
void import_from_ghosted_array_finish_impl(const VectorOperation::values vector_operation, const ArrayView< Number > &locally_owned_storage, const std::vector< ArrayView< const Number > > &shared_arrays, const ArrayView< Number > &ghost_array, const ArrayView< const Number > &temporary_storage, std::vector< MPI_Request > &requests) const
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > sm_export_data
std::vector< std::array< unsigned int, 3 > > import_targets_data
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > ghost_indices_subset_data
void import_from_ghosted_array_finish(const VectorOperation::values vector_operation, const ArrayView< double > &locally_owned_storage, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< const double > &temporary_storage, std::vector< MPI_Request > &requests) const override
std::vector< unsigned int > sm_ghost_ranks
MPI_Comm get_sm_mpi_communicator() const
void export_to_ghosted_array_finish_impl(const ArrayView< const Number > &locally_owned_array, const std::vector< ArrayView< const Number > > &shared_arrays, const ArrayView< Number > &ghost_array, std::vector< MPI_Request > &requests) const
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > sm_import_data
void import_from_ghosted_array_start_impl(const VectorOperation::values vector_operation, const unsigned int communication_channel, const ArrayView< const Number > &locally_owned_array, const std::vector< ArrayView< const Number > > &shared_arrays, const ArrayView< Number > &ghost_array, const ArrayView< Number > &temporary_storage, std::vector< MPI_Request > &requests) const
Full(const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner, const MPI_Comm communicator_sm)
void reset_ghost_values_impl(const ArrayView< Number > &ghost_array) const
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > sm_import_data_this
const types::global_dof_index n_global_elements
virtual types::global_dof_index size() const override
std::pair< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > import_indices_data
const std::shared_ptr< const Utilities::MPI::Partitioner > partitioner
void export_to_ghosted_array_finish(const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, std::vector< MPI_Request > &requests) const override
PartitionerWrapper(const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner)
types::global_dof_index size() const override
unsigned int n_import_indices() const override
unsigned int locally_owned_size() const override
void export_to_ghosted_array_start(const unsigned int communication_channel, const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< double > &temporary_storage, std::vector< MPI_Request > &requests) const override
void reset_ghost_values_impl(const ArrayView< Number > &ghost_array) const
void import_from_ghosted_array_finish(const VectorOperation::values vector_operation, const ArrayView< double > &locally_owned_storage, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< const double > &temporary_storage, std::vector< MPI_Request > &requests) const override
void reset_ghost_values(const ArrayView< double > &ghost_array) const override
unsigned int n_ghost_indices() const override
unsigned int n_import_sm_procs() const override
void import_from_ghosted_array_start(const VectorOperation::values vector_operation, const unsigned int communication_channel, const ArrayView< const double > &locally_owned_array, const std::vector< ArrayView< const double > > &shared_arrays, const ArrayView< double > &ghost_array, const ArrayView< double > &temporary_storage, std::vector< MPI_Request > &requests) const override
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcNeedsMPI()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
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< std::vector< unsigned int >, std::vector< std::pair< unsigned int, unsigned int > > > compress_to_contiguous_ranges(const std::vector< unsigned int > &sm_export_ptr, const std::vector< unsigned int > &sm_export_indices)