-----------------------------------------------------------------------------
| 1239 | } |
| 1240 | //----------------------------------------------------------------------------- |
| 1241 | std::vector<std::int32_t> IndexMap::shared_indices() const |
| 1242 | { |
| 1243 | // Each process gets a chunk of consecutive indices (global indices) |
| 1244 | // Sorting the ghosts groups them by owner |
| 1245 | std::vector<std::int64_t> send_buffer(_ghosts); |
| 1246 | std::ranges::sort(send_buffer); |
| 1247 | |
| 1248 | std::vector<int32_t> owners(_owners); |
| 1249 | std::ranges::sort(owners); |
| 1250 | std::vector<int> send_sizes, send_disp{0}; |
| 1251 | |
| 1252 | // Count number of ghost per destination |
| 1253 | auto it = owners.begin(); |
| 1254 | while (it != owners.end()) |
| 1255 | { |
| 1256 | auto it1 = std::upper_bound(it, owners.end(), *it); |
| 1257 | send_sizes.push_back(std::distance(it, it1)); |
| 1258 | send_disp.push_back(send_disp.back() + send_sizes.back()); |
| 1259 | |
| 1260 | // Advance iterator |
| 1261 | it = it1; |
| 1262 | } |
| 1263 | |
| 1264 | // Create ghost -> owner comm |
| 1265 | MPI_Comm comm; |
| 1266 | int ierr = MPI_Dist_graph_create_adjacent( |
| 1267 | _comm.comm(), _dest.size(), _dest.data(), MPI_UNWEIGHTED, _src.size(), |
| 1268 | _src.data(), MPI_UNWEIGHTED, MPI_INFO_NULL, false, &comm); |
| 1269 | dolfinx::MPI::check_error(_comm.comm(), ierr); |
| 1270 | |
| 1271 | std::vector<int> recv_sizes(_dest.size(), 0); |
| 1272 | send_sizes.reserve(1); |
| 1273 | recv_sizes.reserve(1); |
| 1274 | ierr = MPI_Neighbor_alltoall(send_sizes.data(), 1, MPI_INT, recv_sizes.data(), |
| 1275 | 1, MPI_INT, comm); |
| 1276 | dolfinx::MPI::check_error(_comm.comm(), ierr); |
| 1277 | |
| 1278 | // Prepare receive displacement array |
| 1279 | std::vector<int> recv_disp(_dest.size() + 1, 0); |
| 1280 | std::partial_sum(recv_sizes.begin(), recv_sizes.end(), |
| 1281 | std::next(recv_disp.begin())); |
| 1282 | |
| 1283 | // Send ghost indices to owner, and receive owned indices |
| 1284 | std::vector<std::int64_t> recv_buffer(recv_disp.back()); |
| 1285 | ierr = MPI_Neighbor_alltoallv(send_buffer.data(), send_sizes.data(), |
| 1286 | send_disp.data(), MPI_INT64_T, |
| 1287 | recv_buffer.data(), recv_sizes.data(), |
| 1288 | recv_disp.data(), MPI_INT64_T, comm); |
| 1289 | dolfinx::MPI::check_error(_comm.comm(), ierr); |
| 1290 | |
| 1291 | ierr = MPI_Comm_free(&comm); |
| 1292 | dolfinx::MPI::check_error(_comm.comm(), ierr); |
| 1293 | |
| 1294 | std::vector<std::int32_t> shared; |
| 1295 | shared.reserve(recv_buffer.size()); |
| 1296 | std::ranges::transform(recv_buffer, std::back_inserter(shared), |
| 1297 | [range = _local_range](auto idx) -> std::int32_t |
| 1298 | { |
no test coverage detected