diff --git a/examples/BigCosmoVolume/makeIC.py b/examples/BigCosmoVolume/makeIC.py
index 8b668289525725bae3ca613feb76b331e7f1909f..0994e1c95e053defe7766122c52bc405c7239776 100644
--- a/examples/BigCosmoVolume/makeIC.py
+++ b/examples/BigCosmoVolume/makeIC.py
@@ -64,7 +64,7 @@ v = inputFile["/PartType0/Velocities"][:,:]
 m = inputFile["/PartType0/Masses"][:]
 h = inputFile["/PartType0/SmoothingLength"][:]
 u = inputFile["/PartType0/InternalEnergy"][:]
-ids = np.array(range(np.size(u)), dtype='L')
+ids = np.array(range(np.size(u)), dtype='L') + 1
 
 # Downsample
 print "Downsampling..."
diff --git a/examples/BigPerturbedBox/makeIC_fcc.py b/examples/BigPerturbedBox/makeIC_fcc.py
index dfe2a41b7d8a17f3f7424294e11d944ae5ff2b94..13809b41b65890c51abfbd6db48640fb07b21623 100644
--- a/examples/BigPerturbedBox/makeIC_fcc.py
+++ b/examples/BigPerturbedBox/makeIC_fcc.py
@@ -111,6 +111,6 @@ ds[()] = h
 ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f')
 ds[()] = u
 ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L')
-ds[()] = ids
+ds[()] = ids + 1
 
 file.close()
diff --git a/examples/GreshoVortex/makeIC.py b/examples/GreshoVortex/makeIC.py
index 533199869ee325dd75831410f3e9f1181ae30ebd..6aceeed559324f97b0b1e388ff0c3524498b52e4 100644
--- a/examples/GreshoVortex/makeIC.py
+++ b/examples/GreshoVortex/makeIC.py
@@ -82,7 +82,7 @@ for i in range(L):
             else:
                 P = P + 3. + 4.*log(2.)
             u[index] = P / ((gamma - 1.)*rho)
-            ids[index] = partId
+            ids[index] = partId + 1
             partId = partId + 1
 
 
diff --git a/examples/Makefile.am b/examples/Makefile.am
index b2c09e54800c556ba03bdb1e2436af3144263dcb..200d340be168651e6dfc91f4b89a0a343d34d9da 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -63,13 +63,15 @@ swift_fixdt_mpi_LDADD =  ../src/.libs/libswiftsim_mpi.a $(HDF5_LDFLAGS) $(HDF5_L
 
 # Scripts to generate ICs
 EXTRA_DIST = UniformBox/makeIC.py \
-             PerturbedBox/makeIC.py \
+	     UniformDMBox/makeIC.py \
+	     PerturbedBox/makeIC.py \
 	     SedovBlast/makeIC.py SedovBlast/makeIC_fcc.py SedovBlast/solution.py \
 	     SodShock/makeIC.py SodShock/solution.py SodShock/glass_001.hdf5 SodShock/glass_002.hdf5 SodShock/rhox.py \
 	     CosmoVolume/getIC.sh \
 	     BigCosmoVolume/makeIC.py \
 	     BigPerturbedBox/makeIC_fcc.py \
-             GreshoVortex/makeIC.py GreshoVortex/solution.py
+             GreshoVortex/makeIC.py GreshoVortex/solution.py \
+             MultiTypes/makeIC.py
 
 
 # Scripts to plot task graphs
diff --git a/examples/MultiTypes/makeIC.py b/examples/MultiTypes/makeIC.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a41910c22c260086b5384b248a5c86ab6340a5e
--- /dev/null
+++ b/examples/MultiTypes/makeIC.py
@@ -0,0 +1,136 @@
+###############################################################################
+ # This file is part of SWIFT.
+ # Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
+ #                    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/>.
+ # 
+ ##############################################################################
+
+import h5py
+import sys
+from numpy import *
+
+# Generates a swift IC file containing a cartesian distribution of DM particles
+# with a density of 1
+
+# Parameters
+periodic= 1           # 1 For periodic box
+boxSize = 1.
+Lgas = int(sys.argv[1])  # Number of particles along one axis
+rhoGas = 2.              # Density
+P = 1.                   # Pressure
+gamma = 5./3.            # Gas adiabatic index
+rhoDM = 1.
+Ldm = int(sys.argv[2])  # Number of particles along one axis
+
+fileName = "multiTypes.hdf5"
+
+#---------------------------------------------------
+numGas = Lgas**3
+massGas = boxSize**3 * rhoGas / numGas
+internalEnergy = P / ((gamma - 1.)*rhoGas)
+
+numDM = Ldm**3
+massDM = boxSize**3 * rhoDM / numDM
+
+#--------------------------------------------------
+
+#File
+file = h5py.File(fileName, 'w')
+
+# Header
+grp = file.create_group("/Header")
+grp.attrs["BoxSize"] = boxSize
+grp.attrs["NumPart_Total"] =  [numGas, numDM, 0, 0, 0, 0]
+grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_ThisFile"] = [numGas, numDM, 0, 0, 0, 0]
+grp.attrs["Time"] = 0.0
+grp.attrs["NumFilesPerSnapshot"] = 1
+grp.attrs["MassTable"] = [0.0, massDM, 0.0, 0.0, 0.0, 0.0]
+grp.attrs["Flag_Entropy_ICs"] = 0
+
+
+#Runtime parameters
+grp = file.create_group("/RuntimePars")
+grp.attrs["PeriodicBoundariesOn"] = periodic
+
+
+# Gas Particle group
+grp = file.create_group("/PartType0")
+
+v  = zeros((numGas, 3))
+ds = grp.create_dataset('Velocities', (numGas, 3), 'f')
+ds[()] = v
+v = zeros(1)
+
+m = full((numGas, 1), massGas)
+ds = grp.create_dataset('Masses', (numGas,1), 'f')
+ds[()] = m
+m = zeros(1)
+
+h = full((numGas, 1), 1.1255 * boxSize / Lgas)
+ds = grp.create_dataset('SmoothingLength', (numGas,1), 'f')
+ds[()] = h
+h = zeros(1)
+
+u = full((numGas, 1), internalEnergy)
+ds = grp.create_dataset('InternalEnergy', (numGas,1), 'f')
+ds[()] = u
+u = zeros(1)
+
+ids = linspace(0, numGas, numGas, endpoint=False).reshape((numGas,1))
+ds = grp.create_dataset('ParticleIDs', (numGas, 1), 'L')
+ds[()] = ids + 1
+x      = ids % Lgas;
+y      = ((ids - x) / Lgas) % Lgas;
+z      = (ids - x - Lgas * y) / Lgas**2;
+coords = zeros((numGas, 3))
+coords[:,0] = z[:,0] * boxSize / Lgas + boxSize / (2*Lgas)
+coords[:,1] = y[:,0] * boxSize / Lgas + boxSize / (2*Lgas)
+coords[:,2] = x[:,0] * boxSize / Lgas + boxSize / (2*Lgas)
+ds = grp.create_dataset('Coordinates', (numGas, 3), 'd')
+ds[()] = coords
+
+
+
+
+
+# DM Particle group
+grp = file.create_group("/PartType1")
+
+v  = zeros((numDM, 3))
+ds = grp.create_dataset('Velocities', (numDM, 3), 'f')
+ds[()] = v
+v = zeros(1)
+
+m = full((numDM, 1), massDM)
+ds = grp.create_dataset('Masses', (numDM,1), 'f')
+ds[()] = m
+m = zeros(1)
+
+ids = linspace(0, numDM, numDM, endpoint=False).reshape((numDM,1))
+ds = grp.create_dataset('ParticleIDs', (numDM, 1), 'L')
+ds[()] = ids + Lgas**3 + 1
+x      = ids % Ldm;
+y      = ((ids - x) / Ldm) % Ldm;
+z      = (ids - x - Ldm * y) / Ldm**2;
+coords = zeros((numDM, 3))
+coords[:,0] = z[:,0] * boxSize / Ldm + boxSize / (2*Ldm)
+coords[:,1] = y[:,0] * boxSize / Ldm + boxSize / (2*Ldm)
+coords[:,2] = x[:,0] * boxSize / Ldm + boxSize / (2*Ldm)
+ds = grp.create_dataset('Coordinates', (numDM, 3), 'd')
+ds[()] = coords
+
+file.close()
diff --git a/examples/PerturbedBox/makeIC.py b/examples/PerturbedBox/makeIC.py
index a5e831eca02463d287ce2c7748eb780ef66aeb33..69c1a69199c9a5262f5ae6c4e95ca14699300fd4 100644
--- a/examples/PerturbedBox/makeIC.py
+++ b/examples/PerturbedBox/makeIC.py
@@ -103,6 +103,6 @@ ds[()] = h
 ds = grp.create_dataset('InternalEnergy', (numPart,1), 'f')
 ds[()] = u
 ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L')
-ds[()] = ids
+ds[()] = ids + 1
 
 file.close()
diff --git a/examples/SedovBlast/makeIC.py b/examples/SedovBlast/makeIC.py
index 04ff73a3cdc4d81cd6edb45ef66e4eb8b0df46a2..75ff81165df51780848e3d8ac679a6dbeb17a039 100644
--- a/examples/SedovBlast/makeIC.py
+++ b/examples/SedovBlast/makeIC.py
@@ -69,7 +69,7 @@ for i in range(L):
             m[index] = mass
             h[index] = 1.1255 * boxSize / L
             u[index] = internalEnergy
-            ids[index] = index
+            ids[index] = index + 1
             if sqrt((x - boxSize/2.)**2 + (y - boxSize/2.)**2 + (z - boxSize/2.)**2) < 2.01 * boxSize/L:
                 u[index] = u[index] + E0 / (33. * mass)
                 print "Particle " , index , " set to detonate."
diff --git a/examples/SedovBlast/makeIC_fcc.py b/examples/SedovBlast/makeIC_fcc.py
index edff869b38d8077944574caf8273bca2b0ab6a33..17f07440909cb5478d09a5b7a1444c72af2f3a47 100644
--- a/examples/SedovBlast/makeIC_fcc.py
+++ b/examples/SedovBlast/makeIC_fcc.py
@@ -72,7 +72,7 @@ for i in range(L):
                 m[index] = mass
                 h[index] = 1.1255 * hbox
                 u[index] = internalEnergy
-                ids[index] = index
+                ids[index] = index + 1
                 if sqrt((x - boxSize/2.)**2 + (y - boxSize/2.)**2 + (z - boxSize/2.)**2) < 1.2 * hbox:
                     u[index] = u[index] + E0 / (28. * mass)
                     print "Particle " , index , " set to detonate."
diff --git a/examples/SodShock/makeIC.py b/examples/SodShock/makeIC.py
index 5bee473f06543d50412ccc476960504c10d56455..0ac0564116f8a6ceb57b4f41d23eb9907df0440d 100644
--- a/examples/SodShock/makeIC.py
+++ b/examples/SodShock/makeIC.py
@@ -86,8 +86,8 @@ h = append(h1, h2,0)
 u = append(u1, u2,0)
 m = append(m1, m2,0)
 ids = zeros(numPart, dtype='L')
-for i in range(numPart):
-    ids[i] = i
+for i in range(1, numPart+1):
+    ids[i-1] = i
 
 #Final operations
 h /= 2
diff --git a/examples/UniformBox/makeIC.py b/examples/UniformBox/makeIC.py
index ea094e5a531456788dcbc35c098dc04e4d858da3..c175349e658799cbcb30dfe2619a1594bafc18b9 100644
--- a/examples/UniformBox/makeIC.py
+++ b/examples/UniformBox/makeIC.py
@@ -86,7 +86,7 @@ u = zeros(1)
 
 ids = linspace(0, numPart, numPart, endpoint=False).reshape((numPart,1))
 ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L')
-ds[()] = ids
+ds[()] = ids + 1
 x      = ids % L;
 y      = ((ids - x) / L) % L;
 z      = (ids - x - L * y) / L**2;
diff --git a/examples/UniformBox/makeICbig.py b/examples/UniformBox/makeICbig.py
index 28b4667cccf381532900c61228c24b3b6b1d62c1..e475fdcbd9f3c4811e3dcfdf20bbd321be3d8b29 100644
--- a/examples/UniformBox/makeICbig.py
+++ b/examples/UniformBox/makeICbig.py
@@ -98,7 +98,7 @@ for n in range(n_iterations):
     u = zeros(1)
 
     ids = linspace(offset, offset+N, N, endpoint=False).reshape((N,1))
-    ds_id[offset:offset+N] = ids
+    ds_id[offset:offset+N] = ids + 1
     x      = ids % L;
     y      = ((ids - x) / L) % L;
     z      = (ids - x - L * y) / L**2;
@@ -130,10 +130,8 @@ u = full((remainder, 1), internalEnergy)
 ds_u[offset:offset+remainder] = u
 u = zeros(1)
 
-print "Done", offset+remainder,"/", numPart
-
 ids = linspace(offset, offset+remainder, remainder, endpoint=False).reshape((remainder,1))
-ds_id[offset:offset+remainder] = ids
+ds_id[offset:offset+remainder] = ids + 1
 x      = ids % L;
 y      = ((ids - x) / L) % L;
 z      = (ids - x - L * y) / L**2;
@@ -143,6 +141,7 @@ coords[:,1] = y[:,0] * boxSize / L + boxSize / (2*L)
 coords[:,2] = x[:,0] * boxSize / L + boxSize / (2*L)
 ds_x[offset:offset+remainder,:] = coords
 
+print "Done", offset+remainder,"/", numPart
 
 
 
diff --git a/examples/UniformDMBox/makeIC.py b/examples/UniformDMBox/makeIC.py
new file mode 100644
index 0000000000000000000000000000000000000000..061b4d0ad1959d9e25356aff80e78adb9c1c4faa
--- /dev/null
+++ b/examples/UniformDMBox/makeIC.py
@@ -0,0 +1,86 @@
+###############################################################################
+ # This file is part of SWIFT.
+ # Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
+ #                    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/>.
+ # 
+ ##############################################################################
+
+import h5py
+import sys
+from numpy import *
+
+# Generates a swift IC file containing a cartesian distribution of DM particles
+# with a density of 1
+
+# Parameters
+periodic= 1           # 1 For periodic box
+boxSize = 1.
+rho = 1.
+L = int(sys.argv[1])  # Number of particles along one axis
+fileName = "uniformDMBox_%d.hdf5"%L 
+
+#---------------------------------------------------
+numPart = L**3
+mass = boxSize**3 * rho / numPart
+
+#--------------------------------------------------
+
+#File
+file = h5py.File(fileName, 'w')
+
+# Header
+grp = file.create_group("/Header")
+grp.attrs["BoxSize"] = boxSize
+grp.attrs["NumPart_Total"] =  [0, numPart, 0, 0, 0, 0]
+grp.attrs["NumPart_Total_HighWord"] = [0, 0, 0, 0, 0, 0]
+grp.attrs["NumPart_ThisFile"] = [0, numPart, 0, 0, 0, 0]
+grp.attrs["Time"] = 0.0
+grp.attrs["NumFilesPerSnapshot"] = 1
+grp.attrs["MassTable"] = [0.0, mass, 0.0, 0.0, 0.0, 0.0]
+grp.attrs["Flag_Entropy_ICs"] = 0
+
+
+#Runtime parameters
+grp = file.create_group("/RuntimePars")
+grp.attrs["PeriodicBoundariesOn"] = periodic
+
+#Particle group
+grp = file.create_group("/PartType1")
+
+v  = zeros((numPart, 3))
+ds = grp.create_dataset('Velocities', (numPart, 3), 'f')
+ds[()] = v
+v = zeros(1)
+
+m = full((numPart, 1), mass)
+ds = grp.create_dataset('Masses', (numPart,1), 'f')
+ds[()] = m
+m = zeros(1)
+
+ids = linspace(0, numPart, numPart, endpoint=False).reshape((numPart,1))
+ds = grp.create_dataset('ParticleIDs', (numPart, 1), 'L')
+ds[()] = ids + 1
+x      = ids % L;
+y      = ((ids - x) / L) % L;
+z      = (ids - x - L * y) / L**2;
+coords = zeros((numPart, 3))
+coords[:,0] = z[:,0] * boxSize / L + boxSize / (2*L)
+coords[:,1] = y[:,0] * boxSize / L + boxSize / (2*L)
+coords[:,2] = x[:,0] * boxSize / L + boxSize / (2*L)
+ds = grp.create_dataset('Coordinates', (numPart, 3), 'd')
+ds[()] = coords
+
+file.close()
diff --git a/examples/main.c b/examples/main.c
index 0fce7500af2e3d4fe98feb7e4d3f484658bd2ded..c88f92a07a747c327692b5e0fbbc7dc07b93ac0c 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -58,8 +58,9 @@
 
 int main(int argc, char *argv[]) {
 
-  int c, icount, j, k, N, periodic = 1;
-  long long N_total = -1;
+  int c, icount, periodic = 1;
+  size_t Ngas = 0, Ngpart = 0;
+  long long N_total[2] = {0, 0};
   int nr_threads = 1, nr_queues = -1;
   int dump_tasks = 0;
   int data[2];
@@ -67,6 +68,7 @@ int main(int argc, char *argv[]) {
   double h_max = -1.0, scaling = 1.0;
   double time_end = DBL_MAX;
   struct part *parts = NULL;
+  struct gpart *gparts = NULL;
   struct space s;
   struct engine e;
   struct UnitSystem us;
@@ -354,14 +356,14 @@ int main(int argc, char *argv[]) {
   if (myrank == 0) clocks_gettime(&tic);
 #if defined(WITH_MPI)
 #if defined(HAVE_PARALLEL_HDF5)
-  read_ic_parallel(ICfileName, dim, &parts, &N, &periodic, myrank, nr_nodes,
+  read_ic_parallel(ICfileName, dim, &parts, &Ngas, &periodic, myrank, nr_nodes,
                    MPI_COMM_WORLD, MPI_INFO_NULL);
 #else
-  read_ic_serial(ICfileName, dim, &parts, &N, &periodic, myrank, nr_nodes,
+  read_ic_serial(ICfileName, dim, &parts, &Ngas, &periodic, myrank, nr_nodes,
                  MPI_COMM_WORLD, MPI_INFO_NULL);
 #endif
 #else
-  read_ic_single(ICfileName, dim, &parts, &N, &periodic);
+  read_ic_single(ICfileName, dim, &parts, &gparts, &Ngas, &Ngpart, &periodic);
 #endif
 
   if (myrank == 0) {
@@ -372,24 +374,35 @@ int main(int argc, char *argv[]) {
   }
 
 #if defined(WITH_MPI)
-  long long N_long = N;
-  MPI_Reduce(&N_long, &N_total, 1, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+  long long N_long[2] = {Ngas, Ngpart};
+  MPI_Reduce(&N_long, &N_total, 2, MPI_LONG_LONG, MPI_SUM, 0, MPI_COMM_WORLD);
+  if (myrank == 0)
+    message("Read %lld gas particles and %lld DM particles from the ICs",
+            N_total[0], N_total[1]);
 #else
-  N_total = N;
+  N_total[0] = Ngas;
+  N_total[1] = Ngpart - Ngas;
+  message("Read %lld gas particles and %lld DM particles from the ICs",
+	  N_total[0], N_total[1]);
 #endif
-  if (myrank == 0) message("Read %lld particles from the ICs", N_total);
 
   /* Apply h scaling */
   if (scaling != 1.0)
-    for (k = 0; k < N; k++) parts[k].h *= scaling;
+    for (size_t k = 0; k < Ngas; k++) parts[k].h *= scaling;
 
   /* Apply shift */
-  if (shift[0] != 0 || shift[1] != 0 || shift[2] != 0)
-    for (k = 0; k < N; k++) {
+  if (shift[0] != 0 || shift[1] != 0 || shift[2] != 0) {
+    for (size_t k = 0; k < Ngas; k++) {
       parts[k].x[0] += shift[0];
       parts[k].x[1] += shift[1];
       parts[k].x[2] += shift[2];
     }
+    for (size_t k = 0; k < Ngpart; k++) {
+      gparts[k].x[0] += shift[0];
+      gparts[k].x[1] += shift[1];
+      gparts[k].x[2] += shift[2];
+    }
+  }
 
   /* Set default number of queues. */
   if (nr_queues < 0) nr_queues = nr_threads;
@@ -399,7 +412,8 @@ int main(int argc, char *argv[]) {
 
   /* Initialize the space with this data. */
   if (myrank == 0) clocks_gettime(&tic);
-  space_init(&s, dim, parts, N, periodic, h_max, myrank == 0);
+  space_init(&s, dim, parts, gparts, Ngas, Ngpart, periodic, h_max,
+             myrank == 0);
   if (myrank == 0 && verbose) {
     clocks_gettime(&toc);
     message("space_init took %.3f %s.", clocks_diff(&tic, &toc),
@@ -415,6 +429,7 @@ int main(int argc, char *argv[]) {
     message("highest-level cell dimensions are [ %i %i %i ].", s.cdim[0],
             s.cdim[1], s.cdim[2]);
     message("%zi parts in %i cells.", s.nr_parts, s.tot_cells);
+    message("%zi gparts in %i cells.", s.nr_gparts, s.tot_cells);
     message("maximum depth is %d.", s.maxdepth);
     // message( "cutoffs in [ %g %g ]." , s.h_min , s.h_max ); fflush(stdout);
   }
@@ -482,9 +497,10 @@ int main(int argc, char *argv[]) {
 
   if (myrank == 0) {
     message(
-        "Running on %lld particles until t=%.3e with %i threads and %i "
-        "queues (dt_min=%.3e, dt_max=%.3e)...",
-        N_total, time_end, e.nr_threads, e.sched.nr_queues, e.dt_min, e.dt_max);
+        "Running on %lld gas particles and %lld DM particles until t=%.3e with "
+        "%i threads and %i queues (dt_min=%.3e, dt_max=%.3e)...",
+        N_total[0], N_total[1], time_end, e.nr_threads, e.sched.nr_queues,
+        e.dt_min, e.dt_max);
     fflush(stdout);
   }
 
@@ -499,7 +515,7 @@ int main(int argc, char *argv[]) {
         clocks_getunit());
 
   /* Let loose a runner on the space. */
-  for (j = 0; !engine_is_done(&e); j++) {
+  for (int j = 0; !engine_is_done(&e); j++) {
 
 /* Repartition the space amongst the nodes? */
 #ifdef WITH_MPI
diff --git a/src/Makefile.am b/src/Makefile.am
index 8a4e7cdc4b849e8f99bdf9a3dbda9b30fa986332..f44d47819672d10445fd969fe2ff20dbcb49463b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,9 +46,9 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
 # Include files for distribution, not installation.
 nobase_noinst_HEADERS = approx_math.h atomic.h cycle.h error.h inline.h kernel.h vector.h \
 		 runner_doiact.h runner_doiact_grav.h units.h intrinsics.h minmax.h \
-		 gravity.h \
-		 gravity/Default/gravity.h gravity/Default/runner_iact_grav.h \
-		 gravity/Default/gravity_part.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  \
 	 	 hydro.h hydro_io.h \
 		 hydro/Minimal/hydro.h hydro/Minimal/hydro_iact.h hydro/Minimal/hydro_io.h \
                  hydro/Minimal/hydro_debug.h hydro/Minimal/hydro_part.h \
diff --git a/src/cell.c b/src/cell.c
index 3242c6b0b8226719d3f5311534f7945bb6c20a70..df11782048dfa80c697f53feefe8fabc104eb23b 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -345,9 +345,9 @@ void cell_split(struct cell *c) {
 
   int i, j;
   const int count = c->count, gcount = c->gcount;
-  struct part* parts = c->parts;
-  struct xpart* xparts = c->xparts;
-  struct gpart* gparts = c->gparts;
+  struct part *parts = c->parts;
+  struct xpart *xparts = c->xparts;
+  struct gpart *gparts = c->gparts;
   int left[8], right[8];
   double pivot[3];
 
diff --git a/src/common_io.c b/src/common_io.c
index 0e9c5b6cd51ec64e04995cbc47be64b1f36bc131..f6a4803333581b69671e3adc223b46122ec5364c 100644
--- a/src/common_io.c
+++ b/src/common_io.c
@@ -359,7 +359,9 @@ FILE* prepareXMFfile() {
 
   if (tempFile == NULL) error("Unable to open temporary file.");
 
-  for (int i = 0; fgets(buffer, 1024, tempFile) != NULL && i < counter - 3; i++) {
+  int i = 0;
+  while (fgets(buffer, 1024, tempFile) != NULL && i < counter - 3) {
+    i++;
     fprintf(xmfFile, "%s", buffer);
   }
   fprintf(xmfFile, "\n");
@@ -471,4 +473,90 @@ void writeXMFline(FILE* xmfFile, char* fileName, char* name, long long N,
   fprintf(xmfFile, "</Attribute>\n");
 }
 
+/**
+ * @brief Prepare the DM particles (in gparts) read in for the addition of the
+ * other particle types
+ *
+ * This function assumes that the DM particles are all at the start of the
+ * gparts array
+ *
+ * @param gparts The array of #gpart freshly read in.
+ * @param Ndm The number of DM particles read in.
+ */
+void prepare_dm_gparts(struct gpart* gparts, size_t Ndm) {
+
+  /* Let's give all these gparts a negative id */
+  for (size_t i = 0; i < Ndm; ++i) {
+
+    /* 0 or negative ids are not allowed */
+    if (gparts[i].id <= 0) error("0 or negative ID for DM particle");
+
+    gparts[i].id = -gparts[i].id;
+  }
+}
+
+/**
+ * @brief Copy every #part into the corresponding #gpart and link them.
+ *
+ * This function assumes that the DM particles are all at the start of the
+ * gparts array and adds the hydro particles afterwards
+ *
+ * @param parts The array of #part freshly read in.
+ * @param gparts The array of #gpart freshly read in with all the DM particles
+ *at the start
+ * @param Ngas The number of gas particles read in.
+ * @param Ndm The number of DM particles read in.
+ */
+void duplicate_hydro_gparts(struct part* parts, struct gpart* gparts,
+                            size_t Ngas, size_t Ndm) {
+
+  for (size_t i = 0; i < Ngas; ++i) {
+
+    /* Duplicate the crucial information */
+    gparts[i + Ndm].x[0] = parts[i].x[0];
+    gparts[i + Ndm].x[1] = parts[i].x[1];
+    gparts[i + Ndm].x[2] = parts[i].x[2];
+
+    gparts[i + Ndm].v_full[0] = parts[i].v[0];
+    gparts[i + Ndm].v_full[1] = parts[i].v[1];
+    gparts[i + Ndm].v_full[2] = parts[i].v[2];
+
+    gparts[i + Ndm].mass = parts[i].mass;
+
+    /* Link the particles */
+    gparts[i + Ndm].part = &parts[i];
+    parts[i].gpart = &gparts[i + Ndm];
+  }
+}
+
+/**
+ * @brief Copy every DM #gpart into the dmparts array.
+ *
+ * @param gparts The array of #gpart containing all particles.
+ * @param Ntot The number of #gpart.
+ * @param dmparts The array of #gpart containg DM particles to be filled.
+ * @param Ndm The number of DM particles.
+ */
+void collect_dm_gparts(struct gpart* gparts, size_t Ntot, struct gpart* dmparts,
+                       size_t Ndm) {
+
+  size_t count = 0;
+
+  /* Loop over all gparts */
+  for (size_t i = 0; i < Ntot; ++i) {
+
+    /* And collect the DM ones */
+    if (gparts[i].id < 0) {
+      memcpy(&dmparts[count], &gparts[i], sizeof(struct gpart));
+      dmparts[count].id = -dmparts[count].id;
+      count++;
+    }
+  }
+
+  /* Check that everything is fine */
+  if (count != Ndm)
+    error("Collected the wrong number of dm particles (%zd vs. %zd expected)",
+          count, Ndm);
+}
+
 #endif
diff --git a/src/common_io.h b/src/common_io.h
index c221ad3aaf84deb83c0067ee4ece729b98003430..2623a03f9a25ce0e650dde4f698da6eb49177e26 100644
--- a/src/common_io.h
+++ b/src/common_io.h
@@ -24,6 +24,7 @@
 #include "../config.h"
 
 /* Includes. */
+#include "part.h"
 #include "units.h"
 
 #if defined(HAVE_HDF5)
@@ -55,9 +56,29 @@ enum DATA_IMPORTANCE {
   OPTIONAL = 0
 };
 
+/**
+ * @brief The different particle types present in a GADGET IC file
+ *
+ */
+enum PARTICLE_TYPE {
+  GAS = 0,
+  DM = 1,
+  BOUNDARY = 2,
+  DUMMY = 3,
+  STAR = 4,
+  BH = 5,
+  NUM_PARTICLE_TYPES
+};
+
 hid_t hdf5Type(enum DATA_TYPE type);
 size_t sizeOfType(enum DATA_TYPE type);
 
+void collect_dm_gparts(struct gpart* gparts, size_t Ntot, struct gpart* dmparts,
+                       size_t Ndm);
+void prepare_dm_gparts(struct gpart* gparts, size_t Ndm);
+void duplicate_hydro_gparts(struct part* parts, struct gpart* gparts,
+                            size_t Ngas, size_t Ndm);
+
 void readAttribute(hid_t grp, char* name, enum DATA_TYPE type, void* data);
 
 void writeAttribute(hid_t grp, char* name, enum DATA_TYPE type, void* data,
diff --git a/src/debug.c b/src/debug.c
index 48a0995a5d2992c2b23c7294833309508ee5b59d..4c1434118c98aab7def28d3a53493767d249d774 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -38,6 +38,8 @@
 #error "Invalid choice of SPH variant"
 #endif
 
+#include "./gravity/Default/gravity_debug.h"
+
 /**
  * @brief Looks for the particle with the given id and prints its information to
  *the standard output.
@@ -67,21 +69,20 @@ void printParticle(struct part *parts, struct xpart *xparts, long long int id,
   if (!found) printf("## Particles[???] id=%lld not found\n", id);
 }
 
-void printgParticle(struct gpart *parts, long long int id, size_t N) {
+void printgParticle(struct gpart *gparts, long long int id, size_t N) {
 
   int found = 0;
 
   /* Look for the particle. */
   for (size_t i = 0; i < N; i++)
-    if (parts[i].id == -id || (parts[i].id > 0 && parts[i].part->id == id)) {
-      printf(
-          "## gParticle[%zd]: id=%lld, x=[%.16e,%.16e,%.16e], "
-          "v=[%.3e,%.3e,%.3e], a=[%.3e,%.3e,%.3e], m=%.3e, t_begin=%d, "
-          "t_end=%d\n",
-          i, parts[i].part->id, parts[i].x[0], parts[i].x[1], parts[i].x[2],
-          parts[i].v[0], parts[i].v[1], parts[i].v[2], parts[i].a[0],
-          parts[i].a[1], parts[i].a[2], parts[i].mass, parts[i].ti_begin,
-          parts[i].ti_end);
+    if (gparts[i].id == -id) {
+      printf("## gParticle[%zd] (DM) :\n id=%lld", i, -gparts[i].id);
+      gravity_debug_particle(&gparts[i]);
+      found = 1;
+      break;
+    } else if (gparts[i].id > 0 && gparts[i].part->id == id) {
+      printf("## gParticle[%zd] (hydro) :\n id=%lld", i, gparts[i].id);
+      gravity_debug_particle(&gparts[i]);
       found = 1;
       break;
     }
diff --git a/src/engine.c b/src/engine.c
index 0739609170eceeeae08f1523330e1d7436688a0b..c34214c05b6fb45991208dd78689b58ba5d9731f 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -595,7 +595,8 @@ void engine_exchange_cells(struct engine *e) {
  * @return The number of arrived parts copied to parts and xparts.
  */
 
-int engine_exchange_strays(struct engine *e, int offset, size_t *ind, size_t N) {
+int engine_exchange_strays(struct engine *e, int offset, size_t *ind,
+                           size_t N) {
 
 #ifdef WITH_MPI
 
@@ -793,16 +794,18 @@ void engine_maketasks(struct engine *e) {
         }
       }
 
-  /* Add the gravity mm tasks. */
-  for (int i = 0; i < nr_cells; i++)
-    if (cells[i].gcount > 0) {
-      scheduler_addtask(sched, task_type_grav_mm, task_subtype_none, -1, 0,
-                        &cells[i], NULL, 0);
-      for (int j = i + 1; j < nr_cells; j++)
-        if (cells[j].gcount > 0)
-          scheduler_addtask(sched, task_type_grav_mm, task_subtype_none, -1, 0,
-                            &cells[i], &cells[j], 0);
-    }
+  /* /\* Add the gravity mm tasks. *\/ */
+  /* for (int i = 0; i < nr_cells; i++) */
+  /*   if (cells[i].gcount > 0) { */
+  /*     scheduler_addtask(sched, task_type_grav_mm, task_subtype_none, -1, 0,
+   */
+  /*                       &cells[i], NULL, 0); */
+  /*     for (int j = i + 1; j < nr_cells; j++) */
+  /*       if (cells[j].gcount > 0) */
+  /*         scheduler_addtask(sched, task_type_grav_mm, task_subtype_none, -1,
+   * 0, */
+  /*                           &cells[i], &cells[j], 0); */
+  /* } */
 
   /* Split the tasks. */
   scheduler_splittasks(sched);
@@ -816,21 +819,24 @@ void engine_maketasks(struct engine *e) {
     error("Failed to allocate cell-task links.");
   e->nr_links = 0;
 
-  /* Add the gravity up/down tasks at the top-level cells and push them down. */
-  for (int k = 0; k < nr_cells; k++)
-    if (cells[k].nodeID == nodeID && cells[k].gcount > 0) {
-
-      /* Create tasks at top level. */
-      struct task *up =
-          scheduler_addtask(sched, task_type_grav_up, task_subtype_none, 0, 0,
-                            &cells[k], NULL, 0);
-      struct task *down =
-          scheduler_addtask(sched, task_type_grav_down, task_subtype_none, 0, 0,
-                            &cells[k], NULL, 0);
-
-      /* Push tasks down the cell hierarchy. */
-      engine_addtasks_grav(e, &cells[k], up, down);
-    }
+  /* /\* Add the gravity up/down tasks at the top-level cells and push them
+   * down. *\/ */
+  /* for (int k = 0; k < nr_cells; k++) */
+  /*   if (cells[k].nodeID == nodeID && cells[k].gcount > 0) { */
+
+  /*     /\* Create tasks at top level. *\/ */
+  /*     struct task *up = */
+  /*         scheduler_addtask(sched, task_type_grav_up, task_subtype_none, 0,
+   * 0, */
+  /*                           &cells[k], NULL, 0); */
+  /*     struct task *down = */
+  /*         scheduler_addtask(sched, task_type_grav_down, task_subtype_none, 0,
+   * 0, */
+  /*                           &cells[k], NULL, 0); */
+
+  /*     /\* Push tasks down the cell hierarchy. *\/ */
+  /*     engine_addtasks_grav(e, &cells[k], up, down); */
+  /*   } */
 
   /* Count the number of tasks associated with each cell and
      store the density tasks in each cell, and make each sort
@@ -878,17 +884,17 @@ void engine_maketasks(struct engine *e) {
       }
     }
 
-    /* Link gravity multipole tasks to the up/down tasks. */
-    if (t->type == task_type_grav_mm ||
-        (t->type == task_type_sub && t->subtype == task_subtype_grav)) {
-      atomic_inc(&t->ci->nr_tasks);
-      scheduler_addunlock(sched, t->ci->grav_up, t);
-      scheduler_addunlock(sched, t, t->ci->grav_down);
-      if (t->cj != NULL && t->ci->grav_up != t->cj->grav_up) {
-        scheduler_addunlock(sched, t->cj->grav_up, t);
-        scheduler_addunlock(sched, t, t->cj->grav_down);
-      }
-    }
+    /* /\* Link gravity multipole tasks to the up/down tasks. *\/ */
+    /* if (t->type == task_type_grav_mm || */
+    /*     (t->type == task_type_sub && t->subtype == task_subtype_grav)) { */
+    /*   atomic_inc(&t->ci->nr_tasks); */
+    /*   scheduler_addunlock(sched, t->ci->grav_up, t); */
+    /*   scheduler_addunlock(sched, t, t->ci->grav_down); */
+    /*   if (t->cj != NULL && t->ci->grav_up != t->cj->grav_up) { */
+    /*     scheduler_addunlock(sched, t->cj->grav_up, t); */
+    /*     scheduler_addunlock(sched, t, t->cj->grav_down); */
+    /*   } */
+    /* } */
   }
 
   /* Append a ghost task to each cell, and add kick tasks to the
@@ -1165,8 +1171,8 @@ void engine_print_task_counts(struct engine *e) {
     else
       counts[task_type_count] += 1;
 #ifdef WITH_MPI
-  printf("[%04i] %s engine_print_task_counts: task counts are [ %s=%i", e->nodeID,
-         clocks_get_timesincestart(), taskID_names[0], counts[0]);
+  printf("[%04i] %s engine_print_task_counts: task counts are [ %s=%i",
+         e->nodeID, clocks_get_timesincestart(), taskID_names[0], counts[0]);
 #else
   printf("%s engine_print_task_counts: task counts are [ %s=%i",
          clocks_get_timesincestart(), taskID_names[0], counts[0]);
diff --git a/src/gravity.h b/src/gravity.h
index d5361095c744e2df069ccaf99447dcd58e10dcd6..f737a0ab882592cffb974f66ccbb62fa3d16d408 100644
--- a/src/gravity.h
+++ b/src/gravity.h
@@ -24,6 +24,6 @@
 /* So far only one model here */
 /* Straight-forward import */
 #include "./gravity/Default/gravity.h"
-#include "./gravity/Default/runner_iact_grav.h"
+#include "./gravity/Default/gravity_iact.h"
 
 #endif
diff --git a/src/gravity/Default/gravity_debug.h b/src/gravity/Default/gravity_debug.h
new file mode 100644
index 0000000000000000000000000000000000000000..98e0c40a5700b4da70f27fb0955592bb5d2287c3
--- /dev/null
+++ b/src/gravity/Default/gravity_debug.h
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Coypright (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/>.
+ *
+ ******************************************************************************/
+
+__attribute__((always_inline))
+    INLINE static void gravity_debug_particle(struct gpart* p) {
+  printf(
+      "x=[%.3e,%.3e,%.3e], "
+      "v_full=[%.3e,%.3e,%.3e] \n a=[%.3e,%.3e,%.3e],\n "
+      "mass=%.3e t_begin=%d, t_end=%d\n",
+      p->x[0], p->x[1], p->x[2], p->v_full[0], p->v_full[1], p->v_full[2],
+      p->a[0], p->a[1], p->a[2], p->mass, p->ti_begin, p->ti_end);
+}
diff --git a/src/gravity/Default/runner_iact_grav.h b/src/gravity/Default/gravity_iact.h
similarity index 100%
rename from src/gravity/Default/runner_iact_grav.h
rename to src/gravity/Default/gravity_iact.h
diff --git a/src/gravity/Default/gravity_io.h b/src/gravity/Default/gravity_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..d707d69631e65eed8ad21a7fa9601c07d3c71263
--- /dev/null
+++ b/src/gravity/Default/gravity_io.h
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Coypright (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/>.
+ *
+ ******************************************************************************/
+
+/**
+ * @brief Read dark matter particles from HDF5.
+ *
+ * @param h_grp The HDF5 group in which to read the arrays.
+ * @param N The number of particles on that MPI rank.
+ * @param N_total The total number of particles (only used in MPI mode)
+ * @param offset The offset of the particles for this MPI rank (only used in MPI
+ *mode)
+ * @param gparts The particle array
+ *
+ */
+__attribute__((always_inline)) INLINE static void darkmatter_read_particles(
+    hid_t h_grp, int N, long long N_total, long long offset,
+    struct gpart* gparts) {
+
+  /* Read arrays */
+  readArray(h_grp, "Coordinates", DOUBLE, N, 3, gparts, N_total, offset, x,
+            COMPULSORY);
+  readArray(h_grp, "Masses", FLOAT, N, 1, gparts, N_total, offset, mass,
+            COMPULSORY);
+  readArray(h_grp, "Velocities", FLOAT, N, 3, gparts, N_total, offset, v_full,
+            COMPULSORY);
+  readArray(h_grp, "ParticleIDs", ULONGLONG, N, 1, gparts, N_total, offset, id,
+            COMPULSORY);
+}
+
+/**
+ * @brief Writes the different particles to the HDF5 file
+ *
+ * @param h_grp The HDF5 group in which to write the arrays.
+ * @param fileName The name of the file (unsued in MPI mode).
+ * @param xmfFile The XMF file to write to (unused in MPI mode).
+ * @param Ndm The number of DM particles on that MPI rank.
+ * @param Ndm_total The total number of g-particles (only used in MPI mode)
+ * @param mpi_rank The MPI rank of this node (only used in MPI mode)
+ * @param offset The offset of the particles for this MPI rank (only used in MPI
+ *mode)
+ * @param gparts The #gpart array
+ * @param us The unit system to use
+ *
+ */
+__attribute__((always_inline)) INLINE static void darkmatter_write_particles(
+    hid_t h_grp, char* fileName, FILE* xmfFile, int Ndm, long long Ndm_total,
+    int mpi_rank, long long offset, struct gpart* gparts,
+    struct UnitSystem* us) {
+
+  /* Write arrays */
+  writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, Ndm, 3, gparts,
+             Ndm_total, mpi_rank, offset, x, us, UNIT_CONV_LENGTH);
+  writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, Ndm, 1, gparts,
+             Ndm_total, mpi_rank, offset, mass, us, UNIT_CONV_MASS);
+  writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, Ndm, 3, gparts,
+             Ndm_total, mpi_rank, offset, v_full, us, UNIT_CONV_SPEED);
+  writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, Ndm, 1, gparts,
+             Ndm_total, mpi_rank, offset, id, us, UNIT_CONV_NO_UNITS);
+}
diff --git a/src/gravity/Default/gravity_part.h b/src/gravity/Default/gravity_part.h
index 17262f9d413b1e801b71b456eb4e6baeb925febc..7ce7b81892582f2a90f7dd07f7f244c0d4ed8afb 100644
--- a/src/gravity/Default/gravity_part.h
+++ b/src/gravity/Default/gravity_part.h
@@ -26,7 +26,7 @@ struct gpart {
   double x[3];
 
   /* Particle velocity. */
-  float v[3];
+  float v_full[3];
 
   /* Particle acceleration. */
   float a[3];
@@ -44,7 +44,7 @@ struct gpart {
   union {
 
     /* Particle ID. */
-    size_t id;
+    long long id;
 
     /* Pointer to corresponding SPH part. */
     struct part* part;
diff --git a/src/gravity_io.h b/src/gravity_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..6276e50473de64abd1014bdb36a63a14e02ca8cf
--- /dev/null
+++ b/src/gravity_io.h
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Coypright (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_GRAVITY_IO_H
+#define SWIFT_GRAVITY_IO_H
+
+#include "./const.h"
+
+#include "./gravity/Default/gravity_io.h"
+
+#endif /* SWIFT_GRAVITY_IO_H */
diff --git a/src/hydro/Default/hydro_part.h b/src/hydro/Default/hydro_part.h
index 4dbc0388ac20cd7f354007e2e80aa6fccccdc5ad..60453d0c7995f7af2a3166502a24aa590873a043 100644
--- a/src/hydro/Default/hydro_part.h
+++ b/src/hydro/Default/hydro_part.h
@@ -111,7 +111,7 @@ struct part {
   float mass;
 
   /* Particle ID. */
-  unsigned long long id;
+  long long id;
 
   /* Pointer to corresponding gravity part. */
   struct gpart* gpart;
diff --git a/src/hydro/Gadget2/hydro_part.h b/src/hydro/Gadget2/hydro_part.h
index 298cfc5ac1d801f03f7ba104a819fd3de531d55c..05754d07dd70bed071e99c86b95eb17eb2194012 100644
--- a/src/hydro/Gadget2/hydro_part.h
+++ b/src/hydro/Gadget2/hydro_part.h
@@ -104,7 +104,7 @@ struct part {
   float div_v;
 
   /* Particle ID. */
-  unsigned long long id;
+  long long id;
 
   /* Pointer to corresponding gravity part. */
   struct gpart* gpart;
diff --git a/src/hydro/Minimal/hydro_part.h b/src/hydro/Minimal/hydro_part.h
index 8875e737c6f3c0ab0b7a390b56e9b946c145fc1b..173397ef2c72ee99f4d10742f3645afd1e706218 100644
--- a/src/hydro/Minimal/hydro_part.h
+++ b/src/hydro/Minimal/hydro_part.h
@@ -101,7 +101,7 @@ struct part {
     } force;
   };
 
-  unsigned long long id; /*!< Particle unique ID. */
+  long long id; /*!< Particle unique ID. */
 
   struct gpart* gpart; /*!< Pointer to corresponding gravity part. */
 
diff --git a/src/map.c b/src/map.c
index dcaa53465767d414cc54fe05940069ae5ff06d77..da13fbfb4ac00ed58184f7fe818826c82265a1de 100644
--- a/src/map.c
+++ b/src/map.c
@@ -96,14 +96,12 @@ void map_cells_plot(struct cell *c, void *data) {
 
 void map_cellcheck(struct cell *c, void *data) {
 
-  int k, *count = (int *)data;
-  struct part *p;
-
+  int *count = (int *)data;
   __sync_fetch_and_add(count, c->count);
 
   /* Loop over all parts and check if they are in the cell. */
-  for (k = 0; k < c->count; k++) {
-    p = &c->parts[k];
+  for (int k = 0; k < c->count; k++) {
+    struct part *p = &c->parts[k];
     if (p->x[0] < c->loc[0] || p->x[1] < c->loc[1] || p->x[2] < c->loc[2] ||
         p->x[0] > c->loc[0] + c->h[0] || p->x[1] > c->loc[1] + c->h[1] ||
         p->x[2] > c->loc[2] + c->h[2]) {
@@ -115,6 +113,21 @@ void map_cellcheck(struct cell *c, void *data) {
       error("particle out of bounds!");
     }
   }
+
+  /* Loop over all gparts and check if they are in the cell. */
+  for (int k = 0; k < c->gcount; k++) {
+    struct gpart *p = &c->gparts[k];
+    if (p->x[0] < c->loc[0] || p->x[1] < c->loc[1] || p->x[2] < c->loc[2] ||
+        p->x[0] > c->loc[0] + c->h[0] || p->x[1] > c->loc[1] + c->h[1] ||
+        p->x[2] > c->loc[2] + c->h[2]) {
+      printf(
+          "map_cellcheck: g-particle at [ %.16e %.16e %.16e ] outside of cell "
+          "[ %.16e %.16e %.16e ] - [ %.16e %.16e %.16e ].\n",
+          p->x[0], p->x[1], p->x[2], c->loc[0], c->loc[1], c->loc[2],
+          c->loc[0] + c->h[0], c->loc[1] + c->h[1], c->loc[2] + c->h[2]);
+      error("g-particle out of bounds!");
+    }
+  }
 }
 
 /**
diff --git a/src/parallel_io.c b/src/parallel_io.c
index 70650d48020cd75eedfad121804dd91923660b08..cffa99a0fd75566ec3e850076d15e104504eeb40 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -357,7 +357,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
  *
  */
 void read_ic_parallel(char* fileName, double dim[3], struct part** parts,
-                      int* N, int* periodic, int mpi_rank, int mpi_size,
+                      size_t* N, int* periodic, int mpi_rank, int mpi_size,
                       MPI_Comm comm, MPI_Info info) {
   hid_t h_file = 0, h_grp = 0;
   double boxSize[3] = {
diff --git a/src/parallel_io.h b/src/parallel_io.h
index 5ee2714a18dbabdd5fc8c07c0b444e04a87ad4f8..a0589944ec845c712abde1e64e305980748db0e7 100644
--- a/src/parallel_io.h
+++ b/src/parallel_io.h
@@ -32,7 +32,7 @@
 #if defined(HAVE_HDF5) && defined(WITH_MPI) && defined(HAVE_PARALLEL_HDF5)
 
 void read_ic_parallel(char* fileName, double dim[3], struct part** parts,
-                      int* N, int* periodic, int mpi_rank, int mpi_size,
+                      size_t* N, int* periodic, int mpi_rank, int mpi_size,
                       MPI_Comm comm, MPI_Info info);
 
 void write_output_parallel(struct engine* e, struct UnitSystem* us,
diff --git a/src/part.h b/src/part.h
index 168e80b68bb211d1d773f1f80f1fa9cc757edfcb..865403e8c2c157dc5a8ff7a32bc41be676d7919b 100644
--- a/src/part.h
+++ b/src/part.h
@@ -35,6 +35,7 @@
 
 /* Some constants. */
 #define part_align 64
+#define gpart_align 32
 #define xpart_align 32
 
 /* Import the right particle definition */
diff --git a/src/scheduler.c b/src/scheduler.c
index 6c4c7c75a67dc775d04fbddb5e2b479af716963d..722e344b5a86b5fbdc42c7038fd3cb00e44b2ee8 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -534,7 +534,7 @@ void scheduler_splittasks(struct scheduler *s) {
         else if (ci->split) {
 
           /* Make a single sub-task? */
-          if (scheduler_dosub && ci->count < space_subsize / ci->count) {
+          if (scheduler_dosub && ci->gcount < space_subsize / ci->gcount) {
 
             t->type = task_type_sub;
             t->subtype = task_subtype_grav;
@@ -582,7 +582,7 @@ void scheduler_splittasks(struct scheduler *s) {
       else {
 
         /* Make a sub-task? */
-        if (scheduler_dosub && ci->count < space_subsize / cj->count) {
+        if (scheduler_dosub && ci->gcount < space_subsize / cj->gcount) {
 
           t->type = task_type_sub;
           t->subtype = task_subtype_grav;
diff --git a/src/serial_io.c b/src/serial_io.c
index b56d8668b6f4712890120ccbca6e322565ad1775..8e63db5cfad3a3b50fc7e350bbac6ce09708230a 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -410,9 +410,9 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
  * Calls #error() if an error occurs.
  *
  */
-void read_ic_serial(char* fileName, double dim[3], struct part** parts, int* N,
-                    int* periodic, int mpi_rank, int mpi_size, MPI_Comm comm,
-                    MPI_Info info) {
+void read_ic_serial(char* fileName, double dim[3], struct part** parts,
+                    size_t* N, int* periodic, int mpi_rank, int mpi_size,
+                    MPI_Comm comm, MPI_Info info) {
   hid_t h_file = 0, h_grp = 0;
   double boxSize[3] = {0.0, -1.0, -1.0};
   /* GADGET has only cubic boxes (in cosmological mode) */
diff --git a/src/serial_io.h b/src/serial_io.h
index e5ecca9c8cbafbbaf2e555c5c216b494e25cc922..95f09f5977a97a359e978db7a1b71b02030d6a14 100644
--- a/src/serial_io.h
+++ b/src/serial_io.h
@@ -31,9 +31,9 @@
 
 #if defined(HAVE_HDF5) && defined(WITH_MPI) && !defined(HAVE_PARALLEL_HDF5)
 
-void read_ic_serial(char* fileName, double dim[3], struct part** parts, int* N,
-                    int* periodic, int mpi_rank, int mpi_size, MPI_Comm comm,
-                    MPI_Info info);
+void read_ic_serial(char* fileName, double dim[3], struct part** parts,
+                    size_t* N, int* periodic, int mpi_rank, int mpi_size,
+                    MPI_Comm comm, MPI_Info info);
 
 void write_output_serial(struct engine* e, struct UnitSystem* us, int mpi_rank,
                          int mpi_size, MPI_Comm comm, MPI_Info info);
diff --git a/src/single_io.c b/src/single_io.c
index f3225ecf487d223c3bea560cbae626a03da36928..59686a68b5d9e5ea41267ba7b3aad9391862fae4 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -39,6 +39,9 @@
 #include "common_io.h"
 #include "error.h"
 
+#define FILENAME_BUFFER_SIZE 150
+#define PARTICLE_GROUP_BUFFER_SIZE 20
+
 /*-----------------------------------------------------------------------------
  * Routines reading an IC file
  *-----------------------------------------------------------------------------*/
@@ -166,7 +169,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
   char* temp_c = 0;
   hsize_t shape[2];
   hsize_t chunk_shape[2];
-  char buffer[150];
+  char buffer[FILENAME_BUFFER_SIZE];
 
   /* message("Writing '%s' array...", name); */
 
@@ -201,7 +204,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
 
   /* Make sure the chunks are not larger than the dataset */
   if (chunk_shape[0] > N) chunk_shape[0] = N;
-
+  
   /* Change shape of data space */
   h_err = H5Sset_extent_simple(h_space, rank, shape, NULL);
   if (h_err < 0) {
@@ -302,14 +305,18 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
 
 /* Import the right hydro definition */
 #include "hydro_io.h"
+/* Import the right gravity definition */
+#include "gravity_io.h"
 
 /**
  * @brief Reads an HDF5 initial condition file (GADGET-3 type)
  *
  * @param fileName The file to read.
- * @param dim (output) The dimension of the volume read from the file.
- * @param parts (output) The array of #part read from the file.
- * @param N (output) The number of particles read from the file.
+ * @param dim (output) The dimension of the volume.
+ * @param parts (output) Array of Gas particles.
+ * @param gparts (output) Array of DM particles.
+ * @param Ngas (output) number of Gas particles read.
+ * @param Ngparts (output) The number of DM particles read.
  * @param periodic (output) 1 if the volume is periodic, 0 if not.
  *
  * Opens the HDF5 file fileName and reads the particles contained
@@ -322,13 +329,15 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name,
  * Calls #error() if an error occurs.
  *
  */
-void read_ic_single(char* fileName, double dim[3], struct part** parts, int* N,
+void read_ic_single(char* fileName, double dim[3], struct part** parts,
+                    struct gpart** gparts, size_t* Ngas, size_t* Ngparts,
                     int* periodic) {
   hid_t h_file = 0, h_grp = 0;
-  double boxSize[3] = {0.0, -1.0, -1.0};
   /* GADGET has only cubic boxes (in cosmological mode) */
-  int numParticles[6] = {0};
-  /* GADGET has 6 particle types. We only keep the type 0*/
+  double boxSize[3] = {0.0, -1.0, -1.0};
+  /* GADGET has 6 particle types. We only keep the type 0 & 1 for now...*/
+  int numParticles[NUM_PARTICLE_TYPES] = {0};
+  size_t Ndm;
 
   /* Open file */
   /* message("Opening file '%s' as IC.", fileName); */
@@ -357,35 +366,82 @@ void read_ic_single(char* fileName, double dim[3], struct part** parts, int* N,
   readAttribute(h_grp, "BoxSize", DOUBLE, boxSize);
   readAttribute(h_grp, "NumPart_Total", UINT, numParticles);
 
-  *N = numParticles[0];
+  *Ngas = numParticles[0];
+  Ndm = numParticles[1];
   dim[0] = boxSize[0];
   dim[1] = (boxSize[1] < 0) ? boxSize[0] : boxSize[1];
   dim[2] = (boxSize[2] < 0) ? boxSize[0] : boxSize[2];
 
   /* message("Found %d particles in a %speriodic box of size [%f %f %f].",  */
-  /* 	 *N, (periodic ? "": "non-"), dim[0], dim[1], dim[2]); */
+  /* 	  *N, (periodic ? "": "non-"), dim[0], dim[1], dim[2]);  */
 
   /* Close header */
   H5Gclose(h_grp);
 
-  /* Allocate memory to store particles */
-  if (posix_memalign((void*)parts, part_align, *N * sizeof(struct part)) != 0)
-    error("Error while allocating memory for particles");
-  bzero(*parts, *N * sizeof(struct part));
+  /* Total number of particles */
+  *Ngparts = *Ngas + Ndm;
+
+  /* Allocate memory to store SPH particles */
+  if (posix_memalign((void*)parts, part_align, *Ngas * sizeof(struct part)) !=
+      0)
+    error("Error while allocating memory for SPH particles");
+  bzero(*parts, *Ngas * sizeof(struct part));
+
+  /* Allocate memory to store all particles */
+  if (posix_memalign((void*)gparts, gpart_align,
+                     *Ngparts * sizeof(struct gpart)) != 0)
+    error("Error while allocating memory for gravity particles");
+  bzero(*gparts, *Ngparts * sizeof(struct gpart));
 
   /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) /
    * (1024.*1024.)); */
 
   /* Open SPH particles group */
   /* message("Reading particle arrays..."); */
-  h_grp = H5Gopen(h_file, "/PartType0", H5P_DEFAULT);
-  if (h_grp < 0) error("Error while opening particle group.\n");
+  message("BoxSize = %lf", dim[0]);
+  message("NumPart = [%zd, %zd] Total = %zd", *Ngas, Ndm, *Ngparts);
+
+  /* Loop over all particle types */
+  for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ptype++) {
+
+    /* Don't do anything if no particle of this kind */
+    if (numParticles[ptype] == 0) continue;
+
+    /* Open the particle group in the file */
+    char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE];
+    snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d",
+             ptype);
+    h_grp = H5Gopen(h_file, partTypeGroupName, H5P_DEFAULT);
+    if (h_grp < 0) {
+      error("Error while opening particle group %s.", partTypeGroupName);
+    }
 
-  /* Read particle fields into the particle structure */
-  hydro_read_particles(h_grp, *N, *N, 0, *parts);
+    /* message("Group %s found - reading...", partTypeGroupName); */
 
-  /* Close particle group */
-  H5Gclose(h_grp);
+    /* Read particle fields into the particle structure */
+    switch (ptype) {
+
+      case GAS:
+        hydro_read_particles(h_grp, *Ngas, *Ngas, 0, *parts);
+        break;
+
+      case DM:
+        darkmatter_read_particles(h_grp, Ndm, Ndm, 0, *gparts);
+        break;
+
+      default:
+        error("Particle Type %d not yet supported. Aborting", ptype);
+    }
+
+    /* Close particle group */
+    H5Gclose(h_grp);
+  }
+
+  /* Prepare the DM particles */
+  prepare_dm_gparts(*gparts, Ndm);
+
+  /* Now duplicate the hydro particle into gparts */
+  duplicate_hydro_gparts(*parts, *gparts, *Ngas, Ndm);
 
   /* message("Done Reading particles..."); */
 
@@ -409,28 +465,35 @@ void read_ic_single(char* fileName, double dim[3], struct part** parts, int* N,
  */
 void write_output_single(struct engine* e, struct UnitSystem* us) {
 
-  hid_t h_file = 0, h_grp = 0, h_grpsph = 0;
-  int N = e->s->nr_parts;
+  hid_t h_file = 0, h_grp = 0;
+  const size_t Ngas = e->s->nr_parts;
+  const size_t Ntot = e->s->nr_gparts;
   int periodic = e->s->periodic;
-  int numParticles[6] = {N, 0};
-  int numParticlesHighWord[6] = {0};
   int numFiles = 1;
   struct part* parts = e->s->parts;
-  FILE* xmfFile = 0;
+  struct gpart* gparts = e->s->gparts;
+  struct gpart* dmparts = NULL;
   static int outputCount = 0;
 
+  /* Number of particles of each type */
+  const size_t Ndm = Ntot - Ngas;
+  int numParticles[NUM_PARTICLE_TYPES] = /* Gadget-2 convention here */
+      {Ngas, Ndm, 0};                    /* Could use size_t instead */
+  int numParticlesHighWord[NUM_PARTICLE_TYPES] = {0};
+
   /* File name */
-  char fileName[200];
-  sprintf(fileName, "output_%03i.hdf5", outputCount);
+  char fileName[FILENAME_BUFFER_SIZE];
+  snprintf(fileName, FILENAME_BUFFER_SIZE, "output_%03i.hdf5", outputCount);
 
   /* First time, we need to create the XMF file */
   if (outputCount == 0) createXMFfile();
 
   /* Prepare the XMF file for the new entry */
+  FILE* xmfFile = 0;
   xmfFile = prepareXMFfile();
 
   /* Write the part corresponding to this specific output */
-  writeXMFheader(xmfFile, N, fileName, e->time);
+  writeXMFheader(xmfFile, Ngas, fileName, e->time);
 
   /* Open file */
   /* message("Opening file '%s'.", fileName); */
@@ -458,17 +521,20 @@ void write_output_single(struct engine* e, struct UnitSystem* us) {
 
   /* Print the relevant information and print status */
   writeAttribute(h_grp, "BoxSize", DOUBLE, e->s->dim, 3);
-  writeAttribute(h_grp, "NumPart_ThisFile", UINT, numParticles, 6);
+  writeAttribute(h_grp, "NumPart_ThisFile", UINT, numParticles,
+                 NUM_PARTICLE_TYPES);
   double dblTime = e->time;
   writeAttribute(h_grp, "Time", DOUBLE, &dblTime, 1);
 
   /* GADGET-2 legacy values */
-  writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, 6);
+  writeAttribute(h_grp, "NumPart_Total", UINT, numParticles,
+                 NUM_PARTICLE_TYPES);
   writeAttribute(h_grp, "NumPart_Total_HighWord", UINT, numParticlesHighWord,
-                 6);
-  double MassTable[6] = {0., 0., 0., 0., 0., 0.};
-  writeAttribute(h_grp, "MassTable", DOUBLE, MassTable, 6);
-  writeAttribute(h_grp, "Flag_Entropy_ICs", UINT, numParticlesHighWord, 6);
+                 NUM_PARTICLE_TYPES);
+  double MassTable[NUM_PARTICLE_TYPES] = {0., 0., 0., 0., 0., 0.};
+  writeAttribute(h_grp, "MassTable", DOUBLE, MassTable, NUM_PARTICLE_TYPES);
+  writeAttribute(h_grp, "Flag_Entropy_ICs", UINT, numParticlesHighWord,
+                 NUM_PARTICLE_TYPES);
   writeAttribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1);
 
   /* Close header */
@@ -478,25 +544,65 @@ void write_output_single(struct engine* e, struct UnitSystem* us) {
   writeCodeDescription(h_file);
 
   /* Print the SPH parameters */
-  h_grpsph = H5Gcreate(h_file, "/SPH", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grpsph < 0) error("Error while creating SPH group");
-  writeSPHflavour(h_grpsph);
-  H5Gclose(h_grpsph);
+  h_grp = H5Gcreate(h_file, "/SPH", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  if (h_grp < 0) error("Error while creating SPH group");
+  writeSPHflavour(h_grp);
+  H5Gclose(h_grp);
 
   /* Print the system of Units */
   writeUnitSystem(h_file, us);
 
-  /* Create SPH particles group */
-  /* message("Writing particle arrays..."); */
-  h_grp =
-      H5Gcreate(h_file, "/PartType0", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
-  if (h_grp < 0) error("Error while creating particle group.\n");
+  /* Loop over all particle types */
+  for (int ptype = 0; ptype < NUM_PARTICLE_TYPES; ptype++) {
 
-  /* Write particle fields from the particle structure */
-  hydro_write_particles(h_grp, fileName, xmfFile, N, N, 0, 0, parts, us);
+    /* Don't do anything if no particle of this kind */
+    if (numParticles[ptype] == 0) continue;
 
-  /* Close particle group */
-  H5Gclose(h_grp);
+    /* Open the particle group in the file */
+    char partTypeGroupName[PARTICLE_GROUP_BUFFER_SIZE];
+    snprintf(partTypeGroupName, PARTICLE_GROUP_BUFFER_SIZE, "/PartType%d",
+             ptype);
+    h_grp = H5Gcreate(h_file, partTypeGroupName, H5P_DEFAULT, H5P_DEFAULT,
+                      H5P_DEFAULT);
+    if (h_grp < 0) {
+      error("Error while creating particle group.\n");
+    }
+
+    /* message("Writing particle arrays..."); */
+
+    /* Write particle fields from the particle structure */
+    switch (ptype) {
+
+      case GAS:
+        hydro_write_particles(h_grp, fileName, xmfFile, Ngas, Ngas, 0, 0, parts,
+                              us);
+        break;
+
+      case DM:
+        /* Allocate temporary array */
+        if (posix_memalign((void*)&dmparts, gpart_align,
+                           Ndm * sizeof(struct gpart)) != 0)
+          error("Error while allocating temporart memory for DM particles");
+        bzero(dmparts, Ndm * sizeof(struct gpart));
+
+        /* Collect the DM particles from gpart */
+        collect_dm_gparts(gparts, Ntot, dmparts, Ndm);
+
+        /* Write DM particles */
+        darkmatter_write_particles(h_grp, fileName, xmfFile, Ndm, Ndm, 0, 0,
+                                   dmparts, us);
+
+        /* Free temporary array */
+        free(dmparts);
+        break;
+
+      default:
+        error("Particle Type %d not yet supported. Aborting", ptype);
+    }
+
+    /* Close particle group */
+    H5Gclose(h_grp);
+  }
 
   /* Write LXMF file descriptor */
   writeXMFfooter(xmfFile);
diff --git a/src/single_io.h b/src/single_io.h
index f6689901106a2cd5d85a873d4047e1d21edd3547..c5250280e82e1801b2a4a6136d404d09093dd0ec 100644
--- a/src/single_io.h
+++ b/src/single_io.h
@@ -26,7 +26,8 @@
 
 #if defined(HAVE_HDF5) && !defined(WITH_MPI)
 
-void read_ic_single(char* fileName, double dim[3], struct part** parts, int* N,
+void read_ic_single(char* fileName, double dim[3], struct part** parts,
+                    struct gpart** gparts, size_t* Ngas, size_t* Ndm,
                     int* periodic);
 
 void write_output_single(struct engine* e, struct UnitSystem* us);
diff --git a/src/space.c b/src/space.c
index 5938101d94b17097277d7fc06a1cd4d3c1181727..fa2541c2872c38f5000e78ef2802d9a4f719f9fc 100644
--- a/src/space.c
+++ b/src/space.c
@@ -308,11 +308,6 @@ void space_regrid(struct space *s, double cell_max, int verbose) {
 
 void space_rebuild(struct space *s, double cell_max, int verbose) {
 
-  int j, k, cdim[3], nr_parts = s->nr_parts, nr_gparts = s->nr_gparts;
-  struct cell *restrict c, *restrict cells;
-  struct part *restrict p;
-  size_t *ind;
-  double ih[3], dim[3];
   ticks tic = getticks();
 
   /* Be verbose about this. */
@@ -320,13 +315,13 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
 
   /* Re-grid if necessary, or just re-set the cell data. */
   space_regrid(s, cell_max, verbose);
-  cells = s->cells;
 
-  /* Run through the particles and get their cell index. */
-  // tic = getticks();
-  const size_t ind_size = s->size_parts;
-  if ((ind = (size_t *)malloc(sizeof(size_t) * ind_size)) == NULL)
-    error("Failed to allocate temporary particle indices.");
+  int nr_parts = s->nr_parts;
+  int nr_gparts = s->nr_gparts;
+  struct cell *restrict cells = s->cells;
+
+  double ih[3], dim[3];
+  int cdim[3];
   ih[0] = s->ih[0];
   ih[1] = s->ih[1];
   ih[2] = s->ih[2];
@@ -336,9 +331,16 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
   cdim[0] = s->cdim[0];
   cdim[1] = s->cdim[1];
   cdim[2] = s->cdim[2];
-  for (k = 0; k < nr_parts; k++) {
-    p = &s->parts[k];
-    for (j = 0; j < 3; j++)
+
+  /* Run through the particles and get their cell index. */
+  // tic = getticks();
+  const size_t ind_size = s->size_parts;
+  size_t *ind;
+  if ((ind = (size_t *)malloc(sizeof(size_t) * ind_size)) == NULL)
+    error("Failed to allocate temporary particle indices.");
+  for (int k = 0; k < nr_parts; k++) {
+    struct part *restrict p = &s->parts[k];
+    for (int j = 0; j < 3; j++)
       if (p->x[j] < 0.0)
         p->x[j] += dim[j];
       else if (p->x[j] >= dim[j])
@@ -352,8 +354,8 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
 
 #ifdef WITH_MPI
   /* Move non-local parts to the end of the list. */
-  int nodeID = s->e->nodeID;
-  for (k = 0; k < nr_parts; k++)
+  const int nodeID = s->e->nodeID;
+  for (int k = 0; k < nr_parts; k++)
     if (cells[ind[k]].nodeID != nodeID) {
       cells[ind[k]].count -= 1;
       nr_parts -= 1;
@@ -385,8 +387,8 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
   }
 
   /* Assign each particle to its cell. */
-  for (k = nr_parts; k < s->nr_parts; k++) {
-    p = &s->parts[k];
+  for (int k = nr_parts; k < s->nr_parts; k++) {
+    struct part *p = &s->parts[k];
     ind[k] =
         cell_getid(cdim, p->x[0] * ih[0], p->x[1] * ih[1], p->x[2] * ih[2]);
     cells[ind[k]].count += 1;
@@ -401,7 +403,7 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
   space_parts_sort(s, ind, nr_parts, 0, s->nr_cells - 1, verbose);
 
   /* Re-link the gparts. */
-  for (k = 0; k < nr_parts; k++)
+  for (int k = 0; k < nr_parts; k++)
     if (s->parts[k].gpart != NULL) s->parts[k].gpart->part = &s->parts[k];
 
   /* Verify space_sort_struct. */
@@ -419,41 +421,88 @@ void space_rebuild(struct space *s, double cell_max, int verbose) {
 
   /* Run through the gravity particles and get their cell index. */
   // tic = getticks();
-  if ((ind = (size_t *)malloc(sizeof(size_t) * s->size_gparts)) == NULL)
-    error("Failed to allocate temporary particle indices.");
-  for (k = 0; k < nr_gparts; k++) {
+  const size_t gind_size = s->size_gparts;
+  size_t *gind;
+  if ((gind = (size_t *)malloc(sizeof(size_t) * gind_size)) == NULL)
+    error("Failed to allocate temporary g-particle indices.");
+  for (int k = 0; k < nr_gparts; k++) {
     struct gpart *gp = &s->gparts[k];
-    for (j = 0; j < 3; j++)
+    for (int j = 0; j < 3; j++)
       if (gp->x[j] < 0.0)
         gp->x[j] += dim[j];
       else if (gp->x[j] >= dim[j])
         gp->x[j] -= dim[j];
-    ind[k] =
+    gind[k] =
         cell_getid(cdim, gp->x[0] * ih[0], gp->x[1] * ih[1], gp->x[2] * ih[2]);
-    cells[ind[k]].gcount++;
+    cells[gind[k]].gcount++;
   }
-  // message( "getting particle indices took %.3f %s." ,
-  // clocks_from_ticks(getticks() - tic), clocks_getunit());
+// message( "getting particle indices took %.3f %s." ,
+// clocks_from_ticks(getticks() - tic), clocks_getunit());
+
+#ifdef WITH_MPI
+
+  /* Move non-local gparts to the end of the list. */
+  for (int k = 0; k < nr_gparts; k++)
+    if (cells[ind[k]].nodeID != nodeID) {
+      cells[ind[k]].gcount -= 1;
+      nr_gparts -= 1;
+      struct gpart tp = s->gparts[k];
+      s->gparts[k] = s->gparts[nr_gparts];
+      s->gparts[nr_gparts] = tp;
+      int t = ind[k];
+      ind[k] = ind[nr_gparts];
+      ind[nr_gparts] = t;
+    }
+
+  /* Exchange the strays, note that this potentially re-allocates
+     the parts arrays. */
+  // s->nr_gparts =
+  //    nr_gparts + engine_exchange_strays(s->e, nr_gparts, &ind[nr_gparts],
+  //                                        s->nr_gparts - nr_gparts);
+  if (nr_gparts > 0)
+    error("Need to implement the exchange of strays for the gparts");
+
+  /* Re-allocate the index array if needed.. */
+  if (s->nr_gparts > gind_size) {
+    size_t *gind_new;
+    if ((gind_new = (size_t *)malloc(sizeof(size_t) * s->nr_gparts)) == NULL)
+      error("Failed to allocate temporary g-particle indices.");
+    memcpy(gind_new, gind, sizeof(size_t) * nr_gparts);
+    free(gind);
+    gind = gind_new;
+  }
+
+  /* Assign each particle to its cell. */
+  for (int k = nr_gparts; k < s->nr_gparts; k++) {
+    struct gpart *p = &s->gparts[k];
+    gind[k] =
+        cell_getid(cdim, p->x[0] * ih[0], p->x[1] * ih[1], p->x[2] * ih[2]);
+    cells[gind[k]].count += 1;
+    /* if ( cells[ ind[k] ].nodeID != nodeID )
+        error( "Received part that does not belong to me (nodeID=%i)." , cells[
+       ind[k] ].nodeID ); */
+  }
+  nr_gparts = s->nr_gparts;
 
-  /* TODO: Here we should exchange the gparts as well! */
+#endif
 
   /* Sort the parts according to their cells. */
-  space_gparts_sort(s->gparts, ind, nr_gparts, 0, s->nr_cells - 1);
+  space_gparts_sort(s->gparts, gind, nr_gparts, 0, s->nr_cells - 1);
 
   /* Re-link the parts. */
-  for (k = 0; k < nr_gparts; k++)
+  for (int k = 0; k < nr_gparts; k++)
     if (s->gparts[k].id > 0) s->gparts[k].part->gpart = &s->gparts[k];
 
   /* We no longer need the indices as of here. */
-  free(ind);
+  free(gind);
 
   /* Hook the cells up to the parts. */
   // tic = getticks();
   struct part *finger = s->parts;
   struct xpart *xfinger = s->xparts;
   struct gpart *gfinger = s->gparts;
-  for (k = 0; k < s->nr_cells; k++) {
-    c = &cells[k];
+  for (int k = 0; k < s->nr_cells; k++) {
+    struct cell *restrict c = &cells[k];
     c->parts = finger;
     c->xparts = xfinger;
     c->gparts = gfinger;
@@ -1003,12 +1052,15 @@ void space_map_cells_pre(struct space *s, int full,
 
 void space_do_split(struct space *s, struct cell *c) {
 
-  int k, count = c->count, gcount = c->gcount, maxdepth = 0;
-  float h, h_max = 0.0f;
-  int ti_end_min = max_nr_timesteps, ti_end_max = 0, ti_end;
+  const int count = c->count;
+  const int gcount = c->gcount;
+  int maxdepth = 0;
+  float h_max = 0.0f;
+  int ti_end_min = max_nr_timesteps, ti_end_max = 0;
   struct cell *temp;
-  struct part *p, *parts = c->parts;
-  struct xpart *xp, *xparts = c->xparts;
+  struct part *parts = c->parts;
+  struct gpart *gparts = c->gparts;
+  struct xpart *xparts = c->xparts;
 
   /* Check the depth. */
   if (c->depth > s->maxdepth) s->maxdepth = c->depth;
@@ -1020,7 +1072,7 @@ void space_do_split(struct space *s, struct cell *c) {
     c->split = 1;
 
     /* Create the cell's progeny. */
-    for (k = 0; k < 8; k++) {
+    for (int k = 0; k < 8; k++) {
       temp = space_getcell(s);
       temp->count = 0;
       temp->gcount = 0;
@@ -1047,7 +1099,7 @@ void space_do_split(struct space *s, struct cell *c) {
     cell_split(c);
 
     /* Remove any progeny with zero parts. */
-    for (k = 0; k < 8; k++)
+    for (int k = 0; k < 8; k++)
       if (c->progeny[k]->count == 0 && c->progeny[k]->gcount == 0) {
         space_recycle(s, c->progeny[k]);
         c->progeny[k] = NULL;
@@ -1077,26 +1129,36 @@ void space_do_split(struct space *s, struct cell *c) {
     c->maxdepth = c->depth;
 
     /* Get dt_min/dt_max. */
-
-    for (k = 0; k < count; k++) {
-      p = &parts[k];
-      xp = &xparts[k];
+    for (int k = 0; k < count; k++) {
+      struct part *p = &parts[k];
+      struct xpart *xp = &xparts[k];
+      const float h = p->h;
+      const int ti_end = p->ti_end;
       xp->x_old[0] = p->x[0];
       xp->x_old[1] = p->x[1];
       xp->x_old[2] = p->x[2];
-      h = p->h;
-      ti_end = p->ti_end;
       if (h > h_max) h_max = h;
       if (ti_end < ti_end_min) ti_end_min = ti_end;
       if (ti_end > ti_end_max) ti_end_max = ti_end;
     }
+    for (int k = 0; k < gcount; k++) {
+      struct gpart *p = &gparts[k];
+      const int ti_end = p->ti_end;
+      if (ti_end < ti_end_min) ti_end_min = ti_end;
+      if (ti_end > ti_end_max) ti_end_max = ti_end;
+    }
     c->h_max = h_max;
     c->ti_end_min = ti_end_min;
     c->ti_end_max = ti_end_max;
   }
 
   /* Set ownership according to the start of the parts array. */
-  c->owner = ((c->parts - s->parts) % s->nr_parts) * s->nr_queues / s->nr_parts;
+  if (s->nr_parts > 0)
+    c->owner =
+        ((c->parts - s->parts) % s->nr_parts) * s->nr_queues / s->nr_parts;
+  else
+    c->owner =
+        ((c->gparts - s->gparts) % s->nr_gparts) * s->nr_queues / s->nr_gparts;
 }
 
 /**
@@ -1176,8 +1238,10 @@ struct cell *space_getcell(struct space *s) {
  *
  * @param s The #space to initialize.
  * @param dim Spatial dimensions of the domain.
- * @param parts Pointer to an array of #part.
- * @param N The number of parts in the space.
+ * @param parts Array of Gas particles.
+ * @param gparts Array of Gravity particles.
+ * @param Ngas The number of Gas particles in the space.
+ * @param Ngpart The number of Gravity particles in the space.
  * @param periodic flag whether the domain is periodic or not.
  * @param h_max The maximal interaction radius.
  * @param verbose Print messages to stdout or not
@@ -1188,62 +1252,59 @@ struct cell *space_getcell(struct space *s) {
  * recursively.
  */
 
-void space_init(struct space *s, double dim[3], struct part *parts, size_t N,
-                int periodic, double h_max, int verbose) {
+void space_init(struct space *s, double dim[3], struct part *parts,
+                struct gpart *gparts, size_t Ngas, size_t Ngpart, int periodic,
+                double h_max, int verbose) {
 
   /* Store everything in the space. */
   s->dim[0] = dim[0];
   s->dim[1] = dim[1];
   s->dim[2] = dim[2];
   s->periodic = periodic;
-  s->nr_parts = N;
-  s->size_parts = N;
+  s->nr_parts = Ngas;
+  s->size_parts = Ngas;
   s->parts = parts;
+  s->nr_gparts = Ngpart;
+  s->size_gparts = Ngpart;
+  s->gparts = gparts;
   s->cell_min = h_max;
   s->nr_queues = 1;
   s->size_parts_foreign = 0;
 
-  /* Check that all the particle positions are reasonable, wrap if periodic. */
+  /* Check that all the gas particle positions are reasonable, wrap if periodic.
+   */
   if (periodic) {
-    for (int k = 0; k < N; k++)
+    for (int k = 0; k < Ngas; k++)
       for (int j = 0; j < 3; j++) {
         while (parts[k].x[j] < 0) parts[k].x[j] += dim[j];
         while (parts[k].x[j] >= dim[j]) parts[k].x[j] -= dim[j];
       }
   } else {
-    for (int k = 0; k < N; k++)
+    for (int k = 0; k < Ngas; k++)
       for (int j = 0; j < 3; j++)
         if (parts[k].x[j] < 0 || parts[k].x[j] >= dim[j])
           error("Not all particles are within the specified domain.");
   }
 
-  /* Allocate the xtra parts array. */
-  if (posix_memalign((void *)&s->xparts, part_align,
-                     N * sizeof(struct xpart)) != 0)
-    error("Failed to allocate xparts.");
-  bzero(s->xparts, N * sizeof(struct xpart));
-
-  /* For now, clone the parts to make gparts. */
-  if (posix_memalign((void *)&s->gparts, part_align,
-                     N * sizeof(struct gpart)) != 0)
-    error("Failed to allocate gparts.");
-  bzero(s->gparts, N * sizeof(struct gpart));
-  /* for ( int k = 0 ; k < N ; k++ ) {
-      s->gparts[k].x[0] = s->parts[k].x[0];
-      s->gparts[k].x[1] = s->parts[k].x[1];
-      s->gparts[k].x[2] = s->parts[k].x[2];
-      s->gparts[k].v[0] = s->parts[k].v[0];
-      s->gparts[k].v[1] = s->parts[k].v[1];
-      s->gparts[k].v[2] = s->parts[k].v[2];
-      s->gparts[k].mass = s->parts[k].mass;
-      s->gparts[k].dt = s->parts[k].dt;
-      s->gparts[k].id = s->parts[k].id;
-      s->gparts[k].part = &s->parts[k];
-      s->parts[k].gpart = &s->gparts[k];
+  /* Same for the gparts */
+  if (periodic) {
+    for (int k = 0; k < Ngpart; k++)
+      for (int j = 0; j < 3; j++) {
+        while (gparts[k].x[j] < 0) gparts[k].x[j] += dim[j];
+        while (gparts[k].x[j] >= dim[j]) gparts[k].x[j] -= dim[j];
       }
-  s->nr_gparts = s->nr_parts; */
-  s->nr_gparts = 0;
-  s->size_gparts = s->size_parts;
+  } else {
+    for (int k = 0; k < Ngpart; k++)
+      for (int j = 0; j < 3; j++)
+        if (gparts[k].x[j] < 0 || gparts[k].x[j] >= dim[j])
+          error("Not all particles are within the specified domain.");
+  }
+
+  /* Allocate the extra parts array. */
+  if (posix_memalign((void *)&s->xparts, xpart_align,
+                     Ngas * sizeof(struct xpart)) != 0)
+    error("Failed to allocate xparts.");
+  bzero(s->xparts, Ngas * sizeof(struct xpart));
 
   /* Init the space lock. */
   if (lock_init(&s->lock) != 0) error("Failed to create space spin-lock.");
diff --git a/src/space.h b/src/space.h
index 87b618b141b7871aeb5ff76eae5bdc24f063bdef..91485ff7e2ebe9da8ab927748589ae9f71320803 100644
--- a/src/space.h
+++ b/src/space.h
@@ -127,12 +127,14 @@ extern struct parallel_sort space_sort_struct;
 /* function prototypes. */
 void space_parts_sort(struct space *s, size_t *ind, size_t N, int min, int max,
                       int verbose);
-void space_gparts_sort(struct gpart *gparts, size_t *ind, size_t N, int min, int max);
+void space_gparts_sort(struct gpart *gparts, size_t *ind, size_t N, int min,
+                       int max);
 struct cell *space_getcell(struct space *s);
 int space_getsid(struct space *s, struct cell **ci, struct cell **cj,
                  double *shift);
-void space_init(struct space *s, double dim[3], struct part *parts, size_t N,
-                int periodic, double h_max, int verbose);
+void space_init(struct space *s, double dim[3], struct part *parts,
+                struct gpart *gparts, size_t N, size_t Ngpart, int periodic,
+                double h_max, int verbose);
 void space_map_cells_pre(struct space *s, int full,
                          void (*fun)(struct cell *c, void *data), void *data);
 void space_map_parts(struct space *s,
diff --git a/tests/testReading.c b/tests/testReading.c
index 17b33d88f6fd702e0bad6280f4adbe7ebc50ef2a..d2a2a766171a85ace486914f0f39a987d9d8c3d3 100644
--- a/tests/testReading.c
+++ b/tests/testReading.c
@@ -22,10 +22,12 @@
 
 int main() {
 
-  int N = -1, periodic = -1;
+  int Ngas = -1, Ngpart = -1;
+  int periodic = -1;
   int i, j, k, n;
   double dim[3];
   struct part *parts = NULL;
+  struct gpart *gparts = NULL;
 
   /* Properties of the ICs */
   const double boxSize = 1.;
@@ -33,25 +35,26 @@ int main() {
   const double rho = 2.;
 
   /* Read data */
-  read_ic_single("input.hdf5", dim, &parts, &N, &periodic);
+  read_ic_single("input.hdf5", dim, &parts, &gparts, &Ngas, &Ngpart, &periodic);
 
   /* Check global properties read are correct */
   assert(dim[0] == boxSize);
   assert(dim[1] == boxSize);
   assert(dim[2] == boxSize);
-  assert(N == L * L * L);
+  assert(Ngas == L * L * L);
+  assert(Ngpart == L * L * L);
   assert(periodic == 1);
 
   /* Check particles */
-  for (n = 0; n < N; ++n) {
+  for (n = 0; n < Ngas; ++n) {
 
     /* Check that indices are in a reasonable range */
     unsigned long long index = parts[n].id;
-    assert(index < N);
+    assert(index < Ngas);
 
     /* Check masses */
     float mass = parts[n].mass;
-    float correct_mass = boxSize * boxSize * boxSize * rho / N;
+    float correct_mass = boxSize * boxSize * boxSize * rho / Ngas;
     assert(mass == correct_mass);
 
     /* Check smoothing length */