18#include <deal.II/base/mpi.templates.h>
25#include <boost/serialization/utility.hpp>
35 namespace MatrixFreeFunctions
37 namespace VectorDataExchange
40 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner)
41 : partitioner(partitioner)
88 const unsigned int communication_channel,
93 std::vector<MPI_Request> & requests)
const
96#ifndef DEAL_II_WITH_MPI
97 (void)communication_channel;
98 (void)locally_owned_array;
100 (void)temporary_storage;
103 partitioner->export_to_ghosted_array_start(communication_channel,
118 std::vector<MPI_Request> & requests)
const
120 (void)locally_owned_array;
122#ifndef DEAL_II_WITH_MPI
126 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
135 const unsigned int communication_channel,
140 std::vector<MPI_Request> & requests)
const
142 (void)locally_owned_array;
144#ifndef DEAL_II_WITH_MPI
145 (void)vector_operation;
146 (void)communication_channel;
148 (void)temporary_storage;
151 partitioner->import_from_ghosted_array_start(vector_operation,
152 communication_channel,
168 std::vector<MPI_Request> & requests)
const
171#ifndef DEAL_II_WITH_MPI
172 (void)vector_operation;
173 (void)locally_owned_storage;
175 (void)temporary_storage;
178 partitioner->import_from_ghosted_array_finish(vector_operation,
180 locally_owned_storage,
199 const unsigned int communication_channel,
204 std::vector<MPI_Request> & requests)
const
207#ifndef DEAL_II_WITH_MPI
208 (void)communication_channel;
209 (void)locally_owned_array;
211 (void)temporary_storage;
214 partitioner->export_to_ghosted_array_start(communication_channel,
229 std::vector<MPI_Request> & requests)
const
231 (void)locally_owned_array;
233#ifndef DEAL_II_WITH_MPI
237 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
246 const unsigned int communication_channel,
251 std::vector<MPI_Request> & requests)
const
253 (void)locally_owned_array;
255#ifndef DEAL_II_WITH_MPI
256 (void)vector_operation;
257 (void)communication_channel;
259 (void)temporary_storage;
262 partitioner->import_from_ghosted_array_start(vector_operation,
263 communication_channel,
279 std::vector<MPI_Request> & requests)
const
282#ifndef DEAL_II_WITH_MPI
283 (void)vector_operation;
284 (void)locally_owned_storage;
286 (void)temporary_storage;
289 partitioner->import_from_ghosted_array_finish(vector_operation,
291 locally_owned_storage,
308 template <
typename Number>
313 for (
const auto &my_ghosts :
314 partitioner->ghost_indices_within_larger_ghost_set())
315 for (
unsigned int j = my_ghosts.first; j < my_ghosts.second; ++j)
323 std::pair<std::vector<unsigned int>,
324 std::vector<std::pair<unsigned int, unsigned int>>>
326 const std::vector<unsigned int> &sm_export_ptr,
327 const std::vector<unsigned int> &sm_export_indices)
329 std::vector<unsigned int> recv_ptr = {0};
330 std::vector<unsigned int> recv_indices;
331 std::vector<unsigned int> recv_len;
333 for (
unsigned int i = 0; i + 1 < sm_export_ptr.size(); ++i)
335 if (sm_export_ptr[i] != sm_export_ptr[i + 1])
337 recv_indices.push_back(sm_export_indices[sm_export_ptr[i]]);
338 recv_len.push_back(1);
340 for (
unsigned int j = sm_export_ptr[i] + 1;
341 j < sm_export_ptr[i + 1];
343 if (recv_indices.back() + recv_len.back() !=
344 sm_export_indices[j])
346 recv_indices.push_back(sm_export_indices[j]);
347 recv_len.push_back(1);
352 recv_ptr.push_back(recv_indices.size());
355 std::pair<std::vector<unsigned int>,
356 std::vector<std::pair<unsigned int, unsigned int>>>
359 result.first = recv_ptr;
361 for (
unsigned int i = 0; i < recv_indices.size(); ++i)
362 result.second.emplace_back(recv_indices[i], recv_len[i]);
372 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
374 :
comm(partitioner->get_mpi_communicator())
375 , comm_sm(communicator_sm)
376 , n_local_elements(partitioner->locally_owned_range().n_elements())
377 , n_ghost_elements(partitioner->ghost_indices().n_elements())
378 , n_global_elements(partitioner->locally_owned_range().size())
380#ifndef DEAL_II_WITH_MPI
386 const auto &is_locally_owned = partitioner->locally_owned_range();
387 const auto &is_locally_ghost = partitioner->ghost_indices();
388 const auto &ghost_indices_within_larger_ghost_set =
389 partitioner->ghost_indices_within_larger_ghost_set();
403 std::vector<unsigned int> ghost_indices_subset_data_ptr = {0};
404 std::vector<unsigned int> ghost_indices_subset_data_indices;
407 std::vector<unsigned int> import_indices_data_ptr = {0};
408 std::vector<unsigned int> import_indices_data_indices;
411 std::vector<unsigned int> sm_export_data_ptr = {0};
412 std::vector<unsigned int> sm_export_data_indices;
415 std::vector<unsigned int> sm_export_data_this_ptr = {0};
416 std::vector<unsigned int> sm_export_data_this_indices;
419 std::vector<unsigned int> sm_import_data_ptr = {};
420 std::vector<unsigned int> sm_import_data_indices;
423 std::vector<unsigned int> sm_import_data_this_ptr = {0};
424 std::vector<unsigned int> sm_import_data_this_indices;
427 const auto sm_ranks =
431 std::vector<unsigned int> owning_ranks_of_ghosts(
432 is_locally_ghost.n_elements());
435 process(is_locally_owned,
438 owning_ranks_of_ghosts,
443 std::pair<types::global_dof_index, types::global_dof_index>>,
444 std::vector<unsigned int>>
445 consensus_algorithm(process,
comm);
446 consensus_algorithm.run();
450 std::vector<unsigned int> shifts_indices;
451 for (
const auto &pair : ghost_indices_within_larger_ghost_set)
452 for (
unsigned int k = pair.first; k < pair.second; ++k)
453 shifts_indices.push_back(k);
458 std::map<unsigned int, std::vector<types::global_dof_index>>
459 rank_to_local_indices;
461 for (
unsigned int i = 0; i < owning_ranks_of_ghosts.size(); ++i)
462 rank_to_local_indices[owning_ranks_of_ghosts[i]].push_back(i);
464 unsigned int compressed_offset = 0;
466 for (
const auto &rank_and_local_indices : rank_to_local_indices)
468 const auto sm_ranks_ptr = std::find(sm_ranks.begin(),
470 rank_and_local_indices.first);
472 if (sm_ranks_ptr == sm_ranks.end())
475 rank_and_local_indices.first,
476 shifts_indices[compressed_offset],
477 static_cast<unsigned int>(
478 rank_and_local_indices.second.size())
481 for (
unsigned int i = 0;
482 i < rank_and_local_indices.second.size();
484 ghost_indices_subset_data_indices.push_back(
485 shifts_indices[i + compressed_offset]);
487 ghost_indices_subset_data_ptr.push_back(
488 ghost_indices_subset_data_indices.size());
504 std::distance(sm_ranks.begin(), sm_ranks_ptr));
506 sm_export_data_ptr.push_back(
507 sm_export_data_ptr.back() +
508 rank_and_local_indices.second.size());
510 for (
unsigned int i = compressed_offset;
512 rank_and_local_indices.second.size() + compressed_offset;
514 sm_export_data_this_indices.push_back(
515 shifts_indices[i] + is_locally_owned.n_elements());
517 sm_export_data_this_ptr.push_back(
518 sm_export_data_this_indices.size());
520 compressed_offset += rank_and_local_indices.second.size();
523 sm_export_data_indices.resize(sm_export_data_ptr.back());
530 for (
const auto &rank_and_global_indices : rank_to_global_indices)
532 const auto sm_ranks_ptr =
533 std::find(sm_ranks.begin(),
535 rank_and_global_indices.first);
537 if (sm_ranks_ptr == sm_ranks.end())
540 rank_and_global_indices.first,
541 static_cast<unsigned int>(
542 import_indices_data_indices.size()),
543 static_cast<unsigned int>(
544 rank_and_global_indices.second.n_elements())
547 for (
const auto i : rank_and_global_indices.second)
548 import_indices_data_indices.push_back(
549 is_locally_owned.index_within_set(i));
551 import_indices_data_ptr.push_back(
552 import_indices_data_indices.size());
557 std::distance(sm_ranks.begin(), sm_ranks_ptr));
559 for (
const auto i : rank_and_global_indices.second)
560 sm_import_data_this_indices.push_back(
561 is_locally_owned.index_within_set(i));
563 sm_import_data_this_ptr.push_back(
564 sm_import_data_this_indices.size());
568 sm_import_data_ptr = sm_import_data_this_ptr;
569 sm_import_data_indices.resize(sm_import_data_this_ptr.back());
579 const int ierr = MPI_Isend(sm_export_data_this_indices.data() +
580 sm_export_data_this_ptr[i],
581 sm_export_data_this_ptr[i + 1] -
582 sm_export_data_this_ptr[i],
587 requests.data() + i);
594 MPI_Irecv(sm_import_data_indices.data() + sm_import_data_ptr[i],
595 sm_import_data_ptr[i + 1] - sm_import_data_ptr[i],
605 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
616 const int ierr = MPI_Isend(sm_import_data_this_indices.data() +
617 sm_import_data_this_ptr[i],
618 sm_import_data_this_ptr[i + 1] -
619 sm_import_data_this_ptr[i],
624 requests.data() + i);
631 MPI_Irecv(sm_export_data_indices.data() + sm_export_data_ptr[i],
632 sm_export_data_ptr[i + 1] - sm_export_data_ptr[i],
642 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
647 this->n_ghost_indices_in_larger_set_by_remote_rank =
652 ghost_indices_subset_data_ptr, ghost_indices_subset_data_indices);
660 import_indices_data_indices);
666 sm_export_data_indices);
670 sm_export_data_this_indices);
676 sm_import_data_indices);
680 sm_import_data_this_indices);
689 const unsigned int communication_channel,
694 std::vector<MPI_Request> & requests)
const
711 std::vector<MPI_Request> & requests)
const
724 const unsigned int communication_channel,
729 std::vector<MPI_Request> & requests)
const
732 communication_channel,
749 std::vector<MPI_Request> & requests)
const
752 locally_owned_storage,
763 const unsigned int communication_channel,
768 std::vector<MPI_Request> & requests)
const
785 std::vector<MPI_Request> & requests)
const
798 const unsigned int communication_channel,
803 std::vector<MPI_Request> & requests)
const
806 communication_channel,
823 std::vector<MPI_Request> & requests)
const
826 locally_owned_storage,
835 template <
typename Number>
838 const unsigned int communication_channel,
843 std::vector<MPI_Request> & requests)
const
845#ifndef DEAL_II_WITH_MPI
848 (void)communication_channel;
852 (void)temporary_storage;
869 communication_channel + 0,
878 const int ierr = MPI_Isend(&dummy,
882 communication_channel + 0,
884 requests.data() + i);
891 const unsigned int offset =
895 const int ierr = MPI_Irecv(
900 communication_channel + 1,
915 temporary_storage[k] =
919 const int ierr = MPI_Isend(
924 communication_channel + 1,
935 template <
typename Number>
941 std::vector<MPI_Request> & requests)
const
945#ifndef DEAL_II_WITH_MPI
959 [&](
const unsigned int i) -> std::pair<unsigned int, unsigned int> {
969 for (
unsigned int c = 0;
981 const auto s = split(i);
1019 const unsigned int offset =
1023 for (
unsigned int c = 0,
1032 const unsigned int idx_1 =
1034 const unsigned int idx_2 =
1044 else if (idx_1 < idx_2)
1046 ghost_array[idx_1] = ghost_array[idx_2];
1047 ghost_array[idx_2] = 0.0;
1066 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1074 template <
typename Number>
1078 const unsigned int communication_channel,
1083 std::vector<MPI_Request> & requests)
const
1087#ifndef DEAL_II_WITH_MPI
1091 (void)communication_channel;
1094 (void)temporary_storage;
1110 const int ierr = MPI_Isend(&dummy,
1114 communication_channel + 1,
1116 requests.data() + i);
1127 communication_channel + 1,
1135 for (
unsigned int c = 0,
1143 const unsigned int idx_1 =
1154 else if (idx_2 < idx_1)
1156 buffer[idx_2] = buffer[idx_1];
1157 buffer[idx_1] = 0.0;
1171 const int ierr = MPI_Isend(
1176 communication_channel + 0,
1189 *temporary_storage.
data())>,
1191 communication_channel + 0,
1203 template <
typename Number>
1211 std::vector<MPI_Request> & requests)
const
1213#ifndef DEAL_II_WITH_MPI
1220 (void)temporary_storage;
1234 [&](
const unsigned int i) -> std::pair<unsigned int, unsigned int> {
1247 for (
unsigned int c = 0;
1261 const auto &s = split(i);
1300 else if (s.first == 1)
1306 for (
unsigned int l = 0;
1310 temporary_storage[k++];
1321 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1394 template <
typename Number>
1403 sizeof(Number) * i.second);
1407 std::memset(ghost_array.
data() + i.first,
1409 sizeof(Number) * i.second);
value_type * data() const noexcept
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
const MPI_Comm & get_sm_mpi_communicator() const
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
Full(const std::shared_ptr< const Utilities::MPI::Partitioner > &partitioner, const MPI_Comm &communicator_sm)
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
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)