21#include <boost/serialization/utility.hpp>
31 namespace ComputeIndexOwner
39 : use_vector(use_vector)
47 const bool index_range_contiguous,
48 const std::size_t size)
58 if (!index_range_contiguous)
66 const std::size_t start,
67 const std::size_t end,
75 if (
data.empty() && end > start)
86 std::fill(
data.begin() + start,
data.begin() + end, value);
94 std::fill(
data.begin() + start,
data.begin() + end, value);
99 for (
auto i = start; i < end; ++i)
173#ifdef DEAL_II_WITH_MPI
177 std::map<
unsigned int,
182 const auto owned_indices_size_actual =
187 owned_indices_size_actual ==
188 owned_indices.
size(),
200 std::pair<types::global_dof_index, types::global_dof_index>
201 index_range(*interval->begin(), interval->last() + 1);
205 while (index_range.first != index_range.second)
207 Assert(index_range.first < index_range.second,
210 const unsigned int owner =
231 if (owner == my_rank)
237 dic_local_received += next_index - index_range.first;
242 buffers[owner].emplace_back(index_range.first, next_index);
244 index_range.first = next_index;
249 std::vector<MPI_Request> request;
252 if (owned_indices_size_actual == owned_indices.
size())
271 for (
const auto &rank_pair : buffers)
273 request.push_back(MPI_Request());
274 const int ierr = MPI_Isend(rank_pair.second.data(),
275 rank_pair.second.size() * 2,
289 int ierr = MPI_Probe(MPI_ANY_SOURCE, mpi_tag,
comm, &status);
294 ierr = MPI_Get_count(&status,
299 const auto other_rank = status.MPI_SOURCE;
305 std::pair<types::global_dof_index, types::global_dof_index>>
306 buffer(number_amount / 2);
307 ierr = MPI_Recv(buffer.data(),
316 for (
auto interval : buffer)
338 dic_local_received += interval.second - interval.first;
350 using RequestType = std::vector<
351 std::pair<types::global_dof_index, types::global_dof_index>>;
353 ConsensusAlgorithms::selector<RequestType>(
356 std::vector<unsigned int> targets;
357 targets.reserve(buffers.size());
358 for (
const auto &rank_pair : buffers)
359 targets.emplace_back(rank_pair.first);
365 [&buffers](
const unsigned int target_rank) -> RequestType {
366 return buffers.at(target_rank);
370 [&](
const unsigned int source_rank,
371 const RequestType &request) ->
void {
373 for (
auto interval : request)
383 "Multiple processes seem to own the same global index. "
384 "A possible reason is that the sets of locally owned "
385 "indices are not distinct."));
386 Assert(interval.first < interval.second,
392 "The specified interval is not handled by the current process."));
415 if (request.size() > 0)
417 const int ierr = MPI_Waitall(request.size(),
419 MPI_STATUSES_IGNORE);
435#ifdef DEAL_II_WITH_MPI
464 const IndexSet & indices_to_look_up,
466 std::vector<unsigned int> &owning_ranks,
467 const bool track_index_requests)
468 : owned_indices(owned_indices)
469 , indices_to_look_up(indices_to_look_up)
473 , track_index_requests(track_index_requests)
474 , owning_ranks(owning_ranks)
484 const unsigned int other_rank,
487 std::vector<unsigned int> & request_buffer)
489 unsigned int owner_index_guess = 0;
490 for (
const auto &interval : buffer_recv)
491 for (
auto i = interval.first; i < interval.second; ++i)
493 const unsigned int actual_owner =
495 request_buffer.push_back(actual_owner);
507 std::vector<unsigned int>
510 std::vector<unsigned int> targets;
513 unsigned int index = 0;
514 unsigned int owner_index_guess = 0;
530 if (targets.empty() || targets.back() != other_rank)
531 targets.push_back(other_rank);
533 indices.first.push_back(i);
534 indices.second.push_back(index);
549 const unsigned int other_rank,
556 is.
add_indices(indices_i.begin(), indices_i.end());
562 send_buffer.emplace_back(*interval->begin(), interval->last() + 1);
569 const unsigned int other_rank,
570 const std::vector<unsigned int> &recv_buffer)
572 const auto &recv_indices =
575 for (
unsigned int j = 0; j < recv_indices.size(); ++j)
581 std::map<unsigned int, IndexSet>
585 ExcMessage(
"Must enable index range tracking in "
586 "constructor of ConsensusAlgorithmProcess"));
588 std::map<unsigned int, ::IndexSet> requested_indices;
590#ifdef DEAL_II_WITH_MPI
602 std::vector<MPI_Request> send_requests;
613 std::vector<std::vector<unsigned int>> send_data(
requesters.size());
614 for (
unsigned int i = 0; i <
requesters.size(); ++i)
623 IndexSet &my_index_set = requested_indices[j.first];
625 for (
const auto &interval : j.second)
626 my_index_set.
add_range(index_offset + interval.first,
627 index_offset + interval.second);
634 send_data[i].push_back(j.first);
635 send_data[i].push_back(j.second.size());
636 for (
const auto &interval : j.second)
638 send_data[i].push_back(interval.first);
639 send_data[i].push_back(interval.second);
642 send_requests.push_back(MPI_Request());
643 const int ierr = MPI_Isend(send_data[i].data(),
649 &send_requests.back());
659 int ierr = MPI_Probe(MPI_ANY_SOURCE, mpi_tag,
comm, &status);
664 ierr = MPI_Get_count(&status, MPI_UNSIGNED, &number_amount);
669 std::vector<std::pair<unsigned int, unsigned int>> buffer(
671 ierr = MPI_Recv(buffer.data(),
684 unsigned int offset = 0;
685 while (offset < buffer.size())
691 for (
unsigned int i = offset + 1;
692 i < offset + buffer[offset].second + 1;
694 my_index_set.
add_range(index_offset + buffer[i].first,
695 index_offset + buffer[i].second);
700 IndexSet &index_set = requested_indices[buffer[offset].first];
701 if (index_set.
size() == 0)
705 offset += buffer[offset].second + 1;
710 if (send_requests.size() > 0)
712 const auto ierr = MPI_Waitall(send_requests.size(),
713 send_requests.data(),
714 MPI_STATUSES_IGNORE);
720 for (
const auto &it : requested_indices)
726 "The indices requested from the current "
727 "MPI rank should be locally owned here!"));
733 return requested_indices;
740 const unsigned int index_within_dict,
741 const unsigned int rank_of_request,
742 const unsigned int rank_of_owner,
743 unsigned int & owner_index_guess)
752 auto &request =
requesters[owner_index_guess];
753 if (request.empty() || request.back().first != rank_of_request)
754 request.emplace_back(
756 std::vector<std::pair<unsigned int, unsigned int>>());
758 auto &intervals = request.back().second;
759 if (intervals.empty() || intervals.back().second != index_within_dict)
760 intervals.emplace_back(index_within_dict, index_within_dict + 1);
762 ++intervals.back().second;
IntervalIterator end_intervals() const
size_type n_elements() const
void set_size(const size_type size)
IntervalIterator begin_intervals() const
void subtract_set(const IndexSet &other)
void add_range(const size_type begin, const size_type end)
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
const unsigned int my_rank
virtual std::vector< unsigned int > compute_targets() override
virtual void answer_request(const unsigned int other_rank, const std::vector< std::pair< types::global_dof_index, types::global_dof_index > > &buffer_recv, std::vector< unsigned int > &request_buffer) override
virtual void read_answer(const unsigned int other_rank, const std::vector< unsigned int > &recv_buffer) override
virtual void create_request(const unsigned int other_rank, std::vector< std::pair< types::global_dof_index, types::global_dof_index > > &send_buffer) override
std::vector< std::vector< std::pair< unsigned int, std::vector< std::pair< unsigned int, unsigned int > > > > > requesters
std::vector< unsigned int > & owning_ranks
const IndexSet & indices_to_look_up
std::map< unsigned int, std::pair< std::vector< types::global_dof_index >, std::vector< unsigned int > > > indices_to_look_up_by_dict_rank
const IndexSet & owned_indices
std::map< unsigned int, IndexSet > get_requesters()
ConsensusAlgorithmsPayload(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm comm, std::vector< unsigned int > &owning_ranks, const bool track_index_requests=false)
void append_index_origin(const unsigned int index_within_dictionary, const unsigned int rank_of_request, const unsigned int rank_of_owner, unsigned int &owner_index_guess)
const bool track_index_requests
index_type & operator[](const std::size_t index)
bool entry_has_been_set(const std::size_t index) const
void reinit(const bool use_vector, const bool index_range_contiguous, const std::size_t size)
FlexibleIndexStorage(const bool use_vector=true)
static const index_type invalid_index_value
void fill(const std::size_t start, const std::size_t end, const index_type &value)
std::map< std::size_t, index_type > data_map
std::vector< index_type > data
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
T sum(const T &t, const MPI_Comm mpi_communicator)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int global_dof_index
std::vector< unsigned int > actually_owning_rank_list
FlexibleIndexStorage actually_owning_ranks
unsigned int dof_to_dict_rank(const types::global_dof_index i)
types::global_dof_index get_index_offset(const unsigned int rank)
types::global_dof_index locally_owned_size
types::global_dof_index dofs_per_process
unsigned int n_dict_procs_in_owned_indices
static constexpr unsigned int sparsity_factor
unsigned int stride_small_size
static constexpr unsigned int range_minimum_grain_size
std::pair< types::global_dof_index, types::global_dof_index > local_range
void reinit(const IndexSet &owned_indices, const MPI_Comm comm)
void partition(const IndexSet &owned_indices, const MPI_Comm comm)
unsigned int get_owning_rank_index(const unsigned int rank_in_owned_indices, const unsigned int guess=0)
types::global_dof_index size
#define DEAL_II_DOF_INDEX_MPI_TYPE