11 #include <dolfinx/common/MPI.h>
12 #include <dolfinx/graph/AdjacencyList.h>
18 #include <xtl/xspan.hpp>
34 std::tuple<std::int64_t, std::vector<std::int32_t>,
35 std::vector<std::vector<std::int64_t>>,
36 std::vector<std::vector<int>>>
39 std::pair<std::reference_wrapper<const common::IndexMap>,
int>>& maps);
86 IndexMap(MPI_Comm mpi_comm, std::int32_t local_size,
87 const xtl::span<const int>& dest_ranks,
88 const xtl::span<const std::int64_t>&
ghosts,
89 const xtl::span<const int>& src_ranks);
107 std::array<std::int64_t, 2>
local_range() const noexcept;
120 const std::vector<std::int64_t>&
ghosts() const noexcept;
132 const xtl::span<std::int64_t>& global) const;
139 const xtl::span<std::int32_t>& local) const;
159 const graph::AdjacencyList<std::int32_t>&
199 template <typename T>
201 MPI_Datatype& data_type, MPI_Request& request,
202 const xtl::span<T>& recv_buffer)
const
205 const std::vector<int32_t>& displs_send_fwd = _shared_indices->offsets();
208 if (_displs_recv_fwd.size() == 1 and displs_send_fwd.size() == 1)
213 MPI_Type_size(data_type, &n);
215 if (
static_cast<int>(send_buffer.size()) != n * displs_send_fwd.back())
216 throw std::runtime_error(
"Incompatible send buffer size.");
217 if (
static_cast<int>(recv_buffer.size()) != n * _displs_recv_fwd.back())
218 throw std::runtime_error(
"Incompatible receive buffer size..");
221 MPI_Ineighbor_alltoallv(send_buffer.data(), _sizes_send_fwd.data(),
222 displs_send_fwd.data(), data_type,
223 recv_buffer.data(), _sizes_recv_fwd.data(),
224 _displs_recv_fwd.data(), data_type,
225 _comm_owner_to_ghost.comm(), &request);
237 const std::vector<int32_t>& displs_send_fwd = _shared_indices->offsets();
238 if (_displs_recv_fwd.size() == 1 and displs_send_fwd.size() == 1)
242 MPI_Wait(&request, MPI_STATUS_IGNORE);
255 template <
typename T>
257 xtl::span<T> remote_data,
int n)
const
259 MPI_Datatype data_type;
261 data_type = MPI::mpi_type<T>();
264 MPI_Type_contiguous(n, dolfinx::MPI::mpi_type<T>(), &data_type);
265 MPI_Type_commit(&data_type);
268 const std::vector<std::int32_t>& indices = _shared_indices->array();
269 std::vector<T> send_buffer(n * indices.size());
270 for (std::size_t i = 0; i < indices.size(); ++i)
272 std::copy_n(std::next(local_data.cbegin(), n * indices[i]), n,
273 std::next(send_buffer.begin(), n * i));
277 std::vector<T> buffer_recv(n * _displs_recv_fwd.back());
279 xtl::span<T>(buffer_recv));
283 assert(remote_data.size() == n * _ghost_pos_recv_fwd.size());
284 for (std::size_t i = 0; i < _ghost_pos_recv_fwd.size(); ++i)
286 std::copy_n(std::next(buffer_recv.cbegin(), n * _ghost_pos_recv_fwd[i]),
287 n, std::next(remote_data.begin(), n * i));
291 MPI_Type_free(&data_type);
314 template <
typename T>
316 MPI_Datatype& data_type, MPI_Request& request,
317 const xtl::span<T>& recv_buffer)
const
320 const std::vector<int32_t>& displs_send_fwd = _shared_indices->offsets();
323 if (_displs_recv_fwd.size() == 1 and displs_send_fwd.size() == 1)
328 MPI_Type_size(data_type, &n);
330 if (
static_cast<int>(send_buffer.size()) != n * _ghosts.size())
331 throw std::runtime_error(
"Inconsistent send buffer size.");
332 if (
static_cast<int>(recv_buffer.size()) != n * displs_send_fwd.back())
333 throw std::runtime_error(
"Inconsistent receive buffer size.");
336 MPI_Ineighbor_alltoallv(send_buffer.data(), _sizes_recv_fwd.data(),
337 _displs_recv_fwd.data(), data_type,
338 recv_buffer.data(), _sizes_send_fwd.data(),
339 displs_send_fwd.data(), data_type,
340 _comm_ghost_to_owner.comm(), &request);
352 const std::vector<int32_t>& displs_send_fwd = _shared_indices->offsets();
353 if (_displs_recv_fwd.size() == 1 and displs_send_fwd.size() == 1)
357 MPI_Wait(&request, MPI_STATUS_IGNORE);
369 template <
typename T>
371 const xtl::span<const T>& remote_data,
int n,
374 MPI_Datatype data_type;
376 data_type = MPI::mpi_type<T>();
379 MPI_Type_contiguous(n, dolfinx::MPI::mpi_type<T>(), &data_type);
380 MPI_Type_commit(&data_type);
384 std::vector<T> buffer_send;
385 buffer_send.resize(n * _displs_recv_fwd.back());
386 for (std::size_t i = 0; i < _ghost_pos_recv_fwd.size(); ++i)
388 std::copy_n(std::next(remote_data.cbegin(), n * i), n,
389 std::next(buffer_send.begin(), n * _ghost_pos_recv_fwd[i]));
394 std::vector<T> buffer_recv(n * _shared_indices->array().size());
396 xtl::span<T>(buffer_recv));
400 assert(local_data.size() == n * this->size_local());
401 const std::vector<std::int32_t>& shared_indices = _shared_indices->array();
405 for (std::size_t i = 0; i < shared_indices.size(); ++i)
407 std::copy_n(std::next(buffer_recv.cbegin(), n * i), n,
408 std::next(local_data.begin(), n * shared_indices[i]));
412 for (std::size_t i = 0; i < shared_indices.size(); ++i)
414 for (
int j = 0; j < n; ++j)
415 local_data[shared_indices[i] * n + j] += buffer_recv[i * n + j];
421 MPI_Type_free(&data_type);
426 std::array<std::int64_t, 2> _local_range;
429 std::int64_t _size_global;
448 std::vector<std::int32_t> _sizes_recv_fwd, _sizes_send_fwd, _displs_recv_fwd;
452 std::vector<std::int32_t> _ghost_pos_recv_fwd;
455 std::vector<std::int64_t> _ghosts;
462 std::unique_ptr<graph::AdjacencyList<std::int32_t>> _shared_indices;