67 : _src(map.src().begin(), map.src().end()),
68 _dest(map.dest().begin(), map.dest().end()),
69 _sizes_remote(_src.size(), 0), _displs_remote(_src.size() + 1),
70 _sizes_local(_dest.size()), _displs_local(_dest.size() + 1)
78 assert(std::ranges::is_sorted(_src));
79 assert(std::ranges::is_sorted(_dest));
85 ierr = MPI_Dist_graph_create_adjacent(
86 map.
comm(), _src.size(), _src.data(), MPI_UNWEIGHTED, _dest.size(),
87 _dest.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm0);
92 ierr = MPI_Dist_graph_create_adjacent(
93 map.
comm(), _dest.size(), _dest.data(), MPI_UNWEIGHTED, _src.size(),
94 _src.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm1);
99 std::span owners = map.
owners();
100 std::vector<std::int32_t> perm(owners.size());
101 std::iota(perm.begin(), perm.end(), 0);
106 std::span ghosts = map.
ghosts();
107 std::vector<int> owners_sorted(owners.size());
108 std::vector<std::int64_t> ghosts_sorted(owners.size());
109 std::ranges::transform(perm, owners_sorted.begin(),
110 [&owners](
auto idx) { return owners[idx]; });
111 std::ranges::transform(perm, ghosts_sorted.begin(),
112 [&ghosts](
auto idx) { return ghosts[idx]; });
120 assert(_sizes_remote.size() == _src.size());
121 assert(_displs_remote.size() == _src.size() + 1);
122 auto begin = owners_sorted.begin();
123 for (std::size_t i = 0; i < _src.size(); i++)
125 auto upper = std::upper_bound(begin, owners_sorted.end(), _src[i]);
126 std::size_t num_ind = std::distance(begin, upper);
127 _displs_remote[i + 1] = _displs_remote[i] + num_ind;
128 _sizes_remote[i] = num_ind;
139 assert(_sizes_local.size() == _dest.size());
140 assert(_displs_local.size() == _dest.size() + 1);
141 _sizes_remote.reserve(1);
142 _sizes_local.reserve(1);
143 ierr = MPI_Neighbor_alltoall(_sizes_remote.data(), 1, MPI_INT32_T,
144 _sizes_local.data(), 1, MPI_INT32_T,
148 std::partial_sum(_sizes_local.begin(), _sizes_local.end(),
149 std::next(_displs_local.begin()));
151 assert((
int)ghosts_sorted.size() == _displs_remote.back());
152 assert((
int)ghosts_sorted.size() == _displs_remote.back());
156 std::vector<std::int64_t> recv_buffer(_displs_local.back(), 0);
157 ierr = MPI_Neighbor_alltoallv(
158 ghosts_sorted.data(), _sizes_remote.data(), _displs_remote.data(),
159 MPI_INT64_T, recv_buffer.data(), _sizes_local.data(),
160 _displs_local.data(), MPI_INT64_T, _comm1.comm());
163 const std::array<std::int64_t, 2> range = map.
local_range();
166 std::ranges::for_each(recv_buffer, [range](
auto idx)
167 { assert(idx >= range[0] and idx < range[1]); });
172 for (
auto& x : {std::ref(_sizes_local), std::ref(_displs_local),
173 std::ref(_sizes_remote), std::ref(_displs_remote)})
175 std::ranges::transform(x.get(), x.get().begin(),
176 [bs](
auto e) { return e *= bs; });
183 std::vector<typename container_type::value_type> idx(recv_buffer.size()
185 std::int64_t offset = range[0] * bs;
186 for (std::size_t i = 0; i < recv_buffer.size(); i++)
187 for (
int j = 0; j < bs; j++)
188 idx[i * bs + j] = (recv_buffer[i] * bs + j) - offset;
189 _local_inds = std::move(idx);
194 std::vector<typename container_type::value_type> idx(perm.size() * bs);
195 for (std::size_t i = 0; i < perm.size(); i++)
196 for (
int j = 0; j < bs; j++)
197 idx[i * bs + j] = perm[i] * bs + j;
198 _remote_inds = std::move(idx);
283 std::span<MPI_Request> requests)
const
285 if (requests.size() != _dest.size() + _src.size())
287 throw std::runtime_error(
288 "Point-to-point scatterer has wrong number of MPI_Requests.");
292 if (_sizes_local.empty() and _sizes_remote.empty())
295 for (std::size_t i = 0; i < _src.size(); ++i)
297 int ierr = MPI_Irecv(recv_buffer + _displs_remote[i], _sizes_remote[i],
299 _comm0.comm(), &requests[i]);
303 for (std::size_t i = 0; i < _dest.size(); ++i)
305 int ierr = MPI_Isend(send_buffer + _displs_local[i], _sizes_local[i],
307 &requests[i + _src.size()]);
368 std::span<MPI_Request> requests)
const
370 if (requests.size() != _dest.size() + _src.size())
372 throw std::runtime_error(
373 "Point-to-point scatterer has wrong number of MPI_Requests.");
377 if (_sizes_local.empty() and _sizes_remote.empty())
381 for (std::size_t i = 0; i < _dest.size(); i++)
383 int ierr = MPI_Irecv(recv_buffer + _displs_local[i], _sizes_local[i],
385 _comm0.comm(), &requests[i]);
391 for (std::size_t i = 0; i < _src.size(); i++)
393 int ierr = MPI_Isend(send_buffer + _displs_remote[i], _sizes_remote[i],
395 &requests[i + _dest.size()]);