diff --git a/src/Makefile.am b/src/Makefile.am
index 1b9d3b4ae9770b9081ba384851fe6cbf1f2ad688..d273dde02dd186de3697fbc42deb5b49c951941f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
 nobase_noinst_HEADERS = align.h approx_math.h atomic.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \
 		 kernel_long_gravity.h vector.h runner_doiact.h runner_doiact_grav.h runner_doiact_fft.h \
                  units.h intrinsics.h minmax.h kick.h timestep.h drift.h adiabatic_index.h io_properties.h \
-		 dimension.h equation_of_state.h active.h \
+		 dimension.h equation_of_state.h active.h part_type.h \
 		 gravity.h gravity_io.h \
 		 gravity/Default/gravity.h gravity/Default/gravity_iact.h gravity/Default/gravity_io.h \
 		 gravity/Default/gravity_debug.h gravity/Default/gravity_part.h  \
diff --git a/src/cell.c b/src/cell.c
index d4e8f9ff91490cd3a9dd9f78a3e72b19c55bf1cc..2f717850ac423d04ae2d39461c49aa864833d670 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -629,7 +629,8 @@ void cell_split(struct cell *c, ptrdiff_t parts_offset, struct cell_buff *buff,
   }
 
   /* Re-link the gparts. */
-  if (count > 0 && gcount > 0) part_relink_gparts(parts, count, parts_offset);
+  if (count > 0 && gcount > 0)
+    part_relink_gparts_to_parts(parts, count, parts_offset);
 
 #ifdef SWIFT_DEBUG_CHECKS
   /* Check that the buffs are OK. */
@@ -744,7 +745,7 @@ void cell_split(struct cell *c, ptrdiff_t parts_offset, struct cell_buff *buff,
 
   /* Re-link the parts. */
   if (count > 0 && gcount > 0)
-    part_relink_parts(gparts, gcount, parts - parts_offset);
+    part_relink_parts_to_gparts(gparts, gcount, parts - parts_offset);
 }
 
 /**
diff --git a/src/cell.h b/src/cell.h
index bda0c218975c4b7f534fc50338bfdd2997afc6be..a318cdde2ed95f472c47466dafceff561896588b 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -118,7 +118,7 @@ struct cell {
   struct gpart *gparts;
 
   /*! Pointer to the #spart data. */
-  struct gpart *sparts;
+  struct spart *sparts;
 
   /*! Pointer for the sorted indices. */
   struct entry *sort;
diff --git a/src/common_io.c b/src/common_io.c
index a9981e3024d76c445a8d69b03512a67072296c05..b74d056e98c6bf02bdac80fca1cdab3e9355bde5 100644
--- a/src/common_io.c
+++ b/src/common_io.c
@@ -390,6 +390,8 @@ void writeCodeDescription(hid_t h_file) {
   H5Gclose(h_grpcode);
 }
 
+#endif /* HAVE_HDF5 */
+
 /* ------------------------------------------------------------------------------------------------
  * This part writes the XMF file descriptor enabling a visualisation through
  * ParaView
@@ -586,6 +588,9 @@ void prepare_dm_gparts(struct gpart* const gparts, size_t Ndm) {
     if (gparts[i].id_or_neg_offset <= 0)
       error("0 or negative ID for DM particle %zu: ID=%lld", i,
             gparts[i].id_or_neg_offset);
+
+    /* Set gpart type */
+    gparts[i + Ndm].type = swift_type_dark_matter;
   }
 }
 
@@ -618,6 +623,9 @@ void duplicate_hydro_gparts(struct part* const parts,
 
     gparts[i + Ndm].mass = hydro_get_mass(&parts[i]);
 
+    /* Set gpart type */
+    gparts[i + Ndm].type = swift_type_gas;
+
     /* Link the particles */
     gparts[i + Ndm].id_or_neg_offset = -i;
     parts[i].gpart = &gparts[i + Ndm];
@@ -653,6 +661,9 @@ void duplicate_star_gparts(struct spart* const sparts,
 
     gparts[i + Ndm].mass = sparts[i].mass;
 
+    /* Set gpart type */
+    gparts[i + Ndm].type = swift_type_star;
+
     /* Link the particles */
     gparts[i + Ndm].id_or_neg_offset = -i;
     sparts[i].gpart = &gparts[i + Ndm];
@@ -690,5 +701,3 @@ void collect_dm_gparts(const struct gpart* const gparts, size_t Ntot,
     error("Collected the wrong number of dm particles (%zu vs. %zu expected)",
           count, Ndm);
 }
-
-#endif
diff --git a/src/engine.c b/src/engine.c
index 37b6c45598a0f56ccf4ec10fe7717ea357e90cfd..e98ee5090d691fee8a7daadcb1b2247a2b1281d3 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -2840,7 +2840,7 @@ void engine_split(struct engine *e, struct partition *initial_partition) {
 
   /* Re-link the gparts. */
   if (s->nr_parts > 0 && s->nr_gparts > 0)
-    part_relink_gparts(s->parts, s->nr_parts, 0);
+    part_relink_gparts_to_parts(s->parts, s->nr_parts, 0);
 
   /* Re-allocate the local gparts. */
   if (e->verbose)
@@ -2857,7 +2857,7 @@ void engine_split(struct engine *e, struct partition *initial_partition) {
 
   /* Re-link the parts. */
   if (s->nr_parts > 0 && s->nr_gparts > 0)
-    part_relink_parts(s->gparts, s->nr_gparts, s->parts);
+    part_relink_parts_to_gparts(s->gparts, s->nr_gparts, s->parts);
 
 #ifdef SWIFT_DEBUG_CHECKS
 
diff --git a/src/gravity/Default/gravity_part.h b/src/gravity/Default/gravity_part.h
index f06e65e5b30ebcd609c0c6204de33da17b770add..b3953d0e54118ff9fed99cffbc3574eeb122e989 100644
--- a/src/gravity/Default/gravity_part.h
+++ b/src/gravity/Default/gravity_part.h
@@ -25,6 +25,10 @@
 /* Gravity particle. */
 struct gpart {
 
+  /* Particle ID. If negative, it is the negative offset of the #part with
+     which this gpart is linked. */
+  long long id_or_neg_offset;
+
   /* Particle position. */
   double x[3];
 
@@ -49,9 +53,8 @@ struct gpart {
   /* Particle time of end of time-step. */
   int ti_end;
 
-  /* Particle ID. If negative, it is the negative offset of the #part with
-     which this gpart is linked. */
-  long long id_or_neg_offset;
+  /* Type of the #gpart (DM, gas, star, ...) */
+  enum part_type type;
 
 } SWIFT_STRUCT_ALIGN;
 
diff --git a/src/part.c b/src/part.c
index b00eaccaae0e86f7c4e8019a307f0bf455687b7c..3e0377d3de29868b0c828f0c9ccefdcfbb5b42f5 100644
--- a/src/part.c
+++ b/src/part.c
@@ -36,7 +36,8 @@
  * @param N The number of particles to re-link;
  * @param offset The offset of #part%s relative to the global parts list.
  */
-void part_relink_gparts(struct part *parts, size_t N, ptrdiff_t offset) {
+void part_relink_gparts_to_parts(struct part *parts, size_t N,
+                                 ptrdiff_t offset) {
   for (size_t k = 0; k < N; k++) {
     if (parts[k].gpart) {
       parts[k].gpart->id_or_neg_offset = -(k + offset);
@@ -45,20 +46,53 @@ void part_relink_gparts(struct part *parts, size_t N, ptrdiff_t offset) {
 }
 
 /**
- * @brief Re-link the #gpart%s associated with the list of #part%s.
+ * @brief Re-link the #gpart%s associated with the list of #spart%s.
+ *
+ * @param sparts The list of #spart.
+ * @param N The number of s-particles to re-link;
+ * @param offset The offset of #spart%s relative to the global sparts list.
+ */
+void part_relink_gparts_to_sparts(struct spart *sparts, size_t N,
+                                  ptrdiff_t offset) {
+  for (size_t k = 0; k < N; k++) {
+    if (sparts[k].gpart) {
+      sparts[k].gpart->id_or_neg_offset = -(k + offset);
+    }
+  }
+}
+
+/**
+ * @brief Re-link the #part%s associated with the list of #gpart%s.
  *
  * @param gparts The list of #gpart.
  * @param N The number of particles to re-link;
- * @param parts The global part array in which to find the #gpart offsets.
+ * @param parts The global #part array in which to find the #gpart offsets.
  */
-void part_relink_parts(struct gpart *gparts, size_t N, struct part *parts) {
+void part_relink_parts_to_gparts(struct gpart *gparts, size_t N,
+                                 struct part *parts) {
   for (size_t k = 0; k < N; k++) {
-    if (gparts[k].id_or_neg_offset <= 0) {
+    if (gparts[k].type == swift_type_gas) {
       parts[-gparts[k].id_or_neg_offset].gpart = &gparts[k];
     }
   }
 }
 
+/**
+ * @brief Re-link the #spart%s associated with the list of #gpart%s.
+ *
+ * @param gparts The list of #gpart.
+ * @param N The number of particles to re-link;
+ * @param sparts The global #spart array in which to find the #gpart offsets.
+ */
+void part_relink_sparts_to_gparts(struct gpart *gparts, size_t N,
+                                  struct spart *sparts) {
+  for (size_t k = 0; k < N; k++) {
+    if (gparts[k].type == swift_type_star) {
+      sparts[-gparts[k].id_or_neg_offset].gpart = &gparts[k];
+    }
+  }
+}
+
 #ifdef WITH_MPI
 /* MPI data type for the particle transfers */
 MPI_Datatype part_mpi_type;
diff --git a/src/part.h b/src/part.h
index 269e12a9c6b4adbd1046f1a008f1b21ab3214128..149b06eee885cd2614541f5e2afb2db1b8928266 100644
--- a/src/part.h
+++ b/src/part.h
@@ -32,6 +32,7 @@
 
 /* Local headers. */
 #include "align.h"
+#include "part_type.h"
 
 /* Some constants. */
 #define part_align 128
@@ -66,8 +67,14 @@
 /* Import the right star particle definition */
 #include "./stars/Default/star_part.h"
 
-void part_relink_gparts(struct part *parts, size_t N, ptrdiff_t offset);
-void part_relink_parts(struct gpart *gparts, size_t N, struct part *parts);
+void part_relink_gparts_to_parts(struct part *parts, size_t N,
+                                 ptrdiff_t offset);
+void part_relink_gparts_to_sparts(struct spart *sparts, size_t N,
+                                  ptrdiff_t offset);
+void part_relink_parts_to_gparts(struct gpart *gparts, size_t N,
+                                 struct part *parts);
+void part_relink_sparts_to_gparts(struct gpart *gparts, size_t N,
+                                  struct spart *sparts);
 #ifdef WITH_MPI
 /* MPI data type for the particle transfers */
 extern MPI_Datatype part_mpi_type;
diff --git a/src/part_type.h b/src/part_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c564d6908c8887e8fa8a5197a0a92ed85cbe5bb
--- /dev/null
+++ b/src/part_type.h
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ******************************************************************************/
+#ifndef SWIFT_PART_TYPES_H
+#define SWIFT_PART_TYPES_H
+
+/**
+ * @brief The different types of particles a #gpart can link to.
+ *
+ * Note we use the historical values from Gadget for these fields.
+ */
+enum part_type {
+  swift_type_gas = 0,
+  swift_type_dark_matter = 1,
+  swift_type_star = 4,
+  swift_type_black_hole = 5
+} __attribute__((packed));
+
+#endif /* SWIFT_PART_TYPES_H */
diff --git a/src/space.c b/src/space.c
index 84af59d30fdebe839212ea9119aec92d2384802f..38e72f2e1946e850500c8003f94a508dca47bc9e 100644
--- a/src/space.c
+++ b/src/space.c
@@ -108,6 +108,7 @@ struct parallel_sort {
   struct part *parts;
   struct gpart *gparts;
   struct xpart *xparts;
+  struct spart *sparts;
   int *ind;
   struct qstack *stack;
   unsigned int stack_size;
@@ -211,6 +212,7 @@ void space_rebuild_recycle_mapper(void *map_data, int num_elements,
     c->sorted = 0;
     c->count = 0;
     c->gcount = 0;
+    c->scount = 0;
     c->init = NULL;
     c->extra_ghost = NULL;
     c->ghost = NULL;
@@ -389,6 +391,7 @@ void space_regrid(struct space *s, int verbose) {
           c->depth = 0;
           c->count = 0;
           c->gcount = 0;
+          c->scount = 0;
           c->super = c;
           c->ti_old = ti_current;
           lock_init(&c->lock);
@@ -470,6 +473,7 @@ void space_rebuild(struct space *s, int verbose) {
 
   size_t nr_parts = s->nr_parts;
   size_t nr_gparts = s->nr_gparts;
+  size_t nr_sparts = s->nr_sparts;
   struct cell *restrict cells_top = s->cells_top;
   const int ti_current = (s->e != NULL) ? s->e->ti_current : 0;
 
@@ -490,6 +494,14 @@ void space_rebuild(struct space *s, int verbose) {
   if (s->size_gparts > 0)
     space_gparts_get_cell_index(s, gind, cells_top, verbose);
 
+  /* Run through the star particles and get their cell index. */
+  const size_t sind_size = s->size_sparts + 100;
+  int *sind;
+  if ((sind = (int *)malloc(sizeof(int) * sind_size)) == NULL)
+    error("Failed to allocate temporary s-particle indices.");
+  if (s->size_sparts > 0)
+    space_sparts_get_cell_index(s, sind, cells_top, verbose);
+
 #ifdef WITH_MPI
 
   /* Move non-local parts to the end of the list. */
@@ -612,8 +624,15 @@ void space_rebuild(struct space *s, int verbose) {
   if (nr_parts > 0)
     space_parts_sort(s, ind, nr_parts, 0, s->nr_cells - 1, verbose);
 
-  /* Re-link the gparts. */
-  if (nr_parts > 0 && nr_gparts > 0) part_relink_gparts(s->parts, nr_parts, 0);
+  /* Sort the sparts according to their cells. */
+  if (nr_sparts > 0)
+    space_sparts_sort(s, sind, nr_sparts, 0, s->nr_cells - 1, verbose);
+
+  /* Re-link the gparts to their (s-)particles. */
+  if (nr_parts > 0 && nr_gparts > 0)
+    part_relink_gparts_to_parts(s->parts, nr_parts, 0);
+  if (nr_sparts > 0 && nr_gparts > 0)
+    part_relink_gparts_to_sparts(s->sparts, nr_sparts, 0);
 
 #ifdef SWIFT_DEBUG_CHECKS
   /* Verify space_sort_struct. */
@@ -638,8 +657,19 @@ void space_rebuild(struct space *s, int verbose) {
     }
   }
 
+  /* Extract the cell counts from the sorted indices. */
+  size_t last_sindex = 0;
+  sind[nr_parts] = s->nr_cells;  // sentinel.
+  for (size_t k = 0; k < nr_sparts; k++) {
+    if (sind[k] < sind[k + 1]) {
+      cells_top[sind[k]].scount = k - last_sindex + 1;
+      last_sindex = k + 1;
+    }
+  }
+
   /* We no longer need the indices as of here. */
   free(ind);
+  free(sind);
 
 #ifdef WITH_MPI
 
@@ -667,7 +697,7 @@ void space_rebuild(struct space *s, int verbose) {
   }
   nr_gparts = s->nr_gparts;
 
-#endif
+#endif /* WITH_MPI */
 
   /* Sort the gparts according to their cells. */
   if (nr_gparts > 0)
@@ -675,7 +705,11 @@ void space_rebuild(struct space *s, int verbose) {
 
   /* Re-link the parts. */
   if (nr_parts > 0 && nr_gparts > 0)
-    part_relink_parts(s->gparts, nr_gparts, s->parts);
+    part_relink_parts_to_gparts(s->gparts, nr_gparts, s->parts);
+
+  /* Re-link the sparts. */
+  if (nr_sparts > 0 && nr_gparts > 0)
+    part_relink_sparts_to_gparts(s->gparts, nr_gparts, s->sparts);
 
   /* Extract the cell counts from the sorted indices. */
   size_t last_gindex = 0;
@@ -719,15 +753,18 @@ void space_rebuild(struct space *s, int verbose) {
   struct part *finger = s->parts;
   struct xpart *xfinger = s->xparts;
   struct gpart *gfinger = s->gparts;
+  struct spart *sfinger = s->sparts;
   for (int k = 0; k < s->nr_cells; k++) {
     struct cell *restrict c = &cells_top[k];
     c->ti_old = ti_current;
     c->parts = finger;
     c->xparts = xfinger;
     c->gparts = gfinger;
+    c->sparts = sfinger;
     finger = &finger[c->count];
     xfinger = &xfinger[c->count];
     gfinger = &gfinger[c->gcount];
+    sfinger = &sfinger[c->scount];
   }
   // message( "hooking up cells took %.3f %s." ,
   // clocks_from_ticks(getticks() - tic), clocks_getunit());
@@ -892,8 +929,58 @@ void space_gparts_get_cell_index_mapper(void *map_data, int nr_gparts,
 }
 
 /**
- * @brief Computes the cell index of all the particles and update the cell
- * count.
+ * @brief #threadpool mapper function to compute the s-particle cell indices.
+ *
+ * @param map_data Pointer towards the s-particles.
+ * @param nr_sparts The number of s-particles to treat.
+ * @param extra_data Pointers to the space and index list
+ */
+void space_sparts_get_cell_index_mapper(void *map_data, int nr_sparts,
+                                        void *extra_data) {
+
+  /* Unpack the data */
+  struct spart *restrict sparts = (struct spart *)map_data;
+  struct index_data *data = (struct index_data *)extra_data;
+  struct space *s = data->s;
+  int *const ind = data->ind + (ptrdiff_t)(sparts - s->sparts);
+
+  /* Get some constants */
+  const double dim_x = s->dim[0];
+  const double dim_y = s->dim[1];
+  const double dim_z = s->dim[2];
+  const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]};
+  const double ih_x = s->iwidth[0];
+  const double ih_y = s->iwidth[1];
+  const double ih_z = s->iwidth[2];
+
+  for (int k = 0; k < nr_sparts; k++) {
+
+    /* Get the particle */
+    struct spart *restrict sp = &sparts[k];
+
+    const double old_pos_x = sp->x[0];
+    const double old_pos_y = sp->x[1];
+    const double old_pos_z = sp->x[2];
+
+    /* Put it back into the simulation volume */
+    const double pos_x = box_wrap(old_pos_x, 0.0, dim_x);
+    const double pos_y = box_wrap(old_pos_y, 0.0, dim_y);
+    const double pos_z = box_wrap(old_pos_z, 0.0, dim_z);
+
+    /* Get its cell index */
+    const int index =
+        cell_getid(cdim, pos_x * ih_x, pos_y * ih_y, pos_z * ih_z);
+    ind[k] = index;
+
+    /* Update the position */
+    sp->x[0] = pos_x;
+    sp->x[1] = pos_y;
+    sp->x[2] = pos_z;
+  }
+}
+
+/**
+ * @brief Computes the cell index of all the particles.
  *
  * @param s The #space.
  * @param ind The array of indices to fill.
@@ -920,8 +1007,7 @@ void space_parts_get_cell_index(struct space *s, int *ind, struct cell *cells,
 }
 
 /**
- * @brief Computes the cell index of all the g-particles and update the cell
- * gcount.
+ * @brief Computes the cell index of all the g-particles.
  *
  * @param s The #space.
  * @param gind The array of indices to fill.
@@ -947,6 +1033,33 @@ void space_gparts_get_cell_index(struct space *s, int *gind, struct cell *cells,
             clocks_getunit());
 }
 
+/**
+ * @brief Computes the cell index of all the s-particles.
+ *
+ * @param s The #space.
+ * @param sind The array of indices to fill.
+ * @param cells The array of #cell to update.
+ * @param verbose Are we talkative ?
+ */
+void space_sparts_get_cell_index(struct space *s, int *sind, struct cell *cells,
+                                 int verbose) {
+
+  const ticks tic = getticks();
+
+  /* Pack the extra information */
+  struct index_data data;
+  data.s = s;
+  data.cells = cells;
+  data.ind = sind;
+
+  threadpool_map(&s->e->threadpool, space_sparts_get_cell_index_mapper,
+                 s->sparts, s->nr_sparts, sizeof(struct gpart), 1000, &data);
+
+  if (verbose)
+    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
+            clocks_getunit());
+}
+
 /**
  * @brief Sort the particles and condensed particles according to the given
  * indices.
@@ -1127,6 +1240,182 @@ void space_parts_sort_mapper(void *map_data, int num_elements,
   } /* main loop. */
 }
 
+/**
+ * @brief Sort the s-particles according to the given indices.
+ *
+ * @param s The #space.
+ * @param ind The indices with respect to which the #spart are sorted.
+ * @param N The number of parts
+ * @param min Lowest index.
+ * @param max highest index.
+ * @param verbose Are we talkative ?
+ */
+void space_sparts_sort(struct space *s, int *ind, size_t N, int min, int max,
+                       int verbose) {
+
+  const ticks tic = getticks();
+
+  /* Populate a parallel_sort structure with the input data */
+  struct parallel_sort sort_struct;
+  sort_struct.sparts = s->sparts;
+  sort_struct.ind = ind;
+  sort_struct.stack_size = 2 * (max - min + 1) + 10 + s->e->nr_threads;
+  if ((sort_struct.stack =
+           malloc(sizeof(struct qstack) * sort_struct.stack_size)) == NULL)
+    error("Failed to allocate sorting stack.");
+  for (unsigned int i = 0; i < sort_struct.stack_size; i++)
+    sort_struct.stack[i].ready = 0;
+
+  /* Add the first interval. */
+  sort_struct.stack[0].i = 0;
+  sort_struct.stack[0].j = N - 1;
+  sort_struct.stack[0].min = min;
+  sort_struct.stack[0].max = max;
+  sort_struct.stack[0].ready = 1;
+  sort_struct.first = 0;
+  sort_struct.last = 1;
+  sort_struct.waiting = 1;
+
+  /* Launch the sorting tasks with a stride of zero such that the same
+     map data is passed to each thread. */
+  threadpool_map(&s->e->threadpool, space_sparts_sort_mapper, &sort_struct,
+                 s->e->threadpool.num_threads, 0, 1, NULL);
+
+#ifdef SWIFT_DEBUG_CHECKS
+  /* Verify space_sort_struct. */
+  for (size_t i = 1; i < N; i++)
+    if (ind[i - 1] > ind[i])
+      error("Sorting failed (ind[%zu]=%i,ind[%zu]=%i), min=%i, max=%i.", i - 1,
+            ind[i - 1], i, ind[i], min, max);
+  message("Sorting succeeded.");
+#endif
+
+  /* Clean up. */
+  free(sort_struct.stack);
+
+  if (verbose)
+    message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
+            clocks_getunit());
+}
+
+void space_sparts_sort_mapper(void *map_data, int num_elements,
+                              void *extra_data) {
+
+  /* Unpack the mapping data. */
+  struct parallel_sort *sort_struct = (struct parallel_sort *)map_data;
+
+  /* Pointers to the sorting data. */
+  int *ind = sort_struct->ind;
+  struct spart *sparts = sort_struct->sparts;
+
+  /* Main loop. */
+  while (sort_struct->waiting) {
+
+    /* Grab an interval off the queue. */
+    int qid = atomic_inc(&sort_struct->first) % sort_struct->stack_size;
+
+    /* Wait for the entry to be ready, or for the sorting do be done. */
+    while (!sort_struct->stack[qid].ready)
+      if (!sort_struct->waiting) return;
+
+    /* Get the stack entry. */
+    ptrdiff_t i = sort_struct->stack[qid].i;
+    ptrdiff_t j = sort_struct->stack[qid].j;
+    int min = sort_struct->stack[qid].min;
+    int max = sort_struct->stack[qid].max;
+    sort_struct->stack[qid].ready = 0;
+
+    /* Loop over sub-intervals. */
+    while (1) {
+
+      /* Bring beer. */
+      const int pivot = (min + max) / 2;
+      /* message("Working on interval [%i,%i] with min=%i, max=%i, pivot=%i.",
+              i, j, min, max, pivot); */
+
+      /* One pass of QuickSort's partitioning. */
+      ptrdiff_t ii = i;
+      ptrdiff_t jj = j;
+      while (ii < jj) {
+        while (ii <= j && ind[ii] <= pivot) ii++;
+        while (jj >= i && ind[jj] > pivot) jj--;
+        if (ii < jj) {
+          memswap(&ind[ii], &ind[jj], sizeof(int));
+          memswap(&sparts[ii], &sparts[jj], sizeof(struct spart));
+        }
+      }
+
+#ifdef SWIFT_DEBUG_CHECKS
+      /* Verify space_sort_struct. */
+      for (int k = i; k <= jj; k++)
+        if (ind[k] > pivot) {
+          message("sorting failed at k=%i, ind[k]=%i, pivot=%i, i=%li, j=%li.",
+                  k, ind[k], pivot, i, j);
+          error("Partition failed (<=pivot).");
+        }
+      for (int k = jj + 1; k <= j; k++)
+        if (ind[k] <= pivot) {
+          message("sorting failed at k=%i, ind[k]=%i, pivot=%i, i=%li, j=%li.",
+                  k, ind[k], pivot, i, j);
+          error("Partition failed (>pivot).");
+        }
+#endif
+
+      /* Split-off largest interval. */
+      if (jj - i > j - jj + 1) {
+
+        /* Recurse on the left? */
+        if (jj > i && pivot > min) {
+          qid = atomic_inc(&sort_struct->last) % sort_struct->stack_size;
+          while (sort_struct->stack[qid].ready)
+            ;
+          sort_struct->stack[qid].i = i;
+          sort_struct->stack[qid].j = jj;
+          sort_struct->stack[qid].min = min;
+          sort_struct->stack[qid].max = pivot;
+          if (atomic_inc(&sort_struct->waiting) >= sort_struct->stack_size)
+            error("Qstack overflow.");
+          sort_struct->stack[qid].ready = 1;
+        }
+
+        /* Recurse on the right? */
+        if (jj + 1 < j && pivot + 1 < max) {
+          i = jj + 1;
+          min = pivot + 1;
+        } else
+          break;
+
+      } else {
+
+        /* Recurse on the right? */
+        if (pivot + 1 < max) {
+          qid = atomic_inc(&sort_struct->last) % sort_struct->stack_size;
+          while (sort_struct->stack[qid].ready)
+            ;
+          sort_struct->stack[qid].i = jj + 1;
+          sort_struct->stack[qid].j = j;
+          sort_struct->stack[qid].min = pivot + 1;
+          sort_struct->stack[qid].max = max;
+          if (atomic_inc(&sort_struct->waiting) >= sort_struct->stack_size)
+            error("Qstack overflow.");
+          sort_struct->stack[qid].ready = 1;
+        }
+
+        /* Recurse on the left? */
+        if (jj > i && pivot > min) {
+          j = jj;
+          max = pivot;
+        } else
+          break;
+      }
+
+    } /* loop over sub-intervals. */
+
+    atomic_dec(&sort_struct->waiting);
+
+  } /* main loop. */
+}
+
 /**
  * @brief Sort the g-particles according to the given indices.
  *
diff --git a/src/space.h b/src/space.h
index 1103cc4867c0ff7ded700331a1a4ff540233e8a7..17e4fc507488ba9f494dbf8d6ca0b702b2bc543e 100644
--- a/src/space.h
+++ b/src/space.h
@@ -153,6 +153,8 @@ void space_parts_sort(struct space *s, int *ind, size_t N, int min, int max,
                       int verbose);
 void space_gparts_sort(struct space *s, int *ind, size_t N, int min, int max,
                        int verbose);
+void space_sparts_sort(struct space *s, int *ind, size_t N, int min, int max,
+                       int verbose);
 struct cell *space_getcell(struct space *s);
 int space_getsid(struct space *s, struct cell **ci, struct cell **cj,
                  double *shift);
@@ -176,6 +178,8 @@ void space_parts_sort_mapper(void *map_data, int num_elements,
                              void *extra_data);
 void space_gparts_sort_mapper(void *map_data, int num_elements,
                               void *extra_data);
+void space_sparts_sort_mapper(void *map_data, int num_elements,
+                              void *extra_data);
 void space_rebuild(struct space *s, int verbose);
 void space_recycle(struct space *s, struct cell *c);
 void space_recycle_list(struct space *s, struct cell *list_begin,
@@ -187,8 +191,11 @@ void space_parts_get_cell_index(struct space *s, int *ind, struct cell *cells,
                                 int verbose);
 void space_gparts_get_cell_index(struct space *s, int *gind, struct cell *cells,
                                  int verbose);
+void space_sparts_get_cell_index(struct space *s, int *sind, struct cell *cells,
+                                 int verbose);
 void space_do_parts_sort();
 void space_do_gparts_sort();
+void space_do_sparts_sort();
 void space_init_parts(struct space *s);
 void space_init_gparts(struct space *s);
 void space_init_sparts(struct space *s);
diff --git a/src/stars/Default/star_part.h b/src/stars/Default/star_part.h
index 3ee5a9452549f5f02aaf8131204b5018ccb1d029..943a392db2e6e93a52c95f4aa4ec794246589939 100644
--- a/src/stars/Default/star_part.h
+++ b/src/stars/Default/star_part.h
@@ -40,6 +40,7 @@ struct spart {
   /* Particle velocity. */
   float v[3];
 
+  /* Star mass */
   float mass;
 
   /* Particle time of beginning of time-step. */