From f70b07870f788ac5c2e8d8f48b6daf590e1e49d6 Mon Sep 17 00:00:00 2001
From: James Willis <james.s.willis@durham.ac.uk>
Date: Wed, 18 Jul 2018 15:10:20 +0100
Subject: [PATCH] Store fof data in a SoA. Renamed group_id -> group_index.

---
 src/fof.c   | 186 ++++++++++++++++++++++++++++------------------------
 src/space.c |   3 +-
 src/space.h |  12 +++-
 3 files changed, 113 insertions(+), 88 deletions(-)

diff --git a/src/fof.c b/src/fof.c
index 947e0cf13d..166eb33b8f 100644
--- a/src/fof.c
+++ b/src/fof.c
@@ -57,23 +57,23 @@ void fof_init(struct space *s, long long Ngas, long long Ngparts) {
 
 /* Finds the root ID of the group a particle exists in. */
 __attribute__((always_inline)) INLINE static int fof_find(const int i,
-                                                          int *group_id) {
+                                                          int *group_index) {
 
   int root = node_offset + i;
   if (root < node_offset) return root;
   /* TODO: May need this atomic here:
-   * while (root != atomic_cas(&group_id[root], group_id[root], group_id[root])) 
-   *   root = atomic_cas(&group_id[root], group_id[root], group_id[root]); */
-  while (root != group_id[root - node_offset]) {
-    root = group_id[root - node_offset];
+   * while (root != atomic_cas(&group_index[root], group_index[root], group_index[root])) 
+   *   root = atomic_cas(&group_index[root], group_index[root], group_index[root]); */
+  while (root != group_index[root - node_offset]) {
+    root = group_index[root - node_offset];
     if (root < node_offset) break;
   }
 
   /* Perform path compression. */
   // int index = i;
   // while(index != root) {
-  //  int next = group_id[index];
-  //  group_id[index] = root;
+  //  int next = group_index[index];
+  //  group_index[index] = root;
   //  index = next;
   //}
 
@@ -83,21 +83,21 @@ __attribute__((always_inline)) INLINE static int fof_find(const int i,
 #ifdef WITH_MPI
 /* Finds the root ID of the group a particle exists in. */
 __attribute__((always_inline)) INLINE static int fof_find_global(const int i,
-                                                          int *group_id) {
+                                                          int *group_index) {
 
   int root = i;
   /* TODO: May need this atomic here:
-   * while (root != atomic_cas(&group_id[root], group_id[root], group_id[root])) 
-   *   root = atomic_cas(&group_id[root], group_id[root], group_id[root]); */
-  while (root != group_id[root]) {
-    root = group_id[root];
+   * while (root != atomic_cas(&group_index[root], group_index[root], group_index[root])) 
+   *   root = atomic_cas(&group_index[root], group_index[root], group_index[root]); */
+  while (root != group_index[root]) {
+    root = group_index[root];
   }
 
   /* Perform path compression. */
   // int index = i;
   // while(index != root) {
-  //  int next = group_id[index];
-  //  group_id[index] = root;
+  //  int next = group_index[index];
+  //  group_index[index] = root;
   //  index = next;
   //}
 
@@ -274,7 +274,7 @@ void fof_search_serial(struct space *s) {
   struct gpart *gparts = s->gparts;
   const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const double l_x2 = s->l_x2;
-  int *group_id = s->group_id;
+  int *group_index = s->fof_data.group_index;
   int *group_size;
   int num_groups = 0;
 
@@ -296,12 +296,12 @@ void fof_search_serial(struct space *s) {
     const double piz = pi->x[2];
 
     /* Find the root of pi. */
-    int root_i = fof_find(i, group_id);
+    int root_i = fof_find(i, group_index);
     
     for (size_t j = i + 1; j < nr_gparts; j++) {
 
       /* Find the roots of pi and pj. */
-      const int root_j = fof_find(j, group_id);
+      const int root_j = fof_find(j, group_index);
 
       /* Skip particles in the same group. */
       if (root_i == root_j) continue;
@@ -329,12 +329,12 @@ void fof_search_serial(struct space *s) {
         /* If the root ID of pj is lower than pi's root ID set pi's root to point to pj's. 
          * Otherwise set pj's to root to point to pi's.*/
         if (root_j < root_i) {
-          group_id[root_i] = root_j;
+          group_index[root_i] = root_j;
           /* Update root_i on the fly. */
           root_i = root_j;
         }
         else
-          group_id[root_j] = root_i;
+          group_index[root_j] = root_i;
 
       }
     }
@@ -342,20 +342,20 @@ void fof_search_serial(struct space *s) {
 
   /* Calculate the total number of particles in each group and total number of groups. */
   for (size_t i = 0; i < nr_gparts; i++) {
-    group_size[fof_find(i, group_id)]++;
-    if(group_id[i] == i) num_groups++;
+    group_size[fof_find(i, group_index)]++;
+    if(group_index[i] == i) num_groups++;
   }
 
-  fof_dump_group_data("fof_output_serial.dat", nr_gparts, group_id, group_size);
+  fof_dump_group_data("fof_output_serial.dat", nr_gparts, group_index, group_size);
 
   int num_parts_in_groups = 0;
-  int max_group_size = 0, max_group_id = 0;
+  int max_group_size = 0, max_group_index = 0;
   for (size_t i = 0; i < nr_gparts; i++) {
 
     if (group_size[i] > 1) num_parts_in_groups += group_size[i];
     if (group_size[i] > max_group_size) {
       max_group_size = group_size[i];
-      max_group_id = i;
+      max_group_index = i;
     }
   }
 
@@ -363,7 +363,7 @@ void fof_search_serial(struct space *s) {
       "No. of groups: %d. No. of particles in groups: %d. No. of particles not "
       "in groups: %zu.",
       num_groups, num_parts_in_groups, nr_gparts - num_parts_in_groups);
-  message("Biggest group size: %d with ID: %d", max_group_size, max_group_id);
+  message("Biggest group size: %d with ID: %d", max_group_size, max_group_index);
 
   free(group_size);
 }
@@ -374,10 +374,10 @@ void fof_search_cell(struct space *s, struct cell *c) {
   const size_t count = c->gcount;
   struct gpart *gparts = c->gparts;
   const double l_x2 = s->l_x2;
-  int *group_id = s->group_id;
+  int *group_index = s->fof_data.group_index;
 
   /* Make a list of particle offsets into the global gparts array. */
-  int *const offset = group_id + (ptrdiff_t)(gparts - s->gparts);
+  int *const offset = group_index + (ptrdiff_t)(gparts - s->gparts);
 
   /* Loop over particles and find which particles belong in the same group. */
   for (size_t i = 0; i < count; i++) {
@@ -388,12 +388,12 @@ void fof_search_cell(struct space *s, struct cell *c) {
     const double piz = pi->x[2];
 
     /* Find the root of pi. */
-    int root_i = fof_find(offset[i] - node_offset, group_id);
+    int root_i = fof_find(offset[i] - node_offset, group_index);
 
     for (size_t j = i + 1; j < count; j++) {
 
       /* Find the root of pj. */
-      const int root_j = fof_find(offset[j] - node_offset, group_id);
+      const int root_j = fof_find(offset[j] - node_offset, group_index);
 
       /* Skip particles in the same group. */
       if (root_i == root_j) continue;
@@ -417,12 +417,12 @@ void fof_search_cell(struct space *s, struct cell *c) {
         /* If the root ID of pj is lower than pi's root ID set pi's root to point to pj's. 
          * Otherwise set pj's to root to point to pi's.*/
         if (root_j < root_i) {
-          atomic_min(&group_id[root_i - node_offset], root_j);
+          atomic_min(&group_index[root_i - node_offset], root_j);
           /* Update root_i on the fly. */
           root_i = root_j;
         }
         else
-          atomic_min(&group_id[root_j - node_offset], root_i);
+          atomic_min(&group_index[root_j - node_offset], root_i);
 
       }
     }
@@ -438,11 +438,11 @@ void fof_search_pair_cells(struct space *s, struct cell *ci, struct cell *cj) {
   struct gpart *gparts_j = cj->gparts;
   const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const double l_x2 = s->l_x2;
-  int *group_id = s->group_id;
+  int *group_index = s->fof_data.group_index;
   
   /* Make a list of particle offsets into the global gparts array. */
-  int *const offset_i = group_id + (ptrdiff_t)(gparts_i - s->gparts);
-  int *const offset_j = group_id + (ptrdiff_t)(gparts_j - s->gparts);
+  int *const offset_i = group_index + (ptrdiff_t)(gparts_i - s->gparts);
+  int *const offset_j = group_index + (ptrdiff_t)(gparts_j - s->gparts);
 
   /* Account for boundary conditions.*/
   double shift[3] = {0.0, 0.0, 0.0};
@@ -470,12 +470,12 @@ void fof_search_pair_cells(struct space *s, struct cell *ci, struct cell *cj) {
     const double piz = pi->x[2] - shift[2];
 
     /* Find the root of pi. */
-    int root_i = fof_find(offset_i[i] - node_offset, group_id);
+    int root_i = fof_find(offset_i[i] - node_offset, group_index);
     
     for (size_t j = 0; j < count_j; j++) {
 
       /* Find the root of pj. */
-      const int root_j = fof_find(offset_j[j] - node_offset, group_id);
+      const int root_j = fof_find(offset_j[j] - node_offset, group_index);
 
       /* Skip particles in the same group. */
       if (root_i == root_j) continue;
@@ -500,12 +500,12 @@ void fof_search_pair_cells(struct space *s, struct cell *ci, struct cell *cj) {
         /* If the root ID of pj is lower than pi's root ID set pi's root to point to pj's. 
          * Otherwise set pj's to root to point to pi's.*/
         if (root_j < root_i) {
-          atomic_min(&group_id[root_i - node_offset], root_j);
+          atomic_min(&group_index[root_i - node_offset], root_j);
           /* Update root_i on the fly. */
           root_i = root_j;
         }
         else
-          atomic_min(&group_id[root_j - node_offset], root_i);
+          atomic_min(&group_index[root_j - node_offset], root_i);
 
       }
     }
@@ -522,11 +522,11 @@ void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell
   struct gpart *gparts_j = cj->gparts;
   const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const double l_x2 = s->l_x2;
-  int *group_id = s->group_id;
+  int *group_index = s->fof_data.group_index;
   
   /* Make a list of particle offsets into the global gparts array. */
-  int *const offset_i = group_id + (ptrdiff_t)(gparts_i - s->gparts);
-  int *const offset_j = group_id + (ptrdiff_t)(gparts_j - s->gparts);
+  int *const offset_i = group_index + (ptrdiff_t)(gparts_i - s->gparts);
+  int *const offset_j = group_index + (ptrdiff_t)(gparts_j - s->gparts);
 
   /* Account for boundary conditions.*/
   double shift[3] = {0.0, 0.0, 0.0};
@@ -565,7 +565,7 @@ void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell
       const double piz = pi->x[2] - shift[2];
 
       /* Find the root of pi. */
-      int root_i = fof_find(offset_i[i] - node_offset, group_id);
+      int root_i = fof_find(offset_i[i] - node_offset, group_index);
 
       for (size_t j = 0; j < count_j; j++) {
 
@@ -622,7 +622,7 @@ void fof_search_pair_cells_foreign(struct space *s, struct cell *ci, struct cell
       const double pjz = pj->x[2] - shift[2];
 
       /* Find the root of pj. */
-      int root_j = fof_find(offset_j[j] - node_offset, group_id);
+      int root_j = fof_find(offset_j[j] - node_offset, group_index);
 
       for (size_t i = 0; i < count_i; i++) {
 
@@ -674,7 +674,7 @@ void fof_search_tree_serial(struct space *s) {
   const size_t nr_gparts = s->nr_gparts;
   const size_t nr_cells = s->nr_cells;
   struct gpart *gparts = s->gparts;
-  int *group_id;
+  int *group_index;
   int *group_size;
   float *group_mass;
   int num_groups = 0;
@@ -686,17 +686,17 @@ void fof_search_tree_serial(struct space *s) {
           s->l_x2);
 
   /* Allocate and initialise array of particle group IDs. */
-  if(s->group_id != NULL) free(s->group_id);
+  if(s->fof_data.group_index != NULL) free(s->fof_data.group_index);
 
-  if (posix_memalign((void **)&s->group_id, 32, nr_gparts * sizeof(int)) != 0)
+  if (posix_memalign((void **)&s->fof_data.group_index, 32, nr_gparts * sizeof(int)) != 0)
     error("Failed to allocate list of particle group IDs for FOF search.");
 
   /* Initial group ID is particle offset into array. */
-  for (size_t i = 0; i < nr_gparts; i++) s->group_id[i] = i;
+  for (size_t i = 0; i < nr_gparts; i++) s->fof_data.group_index[i] = i;
 
-  group_id = s->group_id;
+  group_index = s->fof_data.group_index;
   
-  message("Rank: %d, Allocated group_id array of size %zu", engine_rank, s->nr_gparts);
+  message("Rank: %d, Allocated group_index array of size %zu", engine_rank, s->nr_gparts);
 
   /* Allocate and initialise a group size array. */
   if (posix_memalign((void **)&group_size, 32, nr_gparts * sizeof(int)) != 0)
@@ -743,17 +743,17 @@ void fof_search_tree_serial(struct space *s) {
 
   /* Calculate the total number of particles in each group, group mass and the total number of groups. */
   for (size_t i = 0; i < nr_gparts; i++) {
-    const int root = fof_find(i, group_id);
+    const int root = fof_find(i, group_index);
     group_size[root]++;
     group_mass[root] += gparts[i].mass;
-    if(group_id[i] == i) num_groups++;
+    if(group_index[i] == i) num_groups++;
   }
 
-  fof_dump_group_data("fof_output_tree_serial.dat", nr_gparts, group_id,
+  fof_dump_group_data("fof_output_tree_serial.dat", nr_gparts, group_index,
                       group_size);
 
   int num_parts_in_groups = 0;
-  int max_group_size = 0, max_group_id = 0, max_group_mass_id = 0;
+  int max_group_size = 0, max_group_index = 0, max_group_mass_id = 0;
   float max_group_mass = 0;
   for (size_t i = 0; i < nr_gparts; i++) {
 
@@ -763,7 +763,7 @@ void fof_search_tree_serial(struct space *s) {
     /* Find the largest group. */
     if (group_size[i] > max_group_size) {
       max_group_size = group_size[i];
-      max_group_id = i;
+      max_group_index = i;
     }
     
     /* Find the largest group by mass. */
@@ -777,7 +777,7 @@ void fof_search_tree_serial(struct space *s) {
       "No. of groups: %d. No. of particles in groups: %d. No. of particles not "
       "in groups: %zu.",
       num_groups, num_parts_in_groups, nr_gparts - num_parts_in_groups);
-  message("Biggest group size: %d with ID: %d", max_group_size, max_group_id);
+  message("Biggest group size: %d with ID: %d", max_group_size, max_group_index);
   message("Biggest group by mass: %f with ID: %d", max_group_mass, max_group_mass_id);
 
   free(group_size);
@@ -1025,7 +1025,7 @@ void fof_search_foreign_cells(struct space *s) {
         struct gpart *gparts = c->gparts;
 
         /* Make a list of particle offsets into the global gparts array. */
-        int *const offset = s->group_id + (ptrdiff_t)(gparts - s->gparts);
+        int *const offset = s->fof_data.group_index + (ptrdiff_t)(gparts - s->gparts);
 
         for(int k=0; k<c->gcount; k++) {
 
@@ -1036,13 +1036,13 @@ void fof_search_foreign_cells(struct space *s) {
             found_count++;
             found = 1;
 
-            int local_root = fof_find(offset[k] - node_offset, s->group_id);
+            int local_root = fof_find(offset[k] - node_offset, s->fof_data.group_index);
 
             if(local_root == fof_recv[i].root_i) continue;
 
             if(fof_recv[i].root_i < local_root) {
 
-              s->group_id[local_root - node_offset] = fof_recv[i].root_i;
+              s->fof_data.group_index[local_root - node_offset] = fof_recv[i].root_i;
 
               //message("Rank: %d Particle %lld found new group with root: %d, previous group: %d, i=%d, j=%d, k=%d", engine_rank, gp->id_or_neg_offset, fof_recv[i].root_i, local_root, i,j,k);
               
@@ -1077,7 +1077,8 @@ void fof_search_tree(struct space *s) {
   const size_t nr_gparts = s->nr_gparts;
   const size_t nr_cells = s->nr_cells;
   struct gpart *gparts = s->gparts;
-  int *group_id;
+  //long long *group_id;
+  int *group_index;
   int *group_size;
   float *group_mass;
   int num_groups = 0;
@@ -1115,17 +1116,17 @@ void fof_search_tree(struct space *s) {
   message("Node offset: %d", node_offset);
 
   /* Allocate and initialise array of particle group IDs. */
-  if(s->group_id != NULL) free(s->group_id);
+  if(s->fof_data.group_index != NULL) free(s->fof_data.group_index);
 
-  if (posix_memalign((void **)&s->group_id, 32, nr_gparts * sizeof(int)) != 0)
+  if (posix_memalign((void **)&s->fof_data.group_index, 32, nr_gparts * sizeof(int)) != 0)
     error("Failed to allocate list of particle group IDs for FOF search.");
 
   /* Initial group ID is particle offset into array. */
-  for (size_t i = 0; i < nr_gparts; i++) s->group_id[i] = node_offset + i;
+  for (size_t i = 0; i < nr_gparts; i++) s->fof_data.group_index[i] = node_offset + i;
 
-  group_id = s->group_id;
+  group_index = s->fof_data.group_index;
   
-  message("Rank: %d, Allocated group_id array of size %zu", engine_rank, s->nr_gparts);
+  message("Rank: %d, Allocated group_index array of size %zu", engine_rank, s->nr_gparts);
 
   /* Allocate and initialise a group size array. */
   if (posix_memalign((void **)&group_size, 32, nr_gparts * sizeof(int)) != 0)
@@ -1151,56 +1152,56 @@ void fof_search_tree(struct space *s) {
 
   /* Calculate the total number of particles in each group, group mass and the total number of groups. */
   for (size_t i = 0; i < nr_gparts; i++) {
-    const int root = fof_find(i, group_id);
+    const int root = fof_find(i, group_index);
     group_size[root - node_offset]++;
     group_mass[root - node_offset] += gparts[i].mass;
-    if(group_id[i] == i + node_offset) num_groups++;
+    if(group_index[i] == i + node_offset) num_groups++;
   }
 
-  fof_dump_group_data("fof_search_tree_local.dat", nr_gparts, group_id,
+  fof_dump_group_data("fof_search_tree_local.dat", nr_gparts, group_index,
       group_size);
 
 #ifdef WITH_MPI
-  int *global_group_id, *global_group_size;
+  int *global_group_index, *global_group_size;
   int total_num_groups = 0;
   
   if (s->e->nr_nodes > 1) {
 
     MPI_Reduce(&num_groups, &total_num_groups, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
 
-    if (posix_memalign((void **)&global_group_id, 32, s->e->total_nr_gparts * sizeof(int)) != 0)
+    if (posix_memalign((void **)&global_group_index, 32, s->e->total_nr_gparts * sizeof(int)) != 0)
       error("Failed to allocate list of global group IDs for FOF search.");
     
     if (posix_memalign((void **)&global_group_size, 32, s->e->total_nr_gparts * sizeof(int)) != 0)
       error("Failed to allocate list of global group sizes for FOF search.");
 
-    bzero(global_group_id, s->e->total_nr_gparts * sizeof(int));
+    bzero(global_group_index, s->e->total_nr_gparts * sizeof(int));
     bzero(global_group_size, s->e->total_nr_gparts * sizeof(int));
 
     int displ[2] = {0, nr_gparts};
 
-    MPI_Gatherv(group_id, nr_gparts, MPI_INT, global_group_id, global_nr_gparts, displ, MPI_INT, 0, MPI_COMM_WORLD);
+    MPI_Gatherv(group_index, nr_gparts, MPI_INT, global_group_index, global_nr_gparts, displ, MPI_INT, 0, MPI_COMM_WORLD);
 
     total_num_groups = 0;
 
     for (size_t i = 0; i < s->e->total_nr_gparts; i++) {
-      const int root = fof_find_global(i, global_group_id);
-      //const int root = fof_find(i, global_group_id);
+      const int root = fof_find_global(i, global_group_index);
+      //const int root = fof_find(i, global_group_index);
       global_group_size[root]++;
-      if(global_group_id[i] == i) total_num_groups++;
+      if(global_group_index[i] == i) total_num_groups++;
     }
 
     if(engine_rank == 0) {
-      fof_file = fopen("global_group_id.dat", "w");
+      fof_file = fopen("global_group_index.dat", "w");
       fprintf(fof_file, "# %7s %7s\n", "Index", "Group ID");
       fprintf(fof_file, "#-------------------------------\n");
 
       for (size_t i = 0; i < s->e->total_nr_gparts; i++) {
 
-        fprintf(fof_file, "  %7zu %7d \n", i, global_group_id[i]);
+        fprintf(fof_file, "  %7zu %7d \n", i, global_group_index[i]);
       }
   
-      fof_dump_group_data(output_file_name, s->e->total_nr_gparts, global_group_id,
+      fof_dump_group_data(output_file_name, s->e->total_nr_gparts, global_group_index,
           global_group_size);
     }
 
@@ -1208,7 +1209,7 @@ void fof_search_tree(struct space *s) {
 #endif /* WITH_MPI */
 
   int num_parts_in_groups = 0;
-  int max_group_size = 0, max_group_id = 0, max_group_mass_id = 0;
+  int max_group_size = 0, max_group_index = 0, max_group_mass_id = 0;
   float max_group_mass = 0;
   for (size_t i = 0; i < nr_gparts; i++) {
 
@@ -1218,7 +1219,7 @@ void fof_search_tree(struct space *s) {
     /* Find the largest group. */
     if (group_size[i] > max_group_size) {
       max_group_size = group_size[i];
-      max_group_id = i;
+      max_group_index = i;
     }
     
     /* Find the largest group by mass. */
@@ -1233,7 +1234,7 @@ void fof_search_tree(struct space *s) {
       "in groups: %zu.",
       num_groups, num_parts_in_groups, nr_gparts - num_parts_in_groups);
 
-  message("Biggest group size: %d with ID: %d", max_group_size, max_group_id);
+  message("Biggest group size: %d with ID: %d", max_group_size, max_group_index);
   message("Biggest group by mass: %f with ID: %d", max_group_mass, max_group_mass_id);
 
   free(group_size);
@@ -1243,7 +1244,7 @@ void fof_search_tree(struct space *s) {
   if (s->e->nr_nodes > 1) {
     if(engine_rank == 0) message("Total number of groups: %d", total_num_groups);
     free(global_nr_gparts);
-    free(global_group_id);
+    free(global_group_index);
   }
 #endif /* WITH_MPI */
 
@@ -1251,18 +1252,33 @@ void fof_search_tree(struct space *s) {
       clocks_from_ticks(getticks() - tic), clocks_getunit());
 }
 
-/* Dump FOF group data. */
-void fof_dump_group_data(char *out_file, const size_t nr_gparts, int *group_id,
+void fof_dump_group_data(char *out_file, const size_t nr_gparts, int *group_index,
                          int *group_size) {
 
   FILE *file = fopen(out_file, "w");
   fprintf(file, "# %7s %7s %7s\n", "ID", "Root ID", "Group Size");
-  fprintf(file, "#-------------------------------\n");
+  fprintf(file, "#---------------------------------------\n");
 
   for (size_t i = 0; i < nr_gparts; i++) {
-    const int root = fof_find(i, group_id);
+    const int root = fof_find(i, group_index);
     fprintf(file, "  %7zu %7d %7d\n", i, root, group_size[i]);
   }
 
   fclose(file);
 }
+
+/* Dump FOF group data. */
+//void fof_dump_group_data(char *out_file, const size_t nr_gparts, int *group_index,
+//                         int *group_size, struct gpart *gparts) {
+//
+//  FILE *file = fopen(out_file, "w");
+//  fprintf(file, "# %7s %7s %7s %7s\n", "ID", "Root ID", "Group Size", "Group ID");
+//  fprintf(file, "#---------------------------------------\n");
+//
+//  for (size_t i = 0; i < nr_gparts; i++) {
+//    const int root = fof_find(i, group_index);
+//    fprintf(file, "  %7zu %7d %7d    %10lld\n", i, root, group_size[i], gparts[root].id_or_neg_offset);
+//  }
+//
+//  fclose(file);
+//}
diff --git a/src/space.c b/src/space.c
index 90f4722ce9..3f25954cb7 100644
--- a/src/space.c
+++ b/src/space.c
@@ -3213,7 +3213,8 @@ void space_clean(struct space *s) {
   free(s->xparts);
   free(s->gparts);
   free(s->sparts);
-  free(s->group_id);
+  free(s->fof_data.group_id);
+  free(s->fof_data.group_index);
 }
 
 /**
diff --git a/src/space.h b/src/space.h
index c6b695a060..16fc15b32e 100644
--- a/src/space.h
+++ b/src/space.h
@@ -35,11 +35,19 @@
 #include "lock.h"
 #include "parser.h"
 #include "part.h"
+//#include "fof.h"
 
 /* Avoid cyclic inclusions */
 struct cell;
 struct cosmology;
 
+struct fof {
+
+  long long *group_id;
+  int *group_index;
+
+} SWIFT_STRUCT_ALIGN;
+
 /* Some constants. */
 #define space_cellallocchunk 1000
 #define space_splitsize_default 400
@@ -177,8 +185,8 @@ struct space {
   double l_x2;
   
   /*! The FOF group data. */
-  int *group_id;
-  
+  struct fof fof_data;
+
   /*! List of cell indices. */
   int *cell_index;
 
-- 
GitLab