-----------------------------------------------------------------------------
| 231 | int SparsityPattern::block_size(int dim) const { return _bs[dim]; } |
| 232 | //----------------------------------------------------------------------------- |
| 233 | void SparsityPattern::finalize() |
| 234 | { |
| 235 | if (!_offsets.empty()) |
| 236 | throw std::runtime_error("Sparsity pattern has already been finalised."); |
| 237 | |
| 238 | common::Timer t0("SparsityPattern::finalize"); |
| 239 | |
| 240 | assert(_index_maps[0]); |
| 241 | const std::int32_t local_size0 = _index_maps[0]->size_local(); |
| 242 | const std::array local_range0 = _index_maps[0]->local_range(); |
| 243 | std::span ghosts0 = _index_maps[0]->ghosts(); |
| 244 | std::span owners0 = _index_maps[0]->owners(); |
| 245 | std::span src0 = _index_maps[0]->src(); |
| 246 | |
| 247 | assert(_index_maps[1]); |
| 248 | const std::int32_t local_size1 = _index_maps[1]->size_local(); |
| 249 | const std::array local_range1 = _index_maps[1]->local_range(); |
| 250 | |
| 251 | _col_ghosts.assign(_index_maps[1]->ghosts().begin(), |
| 252 | _index_maps[1]->ghosts().end()); |
| 253 | _col_ghost_owners.assign(_index_maps[1]->owners().begin(), |
| 254 | _index_maps[1]->owners().end()); |
| 255 | |
| 256 | // Compute size of data to send to each process |
| 257 | std::vector<int> send_sizes(src0.size(), 0); |
| 258 | for (std::size_t i = 0; i < owners0.size(); ++i) |
| 259 | { |
| 260 | auto it = std::ranges::lower_bound(src0, owners0[i]); |
| 261 | assert(it != src0.end() and *it == owners0[i]); |
| 262 | const int neighbour_rank = std::distance(src0.begin(), it); |
| 263 | send_sizes[neighbour_rank] += 3 * _row_cache[i + local_size0].size(); |
| 264 | } |
| 265 | |
| 266 | // Compute send displacements |
| 267 | std::vector<int> send_disp(send_sizes.size() + 1, 0); |
| 268 | std::partial_sum(send_sizes.begin(), send_sizes.end(), |
| 269 | std::next(send_disp.begin(), 1)); |
| 270 | |
| 271 | // For each ghost row, pack and send (global row, global col, |
| 272 | // col_owner) triplets to send to neighborhood |
| 273 | std::vector<int> insert_pos(send_disp); |
| 274 | std::vector<std::int64_t> ghost_data(send_disp.back()); |
| 275 | const int rank = dolfinx::MPI::rank(_comm.comm()); |
| 276 | for (std::size_t i = 0; i < owners0.size(); ++i) |
| 277 | { |
| 278 | auto it = std::ranges::lower_bound(src0, owners0[i]); |
| 279 | assert(it != src0.end() and *it == owners0[i]); |
| 280 | const int neighbour_rank = std::distance(src0.begin(), it); |
| 281 | |
| 282 | for (std::int32_t col_local : _row_cache[i + local_size0]) |
| 283 | { |
| 284 | // Get index in send buffer |
| 285 | const std::int32_t pos = insert_pos[neighbour_rank]; |
| 286 | |
| 287 | // Pack send data |
| 288 | ghost_data[pos] = ghosts0[i]; |
| 289 | if (col_local < local_size1) |
| 290 | { |