18#include <deal.II/base/mpi.templates.h>
25#ifdef DEAL_II_WITH_64BIT_INDICES
26# include <deal.II/base/mpi_consensus_algorithms.templates.h>
37 namespace MatrixFreeFunctions
39 namespace VectorDataExchange
42 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner)
43 : partitioner(partitioner)
90 const unsigned int communication_channel,
95 std::vector<MPI_Request> & requests)
const
98#ifndef DEAL_II_WITH_MPI
99 (void)communication_channel;
100 (void)locally_owned_array;
102 (void)temporary_storage;
105 partitioner->export_to_ghosted_array_start(communication_channel,
120 std::vector<MPI_Request> & requests)
const
122 (void)locally_owned_array;
124#ifndef DEAL_II_WITH_MPI
128 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
137 const unsigned int communication_channel,
142 std::vector<MPI_Request> & requests)
const
144 (void)locally_owned_array;
146#ifndef DEAL_II_WITH_MPI
147 (void)vector_operation;
148 (void)communication_channel;
150 (void)temporary_storage;
153 partitioner->import_from_ghosted_array_start(vector_operation,
154 communication_channel,
170 std::vector<MPI_Request> & requests)
const
173#ifndef DEAL_II_WITH_MPI
174 (void)vector_operation;
175 (void)locally_owned_storage;
177 (void)temporary_storage;
180 partitioner->import_from_ghosted_array_finish(vector_operation,
182 locally_owned_storage,
201 const unsigned int communication_channel,
206 std::vector<MPI_Request> & requests)
const
209#ifndef DEAL_II_WITH_MPI
210 (void)communication_channel;
211 (void)locally_owned_array;
213 (void)temporary_storage;
216 partitioner->export_to_ghosted_array_start(communication_channel,
231 std::vector<MPI_Request> & requests)
const
233 (void)locally_owned_array;
235#ifndef DEAL_II_WITH_MPI
239 partitioner->export_to_ghosted_array_finish(ghost_array, requests);
248 const unsigned int communication_channel,
253 std::vector<MPI_Request> & requests)
const
255 (void)locally_owned_array;
257#ifndef DEAL_II_WITH_MPI
258 (void)vector_operation;
259 (void)communication_channel;
261 (void)temporary_storage;
264 partitioner->import_from_ghosted_array_start(vector_operation,
265 communication_channel,
281 std::vector<MPI_Request> & requests)
const
284#ifndef DEAL_II_WITH_MPI
285 (void)vector_operation;
286 (void)locally_owned_storage;
288 (void)temporary_storage;
291 partitioner->import_from_ghosted_array_finish(vector_operation,
293 locally_owned_storage,
310 template <
typename Number>
315 for (
const auto &my_ghosts :
316 partitioner->ghost_indices_within_larger_ghost_set())
317 for (
unsigned int j = my_ghosts.first; j < my_ghosts.second; ++j)
325 std::pair<std::vector<unsigned int>,
326 std::vector<std::pair<unsigned int, unsigned int>>>
328 const std::vector<unsigned int> &sm_export_ptr,
329 const std::vector<unsigned int> &sm_export_indices)
331 std::vector<unsigned int> recv_ptr = {0};
332 std::vector<unsigned int> recv_indices;
333 std::vector<unsigned int> recv_len;
335 for (
unsigned int i = 0; i + 1 < sm_export_ptr.size(); i++)
337 if (sm_export_ptr[i] != sm_export_ptr[i + 1])
339 recv_indices.push_back(sm_export_indices[sm_export_ptr[i]]);
340 recv_len.push_back(1);
342 for (
unsigned int j = sm_export_ptr[i] + 1;
343 j < sm_export_ptr[i + 1];
345 if (recv_indices.back() + recv_len.back() !=
346 sm_export_indices[j])
348 recv_indices.push_back(sm_export_indices[j]);
349 recv_len.push_back(1);
354 recv_ptr.push_back(recv_indices.size());
357 std::pair<std::vector<unsigned int>,
358 std::vector<std::pair<unsigned int, unsigned int>>>
361 result.first = recv_ptr;
363 for (
unsigned int i = 0; i < recv_indices.size(); ++i)
364 result.second.emplace_back(recv_indices[i], recv_len[i]);
374 const std::shared_ptr<const Utilities::MPI::Partitioner> &partitioner,
376 :
comm(partitioner->get_mpi_communicator())
377 , comm_sm(communicator_sm)
378 , n_local_elements(partitioner->locally_owned_range().n_elements())
379 , n_ghost_elements(partitioner->ghost_indices().n_elements())
382#ifndef DEAL_II_WITH_MPI
388 const auto &is_locally_owned = partitioner->locally_owned_range();
389 const auto &is_locally_ghost = partitioner->ghost_indices();
390 const auto &ghost_indices_within_larger_ghost_set =
391 partitioner->ghost_indices_within_larger_ghost_set();
405 std::vector<unsigned int> ghost_indices_subset_data_ptr = {0};
406 std::vector<unsigned int> ghost_indices_subset_data_indices;
409 std::vector<unsigned int> import_indices_data_ptr = {0};
410 std::vector<unsigned int> import_indices_data_indices;
413 std::vector<unsigned int> sm_export_data_ptr = {0};
414 std::vector<unsigned int> sm_export_data_indices;
417 std::vector<unsigned int> sm_export_data_this_ptr = {0};
418 std::vector<unsigned int> sm_export_data_this_indices;
421 std::vector<unsigned int> sm_import_data_ptr = {};
422 std::vector<unsigned int> sm_import_data_indices;
425 std::vector<unsigned int> sm_import_data_this_ptr = {0};
426 std::vector<unsigned int> sm_import_data_this_indices;
429 const auto sm_ranks =
433 std::vector<unsigned int> owning_ranks_of_ghosts(
434 is_locally_ghost.n_elements());
437 process(is_locally_owned,
440 owning_ranks_of_ghosts,
444 std::pair<types::global_dof_index, types::global_dof_index>,
446 consensus_algorithm(process,
comm);
447 consensus_algorithm.run();
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 =
899 Utilities::MPI::internal::mpi_type_id(buffer.
data()),
901 communication_channel + 1,
916 temporary_storage[k] =
923 Utilities::MPI::internal::mpi_type_id(data_this.
data()),
925 communication_channel + 1,
937 template <
typename Number>
943 std::vector<MPI_Request> & requests)
const
947#ifndef DEAL_II_WITH_MPI
961 [&](
const unsigned int i) -> std::pair<unsigned int, unsigned int> {
971 for (
unsigned int c = 0;
983 const auto s =
split(i);
1021 const unsigned int offset =
1025 for (
unsigned int c = 0,
1034 const unsigned int idx_1 =
1036 const unsigned int idx_2 =
1046 else if (idx_1 < idx_2)
1048 ghost_array[idx_1] = ghost_array[idx_2];
1049 ghost_array[idx_2] = 0.0;
1068 MPI_Waitall(requests.size(), requests.data(), MPI_STATUSES_IGNORE);
1076 template <
typename Number>
1080 const unsigned int communication_channel,
1085 std::vector<MPI_Request> & requests)
const
1089#ifndef DEAL_II_WITH_MPI
1093 (void)communication_channel;
1096 (void)temporary_storage;
1112 const int ierr = MPI_Isend(&dummy,
1116 communication_channel + 1,
1118 requests.data() + i);
1129 communication_channel + 1,
1137 for (
unsigned int c = 0,
1145 const unsigned int idx_1 =
1156 else if (idx_2 < idx_1)
1158 buffer[idx_2] = buffer[idx_1];
1159 buffer[idx_1] = 0.0;
1176 Utilities::MPI::internal::mpi_type_id(buffer.
data()),
1178 communication_channel + 0,
1187 const int ierr = MPI_Irecv(
1190 Utilities::MPI::internal::mpi_type_id(temporary_storage.
data()),
1192 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)
std::vector< value_type > split(const typename ::Triangulation< dim, spacedim >::cell_iterator &parent, const value_type parent_value)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
TrilinosWrappers::types::int_type n_global_elements(const Epetra_BlockMap &map)
const std::vector< unsigned int > mpi_processes_within_communicator(const MPI_Comm &comm_large, const MPI_Comm &comm_small)
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)
*braid_SplitCommworld & comm