From 8411edf44f43d5549ab66e180f359860ae4cd031 Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <github@naumov.de>
Date: Fri, 1 Nov 2024 11:15:44 +0100
Subject: [PATCH] [BL/MPI] allgatherv for variable size data exchg

---
 BaseLib/MPI.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/BaseLib/MPI.h b/BaseLib/MPI.h
index 891b81f98b3..3d60e44a61b 100644
--- a/BaseLib/MPI.h
+++ b/BaseLib/MPI.h
@@ -11,6 +11,7 @@
 
 #include <algorithm>
 
+#include "Algorithm.h"
 #include "Error.h"
 
 #ifdef USE_PETSC
@@ -136,6 +137,33 @@ static void allreduceInplace(std::vector<T>& vector,
                   mpi_op,
                   mpi.communicator);
 }
+
+/// Allgather for variable data. Returns offsets in the receive buffer.
+/// The receive buffer is resized to accommodate the gathered data.
+template <typename T>
+static std::vector<int> allgatherv(
+    std::span<T> const send_buffer,
+    std::vector<std::remove_const_t<T>>& receive_buffer,
+    Mpi const& mpi)
+{
+    // Determine the number of elements to send
+    int const size = static_cast<int>(send_buffer.size());
+
+    // Gather sizes from all ranks
+    std::vector<int> const sizes = allgather(size, mpi);
+
+    // Compute offsets based on counts
+    std::vector<int> const offsets = BaseLib::sizesToOffsets(sizes);
+
+    // Resize receive buffer to hold all gathered data
+    receive_buffer.resize(offsets.back());
+
+    MPI_Allgatherv(send_buffer.data(), size, mpiType<T>(),
+                   receive_buffer.data(), sizes.data(), offsets.data(),
+                   mpiType<T>(), mpi.communicator);
+
+    return offsets;
+}
 #endif
 
 /// The reduction is implemented transparently for with and without MPI. In the
-- 
GitLab