66 : _src(map.src().begin(), map.src().end()),
67 _dest(map.dest().begin(), map.dest().end()),
68 _sizes_remote(_src.size(), 0), _displs_remote(_src.size() + 1),
69 _sizes_local(_dest.size()), _displs_local(_dest.size() + 1)
77 assert(std::ranges::is_sorted(_src));
78 assert(std::ranges::is_sorted(_dest));
84 ierr = MPI_Dist_graph_create_adjacent(
85 map.
comm(), _src.size(), _src.data(), MPI_UNWEIGHTED, _dest.size(),
86 _dest.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm0);
91 ierr = MPI_Dist_graph_create_adjacent(
92 map.
comm(), _dest.size(), _dest.data(), MPI_UNWEIGHTED, _src.size(),
93 _src.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm1);
98 std::span owners = map.
owners();
99 std::vector<std::int32_t> perm(owners.size());
100 std::iota(perm.begin(), perm.end(), 0);
105 std::span ghosts = map.
ghosts();
106 std::vector<int> owners_sorted(owners.size());
107 std::vector<std::int64_t> ghosts_sorted(owners.size());
108 std::ranges::transform(perm, owners_sorted.begin(),
109 [&owners](
auto idx) { return owners[idx]; });
110 std::ranges::transform(perm, ghosts_sorted.begin(),
111 [&ghosts](
auto idx) { return ghosts[idx]; });
119 assert(_sizes_remote.size() == _src.size());
120 assert(_displs_remote.size() == _src.size() + 1);
121 auto begin = owners_sorted.begin();
122 for (std::size_t i = 0; i < _src.size(); i++)
124 auto upper = std::upper_bound(begin, owners_sorted.end(), _src[i]);
125 std::size_t num_ind = std::ranges::distance(begin, upper);
126 _displs_remote[i + 1] = _displs_remote[i] + num_ind;
127 _sizes_remote[i] = num_ind;
138 assert(_sizes_local.size() == _dest.size());
139 assert(_displs_local.size() == _dest.size() + 1);
140 _sizes_remote.reserve(1);
141 _sizes_local.reserve(1);
142 ierr = MPI_Neighbor_alltoall(_sizes_remote.data(), 1, MPI_INT32_T,
143 _sizes_local.data(), 1, MPI_INT32_T,
147 std::partial_sum(_sizes_local.begin(), _sizes_local.end(),
148 std::next(_displs_local.begin()));
150 assert(
static_cast<int>(ghosts_sorted.size()) == _displs_remote.back());
154 std::vector<std::int64_t> recv_buffer(_displs_local.back(), 0);
155 ierr = MPI_Neighbor_alltoallv(
156 ghosts_sorted.data(), _sizes_remote.data(), _displs_remote.data(),
157 MPI_INT64_T, recv_buffer.data(), _sizes_local.data(),
158 _displs_local.data(), MPI_INT64_T, _comm1.comm());
161 const std::array<std::int64_t, 2> range = map.
local_range();
164 std::ranges::for_each(recv_buffer, [range](
auto idx)
165 { assert(idx >= range[0] and idx < range[1]); });
170 for (
auto& x : {std::ref(_sizes_local), std::ref(_displs_local),
171 std::ref(_sizes_remote), std::ref(_displs_remote)})
173 std::ranges::transform(x.get(), x.get().begin(),
174 [bs](
auto e) { return e * bs; });
181 std::vector<typename container_type::value_type> idx(recv_buffer.size()
183 std::int64_t offset = range[0] * bs;
184 for (std::size_t i = 0; i < recv_buffer.size(); i++)
185 for (
int j = 0; j < bs; j++)
186 idx[i * bs + j] = (recv_buffer[i] * bs + j) - offset;
187 _local_inds = std::move(idx);
192 std::vector<typename container_type::value_type> idx(perm.size() * bs);
193 for (std::size_t i = 0; i < perm.size(); i++)
194 for (
int j = 0; j < bs; j++)
195 idx[i * bs + j] = perm[i] * bs + j;
196 _remote_inds = std::move(idx);
281 std::span<MPI_Request> requests)
const
283 if (requests.size() != _dest.size() + _src.size())
285 throw std::runtime_error(
286 "Point-to-point scatterer has wrong number of MPI_Requests.");
290 if (_sizes_local.empty() and _sizes_remote.empty())
293 for (std::size_t i = 0; i < _src.size(); ++i)
295 int ierr = MPI_Irecv(recv_buffer + _displs_remote[i], _sizes_remote[i],
297 _comm0.comm(), &requests[i]);
301 for (std::size_t i = 0; i < _dest.size(); ++i)
303 int ierr = MPI_Isend(send_buffer + _displs_local[i], _sizes_local[i],
305 &requests[i + _src.size()]);
366 std::span<MPI_Request> requests)
const
368 if (requests.size() != _dest.size() + _src.size())
370 throw std::runtime_error(
371 "Point-to-point scatterer has wrong number of MPI_Requests.");
375 if (_sizes_local.empty() and _sizes_remote.empty())
379 for (std::size_t i = 0; i < _dest.size(); i++)
381 int ierr = MPI_Irecv(recv_buffer + _displs_local[i], _sizes_local[i],
383 _comm0.comm(), &requests[i]);
389 for (std::size_t i = 0; i < _src.size(); i++)
391 int ierr = MPI_Isend(send_buffer + _displs_remote[i], _sizes_remote[i],
393 &requests[i + _dest.size()]);