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);