13 #include <dolfinx/graph/AdjacencyList.h>
18 #include <type_traits>
22 #define MPICH_IGNORE_CXX_SEEK 1
39 explicit Comm(MPI_Comm
comm,
bool duplicate =
true);
57 MPI_Comm
comm()
const;
65 static int rank(MPI_Comm comm);
69 static int size(MPI_Comm comm);
90 const std::set<int>& edges);
105 static std::tuple<std::vector<int>, std::vector<int>>
110 static std::size_t
global_offset(MPI_Comm comm, std::size_t range,
115 static std::array<std::int64_t, 2>
local_range(
int process, std::int64_t N,
125 template <
typename T>
131 template <
typename T>
135 throw std::runtime_error(
"MPI data type unknown");
144 inline MPI_Datatype MPI::mpi_type<float>()
149 inline MPI_Datatype MPI::mpi_type<double>()
154 inline MPI_Datatype MPI::mpi_type<std::complex<double>>()
156 return MPI_DOUBLE_COMPLEX;
159 inline MPI_Datatype MPI::mpi_type<short int>()
164 inline MPI_Datatype MPI::mpi_type<int>()
169 inline MPI_Datatype MPI::mpi_type<unsigned int>()
174 inline MPI_Datatype MPI::mpi_type<long int>()
179 inline MPI_Datatype MPI::mpi_type<unsigned long>()
181 return MPI_UNSIGNED_LONG;
184 inline MPI_Datatype MPI::mpi_type<long long>()
186 return MPI_LONG_LONG;
189 inline MPI_Datatype MPI::mpi_type<unsigned long long>()
191 return MPI_UNSIGNED_LONG_LONG;
194 inline MPI_Datatype MPI::mpi_type<bool>()
200 template <
typename T>
201 graph::AdjacencyList<T>
205 const std::vector<std::int32_t>& send_offsets = send_data.
offsets();
206 const std::vector<T>& values_in = send_data.
array();
209 assert(send_data.
num_nodes() == comm_size);
212 std::vector<int> send_size(comm_size);
213 std::adjacent_difference(std::next(send_offsets.begin(), +1),
214 send_offsets.end(), send_size.begin());
217 std::vector<int> recv_size(comm_size);
218 MPI_Alltoall(send_size.data(), 1, mpi_type<int>(), recv_size.data(), 1,
219 mpi_type<int>(), comm);
222 std::vector<std::int32_t> recv_offset(comm_size + 1);
224 std::partial_sum(recv_size.begin(), recv_size.end(),
225 std::next(recv_offset.begin()));
228 std::vector<T> recv_values(recv_offset[comm_size]);
229 MPI_Alltoallv(values_in.data(), send_size.data(), send_offsets.data(),
230 mpi_type<T>(), recv_values.data(), recv_size.data(),
231 recv_offset.data(), mpi_type<T>(), comm);
234 std::move(recv_offset));
237 template <
typename T>
243 int indegree(-1), outdegree(-2), weighted(-1);
244 MPI_Dist_graph_neighbors_count(neighbor_comm, &indegree, &outdegree,
249 std::vector<int> send_sizes(outdegree + 1, 0);
250 std::vector<int> recv_sizes(indegree + 1);
251 std::adjacent_difference(std::next(send_data.
offsets().begin()),
252 send_data.
offsets().end(), send_sizes.begin());
254 MPI_Neighbor_alltoall(send_sizes.data(), 1, MPI::mpi_type<int>(),
255 recv_sizes.data(), 1, MPI::mpi_type<int>(),
260 std::vector<int> recv_offsets(indegree + 1);
262 std::partial_sum(recv_sizes.begin(), std::prev(recv_sizes.end()),
263 std::next(recv_offsets.begin(), 1));
265 std::vector<T> recv_data(recv_offsets[recv_offsets.size() - 1]);
266 MPI_Neighbor_alltoallv(
267 send_data.
array().data(), send_sizes.data(), send_data.
offsets().data(),
268 MPI::mpi_type<T>(), recv_data.data(), recv_sizes.data(),
269 recv_offsets.data(), MPI::mpi_type<T>(), neighbor_comm);