102 : _sizes_remote(map.src().size(), 0),
103 _displs_remote(map.src().size() + 1), _sizes_local(map.dest().size()),
104 _displs_local(map.dest().size() + 1)
110 const std::span<const int> src = map.
src();
111 const std::span<const int> dest = map.
dest();
114 assert(std::ranges::is_sorted(src));
115 assert(std::ranges::is_sorted(dest));
121 ierr = MPI_Dist_graph_create_adjacent(
122 map.
comm(), src.size(), src.data(), MPI_UNWEIGHTED, dest.size(),
123 dest.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm0);
128 ierr = MPI_Dist_graph_create_adjacent(
129 map.
comm(), dest.size(), dest.data(), MPI_UNWEIGHTED, src.size(),
130 src.data(), MPI_UNWEIGHTED, MPI_INFO_NULL,
false, &comm1);
135 std::span owners = map.
owners();
136 std::vector<std::int32_t> perm(owners.size());
137 std::iota(perm.begin(), perm.end(), 0);
142 std::span ghosts = map.
ghosts();
143 std::vector<int> owners_sorted(owners.size());
144 std::vector<std::int64_t> ghosts_sorted(owners.size());
145 std::ranges::transform(perm, owners_sorted.begin(),
146 [&owners](
auto idx) { return owners[idx]; });
147 std::ranges::transform(perm, ghosts_sorted.begin(),
148 [&ghosts](
auto idx) { return ghosts[idx]; });
156 assert(_sizes_remote.size() == src.size());
157 assert(_displs_remote.size() == src.size() + 1);
158 auto begin = owners_sorted.begin();
159 for (std::size_t i = 0; i < src.size(); i++)
161 auto upper = std::ranges::upper_bound(begin, owners_sorted.end(), src[i]);
162 std::size_t num_ind = std::ranges::distance(begin, upper);
163 _displs_remote[i + 1] = _displs_remote[i] + num_ind;
164 _sizes_remote[i] = num_ind;
175 assert(_sizes_local.size() == dest.size());
176 assert(_displs_local.size() == dest.size() + 1);
177 _sizes_remote.reserve(1);
178 _sizes_local.reserve(1);
180 = MPI_Neighbor_alltoall(_sizes_remote.data(), 1, MPI_INT,
181 _sizes_local.data(), 1, MPI_INT, _comm1.comm());
184 std::inclusive_scan(_sizes_local.begin(), _sizes_local.end(),
185 std::next(_displs_local.begin()));
187 assert(
static_cast<int>(ghosts_sorted.size()) == _displs_remote.back());
191 std::vector<std::int64_t> recv_buffer(_displs_local.back(), 0);
192 ierr = MPI_Neighbor_alltoallv(
193 ghosts_sorted.data(), _sizes_remote.data(), _displs_remote.data(),
194 MPI_INT64_T, recv_buffer.data(), _sizes_local.data(),
195 _displs_local.data(), MPI_INT64_T, _comm1.comm());
198 const std::array<std::int64_t, 2> range = map.
local_range();
201 std::ranges::for_each(recv_buffer, [range](
auto idx)
202 { assert(idx >= range[0] and idx < range[1]); });
210 std::vector<typename container_type::value_type> idx(recv_buffer.size());
211 std::ranges::transform(recv_buffer, idx.begin(),
212 [offset = range[0]](
auto i) ->
213 typename container_type::value_type
214 { return i - offset; });
215 _local_inds = std::move(idx);
319 MPI_Datatype type, MPI_Request& request)
const
321 if (!has_neighbours())
323 request = MPI_REQUEST_NULL;
327 int ierr = MPI_Ineighbor_alltoallv(
328 send_buffer, _sizes_local.data(), _displs_local.data(), type,
329 recv_buffer, _sizes_remote.data(), _displs_remote.data(), type,
330 _comm0.comm(), &request);
436 MPI_Datatype type, MPI_Request& request)
const
438 if (!has_neighbours())
440 request = MPI_REQUEST_NULL;
444 int ierr = MPI_Ineighbor_alltoallv(
445 send_buffer, _sizes_remote.data(), _displs_remote.data(), type,
446 recv_buffer, _sizes_local.data(), _displs_local.data(), type,
447 _comm1.comm(), &request);