diff --git a/miniapp/io.cpp b/miniapp/io.cpp
index c1d4f6fc0297b08e9311cdf5bef683e0de720b87..348489ac6bb03491e3573d0c9d61b369325bba76 100644
--- a/miniapp/io.cpp
+++ b/miniapp/io.cpp
@@ -110,7 +110,7 @@ static void update_option(util::optional<T>& opt, const nlohmann::json& j, const
 }
 
 // Read options from (optional) json file and command line arguments.
-cl_options read_options(int argc, char** argv) {
+cl_options read_options(int argc, char** argv, bool allow_write) {
 
     // Default options:
     const cl_options defopts{
@@ -271,7 +271,7 @@ cl_options read_options(int argc, char** argv) {
     }
 
     // Save option values if requested.
-    if (save_file != "") {
+    if (save_file != "" && allow_write) {
         std::ofstream fid(save_file);
         if (fid) {
             try {
@@ -284,6 +284,8 @@ cl_options read_options(int argc, char** argv) {
                 fopts["dt"] = options.dt;
                 fopts["tfinal"] = options.tfinal;
                 fopts["all_to_all"] = options.all_to_all;
+                fopts["ring"] = options.ring;
+                fopts["group_size"] = options.group_size;
                 fopts["probe_ratio"] = options.probe_ratio;
                 fopts["probe_soma_only"] = options.probe_soma_only;
                 fopts["trace_prefix"] = options.trace_prefix;
@@ -316,6 +318,8 @@ std::ostream& operator<<(std::ostream& o, const cl_options& options) {
     o << "  simulation time      : " << options.tfinal << "\n";
     o << "  dt                   : " << options.dt << "\n";
     o << "  all to all network   : " << (options.all_to_all ? "yes" : "no") << "\n";
+    o << "  ring network         : " << (options.ring ? "yes" : "no") << "\n";
+    o << "  group size           : " << options.group_size << "\n";
     o << "  probe ratio          : " << options.probe_ratio << "\n";
     o << "  probe soma only      : " << (options.probe_soma_only ? "yes" : "no") << "\n";
     o << "  trace prefix         : " << options.trace_prefix << "\n";
diff --git a/miniapp/io.hpp b/miniapp/io.hpp
index 1c5bba8163596dcf5bdcbed10113c901a1c816b0..ac769d436b6a36550afe2e64b33e0b35a69f3f80 100644
--- a/miniapp/io.hpp
+++ b/miniapp/io.hpp
@@ -51,7 +51,7 @@ public:
 
 std::ostream& operator<<(std::ostream& o, const cl_options& opt);
 
-cl_options read_options(int argc, char** argv);
+cl_options read_options(int argc, char** argv, bool allow_write = true);
 
 
 } // namespace io
diff --git a/miniapp/miniapp.cpp b/miniapp/miniapp.cpp
index 9ad224efd7c1597ef848559b02921911cfe19b15..2b5df5d963305f82263d4cb3676d949989d90ea2 100644
--- a/miniapp/miniapp.cpp
+++ b/miniapp/miniapp.cpp
@@ -51,7 +51,7 @@ int main(int argc, char** argv) {
         banner();
 
         // read parameters
-        io::cl_options options = io::read_options(argc, argv);
+        io::cl_options options = io::read_options(argc, argv, global_policy::id()==0);
         std::cout << options << "\n";
         std::cout << "\n";
         std::cout << ":: simulation to " << options.tfinal << " ms in "
diff --git a/src/cell_group.hpp b/src/cell_group.hpp
index d8fd2f2ad18edf9e401658cf3c2372190e0226c7..30bdd99dbd66f07fe0851a42cd052028a52b1f89 100644
--- a/src/cell_group.hpp
+++ b/src/cell_group.hpp
@@ -11,6 +11,7 @@
 #include <event_queue.hpp>
 #include <spike.hpp>
 #include <spike_source.hpp>
+#include <util/debug.hpp>
 #include <util/partition.hpp>
 #include <util/range.hpp>
 
@@ -130,7 +131,7 @@ public:
                 // time step. This should be a parameter. e.g. with for variable
                 // order time stepping, use the minimum possible time step size.
                 while(auto e = events_.pop_if_before(cell_.time()+dt/10.)) {
-                    auto handle = get_target_handle(next->target);
+                    auto handle = get_target_handle(e->target);
                     cell_.deliver_event(handle, e->weight);
                 }
             }
diff --git a/src/communication/mpi.hpp b/src/communication/mpi.hpp
index 9ebb0ca412d83dbb600471417beb299fd1a55a8b..472c64039ba8b4b74e96adf97cc6f63782a69f72 100644
--- a/src/communication/mpi.hpp
+++ b/src/communication/mpi.hpp
@@ -11,6 +11,7 @@
 
 #include <algorithms.hpp>
 #include <communication/gathered_vector.hpp>
+#include <util/debug.hpp>
 
 namespace nest {
 namespace mc {
@@ -97,7 +98,7 @@ namespace mpi {
     }
 
     template <typename T>
-    std::vector<T> gather_all(const std::vector<T> &values) {
+    std::vector<T> gather_all(const std::vector<T>& values) {
         static_assert(
             true,//std::is_trivially_copyable<T>::value,
             "gather_all can only be performed on trivally copyable types");
@@ -149,6 +150,10 @@ namespace mpi {
             MPI_COMM_WORLD
         );
 
+        for (auto& d : displs) {
+            d /= traits::count();
+        }
+
         return gathered_type(
             std::move(buffer),
             std::vector<count_type>(displs.begin(), displs.end())
diff --git a/src/fvm_multicell.hpp b/src/fvm_multicell.hpp
index f885906f1ce52902eca89403d27cde9e25559924..1c9c799a933ba67a05bde76bf0b7fc22bdf88396 100644
--- a/src/fvm_multicell.hpp
+++ b/src/fvm_multicell.hpp
@@ -19,6 +19,7 @@
 #include <segment.hpp>
 #include <stimulus.hpp>
 #include <util.hpp>
+#include <util/debug.hpp>
 #include <util/meta.hpp>
 #include <util/partition.hpp>
 #include <util/span.hpp>
diff --git a/src/util/range.hpp b/src/util/range.hpp
index 89fcaddbfc8b0b6161f97bd5f3f2cb0cc2d20545..3addca60883e5ad5dafc24e93240b6f0c189c092 100644
--- a/src/util/range.hpp
+++ b/src/util/range.hpp
@@ -332,13 +332,16 @@ range<const T*> singleton_view(const T& item) {
  */
 
 template <typename Container, typename Seq>
-void append(Container &c, const Seq& seq) {
-    c.insert(c.end(), seq.begin(), seq.end());
+Container& append(Container &c, const Seq& seq) {
+    auto canon = canonical_view(seq);
+    c.insert(c.end(), std::begin(canon), std::end(canon));
+    return c;
 }
 
 template <typename AssignableContainer, typename Seq>
 AssignableContainer& assign(AssignableContainer& c, const Seq& seq) {
-    c.assign(seq.begin(), seq.end());
+    auto canon = canonical_view(seq);
+    c.assign(std::begin(canon), std::end(canon));
     return c;
 }
 
diff --git a/tests/global_communication/CMakeLists.txt b/tests/global_communication/CMakeLists.txt
index cc1e1af8b6567a2fc887815fa4eaeb25c561841e..800e7d193dcb335d2ee8ae164ed38b947eaae313 100644
--- a/tests/global_communication/CMakeLists.txt
+++ b/tests/global_communication/CMakeLists.txt
@@ -4,6 +4,7 @@ set(HEADERS
 set(COMMUNICATION_SOURCES
     test_exporter_spike_file.cpp
     test_communicator.cpp
+    test_mpi_gather_all.cpp
 
     # unit test driver
     test.cpp
diff --git a/tests/global_communication/test_mpi_gather_all.cpp b/tests/global_communication/test_mpi_gather_all.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed99089fd517ae424201637ededfe8049168ca76
--- /dev/null
+++ b/tests/global_communication/test_mpi_gather_all.cpp
@@ -0,0 +1,100 @@
+#include "gtest.h"
+
+#ifdef WITH_MPI
+
+#include <cstring>
+#include <vector>
+
+#include <communication/mpi_global_policy.hpp>
+#include <communication/mpi.hpp>
+#include <util/range.hpp>
+
+using namespace nest::mc;
+using namespace nest::mc::communication;
+
+struct big_thing {
+    big_thing() {}
+    big_thing(int i): value_(i) {}
+
+    bool operator==(const big_thing& other) const {
+        return value_==other.value_ && !memcmp(salt_, other.salt_, sizeof(salt_));
+    }
+
+    bool operator!=(const big_thing& other) const {
+        return !(*this==other);
+    }
+
+private:
+    int value_;
+    char salt_[32] = "it's a lovely day for a picnic";
+};
+
+TEST(mpi, gather_all) {
+    using policy = mpi_global_policy;
+
+    int id = policy::id();
+
+    std::vector<big_thing> data;
+    // odd ranks: three items; even ranks: one item.
+    if (id%2) {
+        data = { id, id+7, id+8 };
+    }
+    else {
+        data = { id };
+    }
+
+    std::vector<big_thing> expected;
+    for (int i = 0; i<policy::size(); ++i) {
+        if (i%2) {
+            int rank_data[] = { i, i+7, i+8 };
+            util::append(expected, rank_data);
+        }
+        else {
+            int rank_data[] = { i };
+            util::append(expected, rank_data);
+        }
+    }
+
+    auto gathered = mpi::gather_all(data);
+
+    EXPECT_EQ(expected, gathered);
+}
+
+TEST(mpi, gather_all_with_partition) {
+    using policy = mpi_global_policy;
+
+    int id = policy::id();
+
+    std::vector<big_thing> data;
+    // odd ranks: three items; even ranks: one item.
+    if (id%2) {
+        data = { id, id+7, id+8 };
+    }
+    else {
+        data = { id };
+    }
+
+    std::vector<big_thing> expected_values;
+    std::vector<unsigned> expected_divisions;
+
+    expected_divisions.push_back(0);
+    for (int i = 0; i<policy::size(); ++i) {
+        if (i%2) {
+            int rank_data[] = { i, i+7, i+8 };
+            util::append(expected_values, rank_data);
+            expected_divisions.push_back(expected_divisions.back()+util::size(rank_data));
+        }
+        else {
+            int rank_data[] = { i };
+            util::append(expected_values, rank_data);
+            expected_divisions.push_back(expected_divisions.back()+util::size(rank_data));
+        }
+    }
+
+    auto gathered = mpi::gather_all_with_partition(data);
+
+    EXPECT_EQ(expected_values, gathered.values());
+    EXPECT_EQ(expected_divisions, gathered.partition());
+}
+
+#endif // WITH_MPI