diff --git a/examples/test.c b/examples/test.c
index 427b761680bde8c96d23f576cbde792fb13519b2..a09e34aede5c5016eae63b2f6f21d9e999a68ca0 100644
--- a/examples/test.c
+++ b/examples/test.c
@@ -677,11 +677,16 @@ int main ( int argc , char *argv[] ) {
 
     /* Read particles and space information from (GADGET) IC */
     tic = getticks();
-#ifdef WITH_MPI
+#if defined( WITH_MPI ) 
+#if defined( HAVE_PARALLEL_HDF5 )
     read_ic_parallel( ICfileName , dim , &parts , &N , &periodic, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL );
 #else
-    read_ic( ICfileName , dim , &parts , &N , &periodic );
+    read_ic_serial( ICfileName , dim , &parts , &N , &periodic, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL );
+#endif
+#else
+    read_ic_single( ICfileName , dim , &parts , &N , &periodic );
 #endif
+
     if ( myrank == 0 )
         message( "reading particle properties took %.3f ms." , ((double)(getticks() - tic)) / CPU_TPS * 1000 ); fflush(stdout);
     
@@ -778,12 +783,17 @@ int main ( int argc , char *argv[] ) {
     engine_redistribute ( &e );
 #endif
 
+    message("Before write !");
     /* Write the state of the system as it is before starting time integration. */
     tic = getticks();
-#ifdef WITH_MPI
+#if defined( WITH_MPI ) 
+#if defined( HAVE_PARALLEL_HDF5 )
     write_output_parallel(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
 #else
-    write_output(&e, &us);
+    write_output_serial(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+#endif
+#else
+    write_output_single(&e, &us);
 #endif
     message( "writing particle properties took %.3f ms." , ((double)(getticks() - tic)) / CPU_TPS * 1000 ); fflush(stdout);
     
@@ -837,11 +847,17 @@ int main ( int argc , char *argv[] ) {
         
         if ( j % 100 == 0 )
 	  {
-#ifdef WITH_MPI
-             write_output_parallel(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+
+#if defined( WITH_MPI ) 
+#if defined( HAVE_PARALLEL_HDF5 )
+	    write_output_parallel(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+#else
+	    write_output_serial(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+#endif
 #else
-             write_output(&e, &us);
+	    write_output_single(&e, &us);
 #endif
+
           }
                 
         /* Dump a line of agregate output. */
@@ -858,20 +874,18 @@ int main ( int argc , char *argv[] ) {
         /* for ( k = 0 ; k < 5 ; k++ )
             printgParticle( s.gparts , pid[k] , N ); */
         
-        }
+    }
         
     /* Print the values of the runner histogram. */
-    #ifdef HIST
-        printf( "main: runner histogram data:\n" );
-        for ( k = 0 ; k < runner_hist_N ; k++ )
-            printf( " %e %e %e\n" ,
-                runner_hist_a + k * (runner_hist_b - runner_hist_a) / runner_hist_N ,
-                runner_hist_a + (k + 1) * (runner_hist_b - runner_hist_a) / runner_hist_N ,
-                (double)runner_hist_bins[k] );
-    #endif
+#ifdef HIST
+    printf( "main: runner histogram data:\n" );
+    for ( k = 0 ; k < runner_hist_N ; k++ )
+      printf( " %e %e %e\n" ,
+	      runner_hist_a + k * (runner_hist_b - runner_hist_a) / runner_hist_N ,
+	      runner_hist_a + (k + 1) * (runner_hist_b - runner_hist_a) / runner_hist_N ,
+	      (double)runner_hist_bins[k] );
+#endif
 
-    // write_output( &e );
-        
     /* Loop over the parts directly. */
     // for ( k = 0 ; k < N ; k++ )
     //     printf( " %i %e %e\n" , s.parts[k].id , s.parts[k].count , s.parts[k].count_dh );
@@ -904,16 +918,20 @@ int main ( int argc , char *argv[] ) {
     #endif */
     
     /* Write final output. */
-#ifdef WITH_MPI
-	write_output_parallel( &e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL );
+#if defined( WITH_MPI ) 
+#if defined( HAVE_PARALLEL_HDF5 )
+    write_output_parallel(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+#else
+    write_output_serial(&e, &us, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL);
+#endif
 #else
-	write_output( &e , &us );
+    write_output_single(&e, &us);
 #endif
         
 #ifdef WITH_MPI
-        if ( MPI_Finalize() != MPI_SUCCESS )
-            error( "call to MPI_Finalize failed with error %i." , res );
-    #endif
+    if ( MPI_Finalize() != MPI_SUCCESS )
+      error( "call to MPI_Finalize failed with error %i." , res );
+#endif
     
     /* Say goodbye. */
     message( "done." );
@@ -921,4 +939,4 @@ int main ( int argc , char *argv[] ) {
     /* All is calm, all is bright. */
     return 0;
     
-    }
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index f9aa25995a20d4aacebf74aa24cd7a9dfc4d2418..99ebb246b99a620b0207784b132e0a8275a12d36 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,12 +35,12 @@ endif
 # List required headers
 include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \
     engine.h swift.h serial_io.h timers.h debug.h scheduler.h proxy.h parallel_io.h \
-    common_io.h multipole.h
+    common_io.h single_io.h multipole.h
 
 # Common source files
 AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
     serial_io.c timers.c debug.c scheduler.c proxy.c parallel_io.c \
-    units.c common_io.c multipole.c version.c
+    units.c common_io.c single_io.c multipole.c version.c
 
 # Include files for distribution, not installation.
 noinst_HEADERS = atomic.h cycle.h error.h inline.h kernel.h vector.h \
diff --git a/src/parallel_io.c b/src/parallel_io.c
index deb6eab914c8a92513ba64c2733affc4db23ffee..7e2f5e244aa3b280872dc25e1fd14ce0348bbd3b 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -21,7 +21,7 @@
 /* Config parameters. */
 #include "../config.h"
 
-#if defined(HAVE_HDF5) && defined(WITH_MPI)
+#if defined(HAVE_HDF5) && defined(WITH_MPI) && defined(HAVE_PARALLEL_HDF5)
 
 /* Tell hdf5 that we intend to use shared-memory parallel stuff. */
 #define H5_HAVE_PARALLEL
@@ -90,24 +90,19 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
 	  error( "Compulsory data set '%s' not present in the file." , name );
 	}
       else
-	{
-	  /* message("Optional data set '%s' not present. Zeroing this particle field...", name);	   */
-	  
+	{	  
 	  for(i=0; i<N; ++i)
 	    memset(part_c+i*partSize, 0, copySize);
-	  
 	  return;
 	}
-   }
+    }
 
   /* message( "Reading %s '%s' array...", importance == COMPULSORY ? "compulsory": "optional  ", name); */
 
   /* Open data space in file */
   h_data = H5Dopen2(grp, name, H5P_DEFAULT);
   if(h_data < 0)
-    {
-      error( "Error while opening data space '%s'." , name );
-    }
+    error( "Error while opening data space '%s'." , name );
 
   /* Check data type */
   h_type = H5Dget_type(h_data);
@@ -121,6 +116,7 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
   if(temp == NULL)
     error("Unable to allocate memory for temporary buffer");
 
+  /* Prepare information for hyperslab */
   if(dim > 1)
     {
       rank = 2;
@@ -161,6 +157,9 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
   
   /* Free and close everything */
   free(temp);
+  H5Pclose(h_plist_id);
+  H5Sclose(h_filespace);
+  H5Sclose(h_memspace);
   H5Tclose(h_type);
   H5Dclose(h_data);
 }
@@ -212,9 +211,9 @@ void read_ic_parallel ( char* fileName, double dim[3], struct part **parts,  int
 
   /* Open file */
   /* message("Opening file '%s' as IC.", fileName); */
-  hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
-  H5Pset_fapl_mpio(plist_id, comm, info);
-  h_file = H5Fopen(fileName, H5F_ACC_RDONLY, plist_id);
+  hid_t h_plist_id = H5Pcreate(H5P_FILE_ACCESS);
+  H5Pset_fapl_mpio(h_plist_id, comm, info);
+  h_file = H5Fopen(fileName, H5F_ACC_RDONLY, h_plist_id);
   if(h_file < 0)
     {
       error( "Error while opening file '%s'." , fileName );
@@ -285,10 +284,13 @@ void read_ic_parallel ( char* fileName, double dim[3], struct part **parts,  int
   /* Close particle group */
   H5Gclose(h_grp);
 
-  /* message("Done Reading particles..."); */
+  /* Close property handler */
+  H5Pclose(h_plist_id);
 
   /* Close file */
   H5Fclose(h_file);
+
+  /* message("Done Reading particles..."); */
 }
 
 
@@ -318,7 +320,7 @@ void read_ic_parallel ( char* fileName, double dim[3], struct part **parts,  int
  *
  * Calls #error() if an error occurs.
  */
-void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enum DATA_TYPE type, int N, int dim, int N_total, int mpi_rank, int offset, char* part_c, struct UnitSystem* us, enum UnitConversionFactor convFactor)
+void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enum DATA_TYPE type, int N, int dim, long long N_total, int mpi_rank, long long offset, char* part_c, struct UnitSystem* us, enum UnitConversionFactor convFactor)
 {
   hid_t h_data=0, h_err=0, h_memspace=0, h_filespace=0, h_plist_id=0;
   hsize_t shape[2], shape_total[2], offsets[2];
@@ -389,7 +391,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
   h_data = H5Dcreate1(grp, name, hdf5Type(type), h_filespace, H5P_DEFAULT);
   if(h_data < 0)
     {
-      error( "Error while creating dataspace '%s'." , name );
+      error( "Error while creating dataset '%s'." , name );
     }
   
   H5Sclose(h_filespace);
@@ -423,6 +425,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
   H5Dclose(h_data);
   H5Pclose(h_plist_id);
   H5Sclose(h_memspace);
+  H5Sclose(h_filespace);
 }
 
 /**
@@ -450,6 +453,7 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
  * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor
  *
  * @param e The engine containing all the system.
+ * @param us The UnitSystem used for the conversion of units in the output
  *
  * Creates an HDF5 output file and writes the particles contained
  * in the engine. If such a file already exists, it is erased and replaced
@@ -491,7 +495,6 @@ void write_output_parallel (struct engine *e, struct UnitSystem* us,  int mpi_ra
   hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
   H5Pset_fapl_mpio(plist_id, comm, info);
   h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id);
-  H5Pclose(plist_id);
   if(h_file < 0)
     {
       error( "Error while opening file '%s'." , fileName );
@@ -580,6 +583,9 @@ void write_output_parallel (struct engine *e, struct UnitSystem* us,  int mpi_ra
 
   /* message("Done writing particles..."); */
 
+  /* Close property descriptor */
+  H5Pclose(plist_id);
+
   /* Close file */
   H5Fclose(h_file);
 
diff --git a/src/parallel_io.h b/src/parallel_io.h
index 51cfb3a906261f8e260fd4825829bce33fa38dca..78699a5938894ef4577e9a14938e4a16dae2b612 100644
--- a/src/parallel_io.h
+++ b/src/parallel_io.h
@@ -18,7 +18,7 @@
  ******************************************************************************/
 
 
-#if defined(HAVE_HDF5) && defined(WITH_MPI)
+#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, MPI_Comm comm, MPI_Info info);
 
diff --git a/src/serial_io.c b/src/serial_io.c
index 92a576da8588a4b66707de11d002d0636139492a..fa54be0b30a3f9e9c33221ab4ba5f668d274b209 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -21,7 +21,7 @@
 /* Config parameters. */
 #include "../config.h"
 
-#if defined(HAVE_HDF5) && !defined(WITH_MPI)
+#if defined(HAVE_HDF5) && defined(WITH_MPI) && !defined(HAVE_PARALLEL_HDF5)
 
 
 /* Some standard headers. */
@@ -32,6 +32,8 @@
 #include <hdf5.h>
 #include <math.h>
 
+#include "mpi.h"
+
 #include "const.h"
 #include "cycle.h"
 #include "lock.h"
@@ -66,12 +68,13 @@
  *  
  * Calls #error() if an error occurs.
  */
-void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, char* part_c, enum DATA_IMPORTANCE importance)
+void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, long long N_total, long long offset, char* part_c, enum DATA_IMPORTANCE importance)
 {
-  hid_t h_data=0, h_err=0, h_type=0;
+  hid_t h_data=0, h_err=0, h_type=0, h_memspace=0, h_filespace=0;
+  hsize_t shape[2], offsets[2];
   htri_t exist=0;
   void* temp;
-  int i=0;
+  int i=0, rank=0;
   const size_t typeSize = sizeOfType(type);
   const size_t copySize = typeSize * dim;
   const size_t partSize = sizeof(struct part);
@@ -91,23 +94,18 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
 	}
       else
 	{
-	  /* message("Optional data set '%s' not present. Zeroing this particle field...", name);	   */
-	  
 	  for(i=0; i<N; ++i)
-	    memset(part_c+i*partSize, 0, copySize);
-	  
+	    memset(part_c+i*partSize, 0, copySize);	  
 	  return;
 	}
-   }
+    }
 
   /* message( "Reading %s '%s' array...", importance == COMPULSORY ? "compulsory": "optional  ", name); */
 
   /* Open data space */
   h_data = H5Dopen1(grp, name);
   if(h_data < 0)
-    {
-      error( "Error while opening data space '%s'." , name );
-    }
+    error( "Error while opening data space '%s'." , name );
 
   /* Check data type */
   h_type = H5Dget_type(h_data);
@@ -121,10 +119,32 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
   if(temp == NULL)
     error("Unable to allocate memory for temporary buffer");
 
+  /* Prepare information for hyperslab */
+  if(dim > 1)
+    {
+      rank = 2;
+      shape[0] = N; shape[1] = dim;
+      offsets[0] = offset; offsets[1] = 0;
+    }
+  else
+    {
+      rank = 1;
+      shape[0] = N; shape[1] = 0;
+      offsets[0] = offset; offsets[1] = 0;
+    }
+
+  /* Create data space in memory */
+  h_memspace = H5Screate_simple(rank, shape, NULL);
+
+  /* Select hyperslab in file */
+  h_filespace = H5Dget_space(h_data);
+  H5Sselect_hyperslab(h_filespace, H5S_SELECT_SET, offsets, NULL, shape, NULL);
+
+
   /* Read HDF5 dataspace in temporary buffer */
   /* Dirty version that happens to work for vectors but should be improved */
   /* Using HDF5 dataspaces would be better */
-  h_err = H5Dread(h_data, hdf5Type(type), H5S_ALL, H5S_ALL, H5P_DEFAULT, temp);
+  h_err = H5Dread(h_data, hdf5Type(type), h_memspace, h_filespace, H5P_DEFAULT, temp);
   if(h_err < 0)
     {
       error( "Error while reading data array '%s'." , name );
@@ -137,6 +157,8 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
   
   /* Free and close everything */
   free(temp);
+  H5Sclose(h_filespace);
+  H5Sclose(h_memspace);
   H5Tclose(h_type);
   H5Dclose(h_data);
 }
@@ -150,11 +172,13 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
  * @param N The number of particles.
  * @param dim The dimension of the data (1 for scalar, 3 for vector)
  * @param part The array of particles to fill
+ * @param N_total Total number of particles
+ * @param offset Offset in the array where this task starts reading
  * @param field The name of the field (C code name as defined in part.h) to fill
  * @param importance Is the data compulsory or not
  *
  */
-#define readArray(grp, name, type, N, dim, part, field, importance) readArrayBackEnd(grp, name, type, N, dim, (char*)(&(part[0]).field), importance)
+#define readArray(grp, name, type, N, dim, part, N_total, offset, field, importance) readArrayBackEnd(grp, name, type, N, dim, N_total, offset, (char*)(&(part[0]).field), importance)
 
 /**
  * @brief Reads an HDF5 initial condition file (GADGET-3 type)
@@ -175,84 +199,123 @@ void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim
  * Calls #error() if an error occurs.
  *
  */
-void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int* periodic)
+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)
 {
   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*/
+  int numParticles_highWord[6]={0};
+  long long offset = 0;
+  long long N_total = 0;
+  int rank;
+
+  /* First read some information about the content */
+  if (mpi_rank == 0) {
+
+    /* Open file */
+    /* message("Opening file '%s' as IC.", fileName); */
+    h_file = H5Fopen(fileName, H5F_ACC_RDONLY, H5P_DEFAULT);
+    if(h_file < 0)
+      error( "Error while opening file '%s' for inital read." , fileName );
+    
+    /* Open header to read simulation properties */
+    /* message("Reading runtime parameters..."); */
+    h_grp = H5Gopen1(h_file, "/RuntimePars");
+    if(h_grp < 0)
+      error("Error while opening runtime parameters\n");
+    
+    /* Read the relevant information */
+    readAttribute(h_grp, "PeriodicBoundariesOn", INT, periodic);
 
-  /* Open file */
-  /* message("Opening file '%s' as IC.", fileName); */
-  h_file = H5Fopen(fileName, H5F_ACC_RDONLY, H5P_DEFAULT);
-  if(h_file < 0)
-    {
-      error( "Error while opening file '%s'." , fileName );
-    }
+    /* Close runtime parameters */
+    H5Gclose(h_grp);
+  
+    /* Open header to read simulation properties */
+    /* message("Reading file header..."); */
+    h_grp = H5Gopen1(h_file, "/Header");
+    if(h_grp < 0)
+      error("Error while opening file header\n");
+    
+    /* Read the relevant information and print status */
+    readAttribute(h_grp, "BoxSize", DOUBLE, boxSize);
+    readAttribute(h_grp, "NumPart_Total", UINT, numParticles);
+    readAttribute(h_grp, "NumPart_Total_HighWord", UINT, numParticles_highWord);
+
+    N_total = ((long long) numParticles[0]) + ((long long) numParticles_highWord[0] << 32);   
+    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]); */
+    
+    /* Close header */
+    H5Gclose(h_grp);
 
-  /* Open header to read simulation properties */
-  /* message("Reading runtime parameters..."); */
-  h_grp = H5Gopen1(h_file, "/RuntimePars");
-  if(h_grp < 0)
-    error("Error while opening runtime parameters\n");
+    /* Close file */
+    H5Fclose(h_file);
+  }
 
-  /* Read the relevant information */
-  readAttribute(h_grp, "PeriodicBoundariesOn", INT, periodic);
 
-  /* Close runtime parameters */
-  H5Gclose(h_grp);
+  /* Now need to broadcast that information to all ranks. */
+  MPI_Bcast(periodic, 1, MPI_INT, 0, comm);
+  MPI_Bcast(&N_total, 1, MPI_LONG_LONG, 0, comm);
+  MPI_Bcast(dim, 3, MPI_DOUBLE, 0, comm);
   
-  /* Open header to read simulation properties */
-  /* message("Reading file header..."); */
-  h_grp = H5Gopen1(h_file, "/Header");
-  if(h_grp < 0)
-    error("Error while opening file header\n");
-    
-  /* Read the relevant information and print status */
-  readAttribute(h_grp, "BoxSize", DOUBLE, boxSize);
-  readAttribute(h_grp, "NumPart_Total", UINT, numParticles);
 
-  *N = numParticles[0];
-  dim[0] = boxSize[0];
-  dim[1] = ( boxSize[1] < 0 ) ? boxSize[0] : boxSize[1];
-  dim[2] = ( boxSize[2] < 0 ) ? boxSize[0] : boxSize[2];
+  /* Divide the particles among the tasks. */
+  offset = mpi_rank * N_total / mpi_size;
+  *N = (mpi_rank + 1) * N_total / mpi_size - offset;
 
-  /* message("Found %d particles in a %speriodic box of size [%f %f %f].",  */
-  /* 	 *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)
+  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) );
-
   /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) / (1024.*1024.)); */
-		  
-  /* Open SPH particles group */
-  /* message("Reading particle arrays..."); */
-  h_grp = H5Gopen1(h_file, "/PartType0");
-  if(h_grp < 0)
-    error( "Error while opening particle group.\n");
-
-  /* Read arrays */
-  readArray(h_grp, "Coordinates", DOUBLE, *N, 3, *parts, x, COMPULSORY);
-  readArray(h_grp, "Velocities", FLOAT, *N, 3, *parts, v, COMPULSORY);
-  readArray(h_grp, "Masses", FLOAT, *N, 1, *parts, mass, COMPULSORY);
-  readArray(h_grp, "SmoothingLength", FLOAT, *N, 1, *parts, h, COMPULSORY);
-  readArray(h_grp, "InternalEnergy", FLOAT, *N, 1, *parts, u, COMPULSORY);
-  readArray(h_grp, "ParticleIDs", ULONGLONG, *N, 1, *parts, id, COMPULSORY);
-  readArray(h_grp, "TimeStep", FLOAT, *N, 1, *parts, dt, OPTIONAL);
-  readArray(h_grp, "Acceleration", FLOAT, *N, 3, *parts, a, OPTIONAL);
-  readArray(h_grp, "Density", FLOAT, *N, 1, *parts, rho, OPTIONAL );
-
-  /* Close particle group */
-  H5Gclose(h_grp);
+
+  /* Now loop over ranks and read the data */
+  for ( rank = 0; rank < mpi_size ; ++ rank ) {
+
+    /* Is it this rank's turn to read ? */
+    if ( rank == mpi_rank ) {
+
+      h_file = H5Fopen(fileName, H5F_ACC_RDONLY, H5P_DEFAULT);
+      if(h_file < 0)
+	error( "Error while opening file '%s' on rank %d." , fileName, mpi_rank );	
+      		  
+      /* Open SPH particles group */
+      /* message("Reading particle arrays..."); */
+      h_grp = H5Gopen1(h_file, "/PartType0");
+      if(h_grp < 0)
+	error( "Error while opening particle group on rank %d.\n", mpi_rank);
+      
+      /* Read arrays */
+      readArray(h_grp, "Coordinates", DOUBLE, *N, 3, *parts, N_total, offset, x, COMPULSORY);
+      readArray(h_grp, "Velocities", FLOAT, *N, 3, *parts, N_total, offset, v, COMPULSORY);
+      readArray(h_grp, "Masses", FLOAT, *N, 1, *parts, N_total, offset, mass, COMPULSORY);
+      readArray(h_grp, "SmoothingLength", FLOAT, *N, 1, *parts, N_total, offset, h, COMPULSORY);
+      readArray(h_grp, "InternalEnergy", FLOAT, *N, 1, *parts, N_total, offset, u, COMPULSORY);
+      readArray(h_grp, "ParticleIDs", ULONGLONG, *N, 1, *parts, N_total, offset, id, COMPULSORY);
+      readArray(h_grp, "TimeStep", FLOAT, *N, 1, *parts, N_total, offset, dt, OPTIONAL);
+      readArray(h_grp, "Acceleration", FLOAT, *N, 3, *parts, N_total, offset, a, OPTIONAL);
+      readArray(h_grp, "Density", FLOAT, *N, 1, *parts, N_total, offset, rho, OPTIONAL );
+      
+      /* Close particle group */
+      H5Gclose(h_grp);
+
+      /* Close file */
+      H5Fclose(h_file);
+
+    }
+
+    /* Wait for the read of the reading to complete */
+    MPI_Barrier(comm);
+
+  }
 
   /* message("Done Reading particles..."); */
 
-  /* Close file */
-  H5Fclose(h_file);
 }
 
 
@@ -260,6 +323,64 @@ void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int*
  * Routines writing an output file
  *-----------------------------------------------------------------------------*/
 
+void prepareArray(hid_t grp, char* fileName, FILE* xmfFile, char* name, enum DATA_TYPE type, long long N_total, int dim,  struct UnitSystem* us, enum UnitConversionFactor convFactor)
+{
+  hid_t h_data=0, h_err=0, h_space=0;
+  void* temp = 0;
+  int i=0, rank=0;
+  const size_t typeSize = sizeOfType(type);
+  const size_t copySize = typeSize * dim;
+  const size_t partSize = sizeof(struct part);
+  char* temp_c = 0;
+  hsize_t shape[2];
+  char buffer[150];
+
+  /* Create data space */
+  h_space = H5Screate(H5S_SIMPLE);
+  if(h_space < 0)
+    {
+      error( "Error while creating data space for field '%s'." , name );
+    }
+  
+  if(dim > 1)
+    {
+      rank = 2;
+      shape[0] = N_total; shape[1] = dim;
+    }
+  else
+    {
+      rank = 1;
+      shape[0] = N_total; shape[1] = 0;
+    }
+  
+  /* Change shape of data space */
+  h_err = H5Sset_extent_simple(h_space, rank, shape, NULL);
+  if(h_err < 0)
+    {
+      error( "Error while changing data space shape for field '%s'." , name );
+    }
+  
+  /* Create dataset */
+  h_data = H5Dcreate1(grp, name, hdf5Type(type), h_space, H5P_DEFAULT);
+  if(h_data < 0)
+    {
+      error( "Error while creating dataspace '%s'." , name );
+    }
+
+  /* Write XMF description for this data set */
+  writeXMFline(xmfFile, fileName, name, N_total, dim, type);
+
+  /* Write unit conversion factors for this data set */
+  conversionString( buffer, us, convFactor );
+  writeAttribute_d( h_data, "CGS conversion factor", conversionFactor( us, convFactor ) );
+  writeAttribute_f( h_data, "h-scale exponant", hFactor( us, convFactor ) );
+  writeAttribute_f( h_data, "a-scale exponant", aFactor( us, convFactor ) );
+  writeAttribute_s( h_data, "Conversion factor", buffer );
+
+  H5Dclose(h_data);
+  H5Sclose(h_space);
+}
+
 /**
  * @brief Writes a data array in given HDF5 group.
  *
@@ -274,22 +395,19 @@ void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int*
  * @param us The UnitSystem currently in use
  * @param convFactor The UnitConversionFactor for this array
  *
- * @todo A better version using HDF5 hyperslabs to write the file directly from the part array
- * will be written once the strucutres have been stabilized.
  *
  * Calls #error() if an error occurs.
  */
-void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enum DATA_TYPE type, int N, int dim, char* part_c, struct UnitSystem* us, enum UnitConversionFactor convFactor)
+void writeArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, long long N_total, long long offset, char* part_c)
 {
-  hid_t h_data=0, h_err=0, h_space=0;
+  hid_t h_data=0, h_err=0, h_memspace=0, h_filespace=0;
+  hsize_t shape[2], shape_total[2], offsets[2];
   void* temp = 0;
   int i=0, rank=0;
   const size_t typeSize = sizeOfType(type);
   const size_t copySize = typeSize * dim;
   const size_t partSize = sizeof(struct part);
   char* temp_c = 0;
-  hsize_t shape[2];
-  char buffer[150];
 
   /* message("Writing '%s' array...", name); */
 
@@ -303,59 +421,52 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
   for(i=0; i<N; ++i)
     memcpy(&temp_c[i*copySize], part_c+i*partSize, copySize);
 
-  /* Create data space */
-  h_space = H5Screate(H5S_SIMPLE);
-  if(h_space < 0)
-    {
-      error( "Error while creating data space for field '%s'." , name );
-    }
-  
+  /* Construct information for the hyperslab */
   if(dim > 1)
     {
       rank = 2;
       shape[0] = N; shape[1] = dim;
+      shape_total[0] = N_total; shape_total[1] = dim;
+      offsets[0] = offset; offsets[1] = 0;
     }
   else
     {
       rank = 1;
       shape[0] = N; shape[1] = 0;
+      shape_total[0] = N_total; shape_total[1] = 0;
+      offsets[0] = offset; offsets[1] = 0;
     }
+
   
-  /* Change shape of data space */
-  h_err = H5Sset_extent_simple(h_space, rank, shape, NULL);
+  /* Create data space in memory */
+  h_memspace = H5Screate(H5S_SIMPLE);
+  if(h_memspace < 0)
+      error( "Error while creating data space (memory) for field '%s'." , name );
+
+  /* Change shape of memory data space */
+  h_err = H5Sset_extent_simple(h_memspace, rank, shape, NULL);
   if(h_err < 0)
-    {
-      error( "Error while changing data space shape for field '%s'." , name );
-    }
+      error( "Error while changing data space (memory) shape for field '%s'." , name );
   
-  /* Create dataset */
-  h_data = H5Dcreate1(grp, name, hdf5Type(type), h_space, H5P_DEFAULT);
+  /* Open pre-existing data set */
+  h_data = H5Dopen(grp, name, H5P_DEFAULT);
   if(h_data < 0)
-    {
-      error( "Error while creating dataspace '%s'." , name );
-    }
-  
-  /* Write temporary buffer to HDF5 dataspace */
-  h_err = H5Dwrite(h_data, hdf5Type(type), h_space, H5S_ALL, H5P_DEFAULT, temp);
-  if(h_err < 0)
-    {
-      error( "Error while writing data array '%s'." , name );
-    }
+      error( "Error while opening dataset '%s'." , name );
 
-  /* Write XMF description for this data set */
-  writeXMFline(xmfFile, fileName, name, N, dim, type);
+  /* Select data space in that data set */
+  h_filespace = H5Dget_space(h_data);
+  H5Sselect_hyperslab(h_filespace, H5S_SELECT_SET, offsets, NULL, shape, NULL);
 
-  /* Write unit conversion factors for this data set */
-  conversionString( buffer, us, convFactor );
-  writeAttribute_d( h_data, "CGS conversion factor", conversionFactor( us, convFactor ) );
-  writeAttribute_f( h_data, "h-scale exponant", hFactor( us, convFactor ) );
-  writeAttribute_f( h_data, "a-scale exponant", aFactor( us, convFactor ) );
-  writeAttribute_s( h_data, "Conversion factor", buffer );
-  
+  /* Write temporary buffer to HDF5 dataspace */
+  h_err = H5Dwrite(h_data, hdf5Type(type), h_memspace, h_filespace, H5P_DEFAULT, temp);
+  if(h_err < 0)
+    error( "Error while writing data array '%s'." , name );
+    
   /* Free and close everything */
   free(temp);
   H5Dclose(h_data);
-  H5Sclose(h_space);
+  H5Sclose(h_memspace);
+  H5Sclose(h_filespace);
 }
 
 /**
@@ -374,7 +485,8 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
  * @param convFactor The UnitConversionFactor for this array
  *
  */
-#define writeArray(grp, fileName, xmfFile, name, type, N, dim, part, field, us, convFactor) writeArrayBackEnd(grp, fileName, xmfFile, name, type, N, dim, (char*)(&(part[0]).field), us, convFactor)
+#define writeArray(grp, name, type, N, dim, N_total, offset, part, field) writeArrayBackEnd(grp, name, type, N, dim, N_total, offset, (char*)(&(part[0]).field))
+
 
 /**
  * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor
@@ -390,15 +502,18 @@ void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enu
  * Calls #error() if an error occurs.
  *
  */
-void write_output (struct engine *e, struct UnitSystem* us)
-{
-  
+void write_output_serial ( struct engine* e, struct UnitSystem* us, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info )
+{  
   hid_t h_file=0, h_grp=0;
   int N = e->s->nr_parts;
   int periodic = e->s->periodic;
   int numParticles[6]={N,0};
   int numParticlesHighWord[6]={0};
+  unsigned int flagEntropy[6]={0};
+  long long N_total = 0, offset = 0;
+  double offset_d = 0., N_d = 0., N_total_d = 0.;
   int numFiles = 1;
+  int rank = 0;
   struct part* parts = e->s->parts;
   FILE* xmfFile = 0;
   static int outputCount = 0;
@@ -407,93 +522,151 @@ void write_output (struct engine *e, struct UnitSystem* us)
   char fileName[200];
   sprintf(fileName, "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 */
-  xmfFile = prepareXMFfile();
-
-  /* Write the part corresponding to this specific output */
-  writeXMFheader(xmfFile, N, fileName, e->time);
-
+  /* Compute offset in the file and total number of particles */
+  /* Done using double to allow for up to 2^50=10^15 particles */
+  N_d = (double)N;
+  MPI_Exscan(&N_d, &offset_d, 1, MPI_DOUBLE, MPI_SUM, comm);
+  N_total_d = offset_d + N_d;
+  MPI_Bcast(&N_total_d, 1, MPI_DOUBLE, mpi_size-1, comm);
+  if(N_total_d > 1.e15)
+    error("Error while computing the offest for parallel output: Simulation has more than 10^15 particles.\n");
+  N_total = (long long) N_total_d;
+  offset = (long long) offset_d;
 
-  /* Open file */
-  /* message("Opening file '%s'.", fileName); */
-  h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT,H5P_DEFAULT);
-  if(h_file < 0)
-    {
-      error( "Error while opening file '%s'." , fileName );
-    }
-
-  /* Open header to write simulation properties */
-  /* message("Writing runtime parameters..."); */
-  h_grp = H5Gcreate1(h_file, "/RuntimePars", 0);
-  if(h_grp < 0)
-    error("Error while creating runtime parameters group\n");
 
-  /* Write the relevant information */
-  writeAttribute(h_grp, "PeriodicBoundariesOn", INT, &periodic, 1);
+  /* Do common stuff first */
+  if ( mpi_rank == 0 ) {
 
-  /* Close runtime parameters */
-  H5Gclose(h_grp);
+    /* First time, we need to create the XMF file */
+    if(outputCount == 0)
+      createXMFfile();
+    
+    /* Prepare the XMF file for the new entry */
+    xmfFile = prepareXMFfile();
+    
+    /* Write the part corresponding to this specific output */
+    writeXMFheader(xmfFile, N_total, fileName, e->time);
+
+    /* Open file */
+    /* message("Opening file '%s'.", fileName); */
+    h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT,H5P_DEFAULT);
+    if(h_file < 0)
+      {
+	error( "Error while opening file '%s'." , fileName );
+      }
+
+    /* Open header to write simulation properties */
+    /* message("Writing runtime parameters..."); */
+    h_grp = H5Gcreate1(h_file, "/RuntimePars", 0);
+    if(h_grp < 0)
+      error("Error while creating runtime parameters group\n");
+
+    /* Write the relevant information */
+    writeAttribute(h_grp, "PeriodicBoundariesOn", INT, &periodic, 1);
+
+    /* Close runtime parameters */
+    H5Gclose(h_grp);
   
-  /* Open header to write simulation properties */
-  /* message("Writing file header..."); */
-  h_grp = H5Gcreate1(h_file, "/Header", 0);
-  if(h_grp < 0)
-    error("Error while creating file header\n");
+    /* Open header to write simulation properties */
+    /* message("Writing file header..."); */
+    h_grp = H5Gcreate1(h_file, "/Header", 0);
+    if(h_grp < 0)
+      error("Error while creating file header\n");
     
-  /* 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, "Time", DOUBLE, &e->time, 1);
-
-  /* GADGET-2 legacy values */
-  writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, 6);
-  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);
-  writeAttribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1);
-
-  /* Close header */
-  H5Gclose(h_grp);
-
-  /* Print the SPH parameters */
-  writeSPHflavour(h_file);
-
-  /* Print the system of Units */
-  writeUnitSystem(h_file, us);
+    /* Print the relevant information and print status */
+    writeAttribute(h_grp, "BoxSize", DOUBLE, e->s->dim, 3);
+    writeAttribute(h_grp, "Time", DOUBLE, &e->time, 1);
+
+    /* GADGET-2 legacy values */
+    numParticles[0] = (unsigned int) N_total ;
+    writeAttribute(h_grp, "NumPart_ThisFile", UINT, numParticles, 6);
+    writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, 6);
+    numParticlesHighWord[0] = (unsigned int) (N_total >> 32);
+    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, flagEntropy, 6);
+    writeAttribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1);
+
+    /* Close header */
+    H5Gclose(h_grp);
+
+    /* Print the SPH parameters */
+    writeSPHflavour(h_file);
+
+    /* Print the system of Units */
+    writeUnitSystem(h_file, us);
 		  
-  /* Create SPH particles group */
-  /* message("Writing particle arrays..."); */
-  h_grp = H5Gcreate1(h_file, "/PartType0", 0);
-  if(h_grp < 0)
-    error( "Error while creating particle group.\n");
-
-  /* Write arrays */
-  writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N, 3, parts, x, us, UNIT_CONV_LENGTH);
-  writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N, 3, parts, v, us, UNIT_CONV_SPEED);
-  writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N, 1, parts, mass, us, UNIT_CONV_MASS);
-  writeArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N, 1, parts, h, us, UNIT_CONV_LENGTH);
-  writeArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N, 1, parts, u, us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
-  writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts, id, us, UNIT_CONV_NO_UNITS);
-  writeArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N, 1, parts, dt, us, UNIT_CONV_TIME);
-  writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts, a, us, UNIT_CONV_ACCELERATION);
-  writeArray(h_grp, fileName, xmfFile, "Density", FLOAT, N, 1, parts, rho, us, UNIT_CONV_DENSITY);
-
-  /* Close particle group */
-  H5Gclose(h_grp);
-
-  /* Write LXMF file descriptor */
-  writeXMFfooter(xmfFile);
+    /* Create SPH particles group */
+    /* message("Writing particle arrays..."); */
+    h_grp = H5Gcreate1(h_file, "/PartType0", 0);
+    if(h_grp < 0)
+      error( "Error while creating particle group.\n");
+
+    /* Prepare the arrays in the file */
+    prepareArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N_total, 3, us, UNIT_CONV_LENGTH);
+    prepareArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N_total, 3, us, UNIT_CONV_SPEED);
+    prepareArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N_total, 1, us, UNIT_CONV_MASS);
+    prepareArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N_total, 1, us, UNIT_CONV_LENGTH);
+    prepareArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N_total, 1, us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+    prepareArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N_total, 1, us, UNIT_CONV_NO_UNITS);
+    prepareArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N_total, 1, us, UNIT_CONV_TIME);
+    prepareArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N_total, 3, us, UNIT_CONV_ACCELERATION);
+    prepareArray(h_grp, fileName, xmfFile, "Density", FLOAT, N_total, 1, us, UNIT_CONV_DENSITY);
+ 
+    /* Close particle group */
+    H5Gclose(h_grp);
+
+    /* Close file */
+    H5Fclose(h_file);
+
+    /* Write footer of LXMF file descriptor */
+    writeXMFfooter(xmfFile);
+  }
+
+
+
+  /* Now loop over ranks and write the data */
+  for ( rank = 0; rank < mpi_size ; ++ rank ) {
+
+    /* Is it this rank's turn to write ? */
+    if ( rank == mpi_rank ) {
+
+      h_file = H5Fopen(fileName, H5F_ACC_RDWR, H5P_DEFAULT);
+      if(h_file < 0)
+	error( "Error while opening file '%s' on rank %d." , fileName, mpi_rank );	
+
+      /* Open SPH particles group */
+      /* message("Reading particle arrays..."); */
+      h_grp = H5Gopen1(h_file, "/PartType0");
+      if(h_grp < 0)
+	error( "Error while opening particle group on rank %d.\n", mpi_rank);
+
+      /* Write arrays */
+      writeArray(h_grp, "Coordinates", DOUBLE, N, 3, N_total, offset, parts, x);
+      writeArray(h_grp, "Velocities", FLOAT, N, 3, N_total, offset, parts, v);
+      writeArray(h_grp, "Masses", FLOAT, N, 1, N_total, offset, parts, mass);
+      writeArray(h_grp, "SmoothingLength", FLOAT, N, 1, N_total, offset, parts, h);
+      writeArray(h_grp, "InternalEnergy", FLOAT, N, 1, N_total, offset, parts, u);
+      writeArray(h_grp, "ParticleIDs", ULONGLONG, N, 1, N_total, offset, parts, id);
+      writeArray(h_grp, "TimeStep", FLOAT, N, 1, N_total, offset, parts, dt);
+      writeArray(h_grp, "Acceleration", FLOAT, N, 3, N_total, offset, parts, a);
+      writeArray(h_grp, "Density", FLOAT, N, 1, N_total, offset, parts, rho);
+
+      /* Close particle group */
+      H5Gclose(h_grp);
+
+      /* Close file */
+      H5Fclose(h_file);
 
-  /* message("Done writing particles..."); */
+    }
 
-  /* Close file */
-  H5Fclose(h_file);
+    /* Wait for the read of the reading to complete */
+    MPI_Barrier(comm);
 
+  }
+
+  /* message("Done writing particles..."); */
   ++outputCount;
 }
 
diff --git a/src/serial_io.h b/src/serial_io.h
index a827a47373fdfbc01b5ff0e5d64faca39d316f6d..3349f221531ce7c4a2a290b121500e5d4336ed6b 100644
--- a/src/serial_io.h
+++ b/src/serial_io.h
@@ -18,11 +18,11 @@
  ******************************************************************************/
 
 
-#if defined(HAVE_HDF5) && !defined(WITH_MPI)
+#if defined(HAVE_HDF5) && defined(WITH_MPI) && !defined(HAVE_PARALLEL_HDF5)
 
-void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int* periodic);
+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 write_output ( struct engine* e, struct UnitSystem* us );
+void write_output_serial ( struct engine* e, struct UnitSystem* us, int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info );
 
 #endif
 
diff --git a/src/single_io.c b/src/single_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..485cb60aa51140682ef868d0323b31f00ce4ed9e
--- /dev/null
+++ b/src/single_io.c
@@ -0,0 +1,503 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Coypright (c) 2012 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/>.
+ * 
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+#if defined(HAVE_HDF5) && !defined(WITH_MPI)
+
+
+/* Some standard headers. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+#include <hdf5.h>
+#include <math.h>
+
+#include "const.h"
+#include "cycle.h"
+#include "lock.h"
+#include "task.h"
+#include "part.h"
+#include "space.h"
+#include "scheduler.h"
+#include "engine.h"
+#include "error.h"
+#include "kernel.h"
+#include "common_io.h"
+
+
+
+/*-----------------------------------------------------------------------------
+ * Routines reading an IC file
+ *-----------------------------------------------------------------------------*/
+
+/**
+ * @brief Reads a data array from a given HDF5 group.
+ *
+ * @param grp The group from which to read.
+ * @param name The name of the array to read.
+ * @param type The #DATA_TYPE of the attribute.
+ * @param N The number of particles.
+ * @param dim The dimension of the data (1 for scalar, 3 for vector)
+ * @param part_c A (char*) pointer on the first occurence of the field of interest in the parts array
+ * @param importance If COMPULSORY, the data must be present in the IC file. If OPTIONAL, the array will be zeroed when the data is not present.
+ *
+ * @todo A better version using HDF5 hyperslabs to read the file directly into the part array 
+ * will be written once the strucutres have been stabilized.
+ *  
+ * Calls #error() if an error occurs.
+ */
+void readArrayBackEnd(hid_t grp, char* name, enum DATA_TYPE type, int N, int dim, char* part_c, enum DATA_IMPORTANCE importance)
+{
+  hid_t h_data=0, h_err=0, h_type=0;
+  htri_t exist=0;
+  void* temp;
+  int i=0;
+  const size_t typeSize = sizeOfType(type);
+  const size_t copySize = typeSize * dim;
+  const size_t partSize = sizeof(struct part);
+  char* temp_c = 0;
+
+  /* Check whether the dataspace exists or not */
+  exist = H5Lexists(grp, name, 0);
+  if(exist < 0)
+    {
+      error( "Error while checking the existence of data set '%s'." , name );
+    }
+  else if(exist == 0)
+    {
+      if(importance == COMPULSORY)
+	{
+	  error( "Compulsory data set '%s' not present in the file." , name );
+	}
+      else
+	{
+	  /* message("Optional data set '%s' not present. Zeroing this particle field...", name);	   */
+	  
+	  for(i=0; i<N; ++i)
+	    memset(part_c+i*partSize, 0, copySize);
+	  
+	  return;
+	}
+   }
+
+  /* message( "Reading %s '%s' array...", importance == COMPULSORY ? "compulsory": "optional  ", name); */
+
+  /* Open data space */
+  h_data = H5Dopen1(grp, name);
+  if(h_data < 0)
+    {
+      error( "Error while opening data space '%s'." , name );
+    }
+
+  /* Check data type */
+  h_type = H5Dget_type(h_data);
+  if(h_type < 0)
+    error("Unable to retrieve data type from the file");
+  if(!H5Tequal(h_type, hdf5Type(type)))
+    error("Non-matching types between the code and the file");
+  
+  /* Allocate temporary buffer */
+  temp = malloc(N * dim * sizeOfType(type));
+  if(temp == NULL)
+    error("Unable to allocate memory for temporary buffer");
+
+  /* Read HDF5 dataspace in temporary buffer */
+  /* Dirty version that happens to work for vectors but should be improved */
+  /* Using HDF5 dataspaces would be better */
+  h_err = H5Dread(h_data, hdf5Type(type), H5S_ALL, H5S_ALL, H5P_DEFAULT, temp);
+  if(h_err < 0)
+    {
+      error( "Error while reading data array '%s'." , name );
+    }
+
+  /* Copy temporary buffer to particle data */
+  temp_c = temp;
+  for(i=0; i<N; ++i)
+    memcpy(part_c+i*partSize, &temp_c[i*copySize], copySize);
+  
+  /* Free and close everything */
+  free(temp);
+  H5Tclose(h_type);
+  H5Dclose(h_data);
+}
+
+/**
+ * @brief A helper macro to call the readArrayBackEnd function more easily.
+ *
+ * @param grp The group from which to read.
+ * @param name The name of the array to read.
+ * @param type The #DATA_TYPE of the attribute.
+ * @param N The number of particles.
+ * @param dim The dimension of the data (1 for scalar, 3 for vector)
+ * @param part The array of particles to fill
+ * @param field The name of the field (C code name as defined in part.h) to fill
+ * @param importance Is the data compulsory or not
+ *
+ */
+#define readArray(grp, name, type, N, dim, part, field, importance) readArrayBackEnd(grp, name, type, N, dim, (char*)(&(part[0]).field), importance)
+
+/**
+ * @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 periodic (output) 1 if the volume is periodic, 0 if not.
+ *
+ * Opens the HDF5 file fileName and reads the particles contained
+ * in the parts array. N is the returned number of particles found
+ * in the file.
+ *
+ * @warning Can not read snapshot distributed over more than 1 file !!!
+ * @todo Read snaphsots distributed in more than one file.
+ *
+ * Calls #error() if an error occurs.
+ *
+ */
+void read_ic_single ( char* fileName, double dim[3], struct part **parts,  int* N, 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*/
+
+  /* Open file */
+  /* message("Opening file '%s' as IC.", fileName); */
+  h_file = H5Fopen(fileName, H5F_ACC_RDONLY, H5P_DEFAULT);
+  if(h_file < 0)
+    {
+      error( "Error while opening file '%s'." , fileName );
+    }
+
+  /* Open header to read simulation properties */
+  /* message("Reading runtime parameters..."); */
+  h_grp = H5Gopen1(h_file, "/RuntimePars");
+  if(h_grp < 0)
+    error("Error while opening runtime parameters\n");
+
+  /* Read the relevant information */
+  readAttribute(h_grp, "PeriodicBoundariesOn", INT, periodic);
+
+  /* Close runtime parameters */
+  H5Gclose(h_grp);
+  
+  /* Open header to read simulation properties */
+  /* message("Reading file header..."); */
+  h_grp = H5Gopen1(h_file, "/Header");
+  if(h_grp < 0)
+    error("Error while opening file header\n");
+    
+  /* Read the relevant information and print status */
+  readAttribute(h_grp, "BoxSize", DOUBLE, boxSize);
+  readAttribute(h_grp, "NumPart_Total", UINT, numParticles);
+
+  *N = numParticles[0];
+  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]); */
+
+  /* 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) );
+
+  /* message("Allocated %8.2f MB for particles.", *N * sizeof(struct part) / (1024.*1024.)); */
+		  
+  /* Open SPH particles group */
+  /* message("Reading particle arrays..."); */
+  h_grp = H5Gopen1(h_file, "/PartType0");
+  if(h_grp < 0)
+    error( "Error while opening particle group.\n");
+
+  /* Read arrays */
+  readArray(h_grp, "Coordinates", DOUBLE, *N, 3, *parts, x, COMPULSORY);
+  readArray(h_grp, "Velocities", FLOAT, *N, 3, *parts, v, COMPULSORY);
+  readArray(h_grp, "Masses", FLOAT, *N, 1, *parts, mass, COMPULSORY);
+  readArray(h_grp, "SmoothingLength", FLOAT, *N, 1, *parts, h, COMPULSORY);
+  readArray(h_grp, "InternalEnergy", FLOAT, *N, 1, *parts, u, COMPULSORY);
+  readArray(h_grp, "ParticleIDs", ULONGLONG, *N, 1, *parts, id, COMPULSORY);
+  readArray(h_grp, "TimeStep", FLOAT, *N, 1, *parts, dt, OPTIONAL);
+  readArray(h_grp, "Acceleration", FLOAT, *N, 3, *parts, a, OPTIONAL);
+  readArray(h_grp, "Density", FLOAT, *N, 1, *parts, rho, OPTIONAL );
+
+  /* Close particle group */
+  H5Gclose(h_grp);
+
+  /* message("Done Reading particles..."); */
+
+  /* Close file */
+  H5Fclose(h_file);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * Routines writing an output file
+ *-----------------------------------------------------------------------------*/
+
+/**
+ * @brief Writes a data array in given HDF5 group.
+ *
+ * @param grp The group in which to write.
+ * @param fileName The name of the file in which the data is written
+ * @param xmfFile The FILE used to write the XMF description
+ * @param name The name of the array to write.
+ * @param type The #DATA_TYPE of the array.
+ * @param N The number of particles to write.
+ * @param dim The dimension of the data (1 for scalar, 3 for vector)
+ * @param part_c A (char*) pointer on the first occurence of the field of interest in the parts array
+ * @param us The UnitSystem currently in use
+ * @param convFactor The UnitConversionFactor for this array
+ *
+ * @todo A better version using HDF5 hyperslabs to write the file directly from the part array
+ * will be written once the strucutres have been stabilized.
+ *
+ * Calls #error() if an error occurs.
+ */
+void writeArrayBackEnd(hid_t grp, char* fileName, FILE* xmfFile, char* name, enum DATA_TYPE type, int N, int dim, char* part_c, struct UnitSystem* us, enum UnitConversionFactor convFactor)
+{
+  hid_t h_data=0, h_err=0, h_space=0;
+  void* temp = 0;
+  int i=0, rank=0;
+  const size_t typeSize = sizeOfType(type);
+  const size_t copySize = typeSize * dim;
+  const size_t partSize = sizeof(struct part);
+  char* temp_c = 0;
+  hsize_t shape[2];
+  char buffer[150];
+
+  /* message("Writing '%s' array...", name); */
+
+  /* Allocate temporary buffer */
+  temp = malloc(N * dim * sizeOfType(type));
+  if(temp == NULL)
+    error("Unable to allocate memory for temporary buffer");
+
+  /* Copy particle data to temporary buffer */
+  temp_c = temp;
+  for(i=0; i<N; ++i)
+    memcpy(&temp_c[i*copySize], part_c+i*partSize, copySize);
+
+  /* Create data space */
+  h_space = H5Screate(H5S_SIMPLE);
+  if(h_space < 0)
+    {
+      error( "Error while creating data space for field '%s'." , name );
+    }
+  
+  if(dim > 1)
+    {
+      rank = 2;
+      shape[0] = N; shape[1] = dim;
+    }
+  else
+    {
+      rank = 1;
+      shape[0] = N; shape[1] = 0;
+    }
+  
+  /* Change shape of data space */
+  h_err = H5Sset_extent_simple(h_space, rank, shape, NULL);
+  if(h_err < 0)
+    {
+      error( "Error while changing data space shape for field '%s'." , name );
+    }
+  
+  /* Create dataset */
+  h_data = H5Dcreate1(grp, name, hdf5Type(type), h_space, H5P_DEFAULT);
+  if(h_data < 0)
+    {
+      error( "Error while creating dataspace '%s'." , name );
+    }
+  
+  /* Write temporary buffer to HDF5 dataspace */
+  h_err = H5Dwrite(h_data, hdf5Type(type), h_space, H5S_ALL, H5P_DEFAULT, temp);
+  if(h_err < 0)
+    {
+      error( "Error while writing data array '%s'." , name );
+    }
+
+  /* Write XMF description for this data set */
+  writeXMFline(xmfFile, fileName, name, N, dim, type);
+
+  /* Write unit conversion factors for this data set */
+  conversionString( buffer, us, convFactor );
+  writeAttribute_d( h_data, "CGS conversion factor", conversionFactor( us, convFactor ) );
+  writeAttribute_f( h_data, "h-scale exponant", hFactor( us, convFactor ) );
+  writeAttribute_f( h_data, "a-scale exponant", aFactor( us, convFactor ) );
+  writeAttribute_s( h_data, "Conversion factor", buffer );
+  
+  /* Free and close everything */
+  free(temp);
+  H5Dclose(h_data);
+  H5Sclose(h_space);
+}
+
+/**
+ * @brief A helper macro to call the readArrayBackEnd function more easily.
+ *
+ * @param grp The group in which to write.
+ * @param fileName The name of the file in which the data is written
+ * @param xmfFile The FILE used to write the XMF description
+ * @param name The name of the array to write.
+ * @param type The #DATA_TYPE of the array.
+ * @param N The number of particles to write.
+ * @param dim The dimension of the data (1 for scalar, 3 for vector)
+ * @param part A (char*) pointer on the first occurence of the field of interest in the parts array
+ * @param field The name (code name) of the field to read from.
+ * @param us The UnitSystem currently in use
+ * @param convFactor The UnitConversionFactor for this array
+ *
+ */
+#define writeArray(grp, fileName, xmfFile, name, type, N, dim, part, field, us, convFactor) writeArrayBackEnd(grp, fileName, xmfFile, name, type, N, dim, (char*)(&(part[0]).field), us, convFactor)
+
+/**
+ * @brief Writes an HDF5 output file (GADGET-3 type) with its XMF descriptor
+ *
+ * @param e The engine containing all the system.
+ * @param us The UnitSystem used for the conversion of units in the output
+ *
+ * Creates an HDF5 output file and writes the particles contained
+ * in the engine. If such a file already exists, it is erased and replaced
+ * by the new one. 
+ * The companion XMF file is also updated accordingly.
+ *
+ * Calls #error() if an error occurs.
+ *
+ */
+void write_output_single (struct engine *e, struct UnitSystem* us)
+{
+  
+  hid_t h_file=0, h_grp=0;
+  int N = e->s->nr_parts;
+  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;
+  static int outputCount = 0;
+  
+  /* File name */
+  char fileName[200];
+  sprintf(fileName, "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 */
+  xmfFile = prepareXMFfile();
+
+  /* Write the part corresponding to this specific output */
+  writeXMFheader(xmfFile, N, fileName, e->time);
+
+
+  /* Open file */
+  /* message("Opening file '%s'.", fileName); */
+  h_file = H5Fcreate(fileName, H5F_ACC_TRUNC, H5P_DEFAULT,H5P_DEFAULT);
+  if(h_file < 0)
+    {
+      error( "Error while opening file '%s'." , fileName );
+    }
+
+  /* Open header to write simulation properties */
+  /* message("Writing runtime parameters..."); */
+  h_grp = H5Gcreate1(h_file, "/RuntimePars", 0);
+  if(h_grp < 0)
+    error("Error while creating runtime parameters group\n");
+
+  /* Write the relevant information */
+  writeAttribute(h_grp, "PeriodicBoundariesOn", INT, &periodic, 1);
+
+  /* Close runtime parameters */
+  H5Gclose(h_grp);
+  
+  /* Open header to write simulation properties */
+  /* message("Writing file header..."); */
+  h_grp = H5Gcreate1(h_file, "/Header", 0);
+  if(h_grp < 0)
+    error("Error while creating file header\n");
+    
+  /* 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, "Time", DOUBLE, &e->time, 1);
+
+  /* GADGET-2 legacy values */
+  writeAttribute(h_grp, "NumPart_Total", UINT, numParticles, 6);
+  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);
+  writeAttribute(h_grp, "NumFilesPerSnapshot", INT, &numFiles, 1);
+
+  /* Close header */
+  H5Gclose(h_grp);
+
+  /* Print the SPH parameters */
+  writeSPHflavour(h_file);
+
+  /* Print the system of Units */
+  writeUnitSystem(h_file, us);
+		  
+  /* Create SPH particles group */
+  /* message("Writing particle arrays..."); */
+  h_grp = H5Gcreate1(h_file, "/PartType0", 0);
+  if(h_grp < 0)
+    error( "Error while creating particle group.\n");
+
+  /* Write arrays */
+  writeArray(h_grp, fileName, xmfFile, "Coordinates", DOUBLE, N, 3, parts, x, us, UNIT_CONV_LENGTH);
+  writeArray(h_grp, fileName, xmfFile, "Velocities", FLOAT, N, 3, parts, v, us, UNIT_CONV_SPEED);
+  writeArray(h_grp, fileName, xmfFile, "Masses", FLOAT, N, 1, parts, mass, us, UNIT_CONV_MASS);
+  writeArray(h_grp, fileName, xmfFile, "SmoothingLength", FLOAT, N, 1, parts, h, us, UNIT_CONV_LENGTH);
+  writeArray(h_grp, fileName, xmfFile, "InternalEnergy", FLOAT, N, 1, parts, u, us, UNIT_CONV_ENERGY_PER_UNIT_MASS);
+  writeArray(h_grp, fileName, xmfFile, "ParticleIDs", ULONGLONG, N, 1, parts, id, us, UNIT_CONV_NO_UNITS);
+  writeArray(h_grp, fileName, xmfFile, "TimeStep", FLOAT, N, 1, parts, dt, us, UNIT_CONV_TIME);
+  writeArray(h_grp, fileName, xmfFile, "Acceleration", FLOAT, N, 3, parts, a, us, UNIT_CONV_ACCELERATION);
+  writeArray(h_grp, fileName, xmfFile, "Density", FLOAT, N, 1, parts, rho, us, UNIT_CONV_DENSITY);
+
+  /* Close particle group */
+  H5Gclose(h_grp);
+
+  /* Write LXMF file descriptor */
+  writeXMFfooter(xmfFile);
+
+  /* message("Done writing particles..."); */
+
+  /* Close file */
+  H5Fclose(h_file);
+
+  ++outputCount;
+}
+
+
+#endif  /* HAVE_HDF5 */
+
+
diff --git a/src/single_io.h b/src/single_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..3cc58a46cc5398affd63e5d7e22b317ae79db3f5
--- /dev/null
+++ b/src/single_io.h
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Coypright (c) 2012 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/>.
+ * 
+ ******************************************************************************/
+
+
+#if defined(HAVE_HDF5) && !defined(WITH_MPI)
+
+void read_ic_single ( char* fileName, double dim[3], struct part **parts,  int* N, int* periodic);
+
+void write_output_single ( struct engine* e, struct UnitSystem* us );
+
+#endif
+
diff --git a/src/swift.h b/src/swift.h
index 098092b29006e89a32ffada43284d9047132dbe0..7652191b2e9cfb864cc64e157eeda98627cdccdc 100644
--- a/src/swift.h
+++ b/src/swift.h
@@ -38,6 +38,7 @@
 #include "runner.h"
 #include "engine.h"
 #include "units.h"
+#include "single_io.h"
 #include "serial_io.h"
 #include "parallel_io.h"
 #include "debug.h"
diff --git a/src/units.c b/src/units.c
index f0f526cca39ecc2e81ed10424875fe60a1f37084..ffca1974205936fe50dc770ba7eaa73895273737 100644
--- a/src/units.c
+++ b/src/units.c
@@ -47,7 +47,7 @@ void initUnitSystem(struct UnitSystem* us)
 {
   us->UnitMass_in_cgs = const_unit_mass_in_cgs;
   us->UnitLength_in_cgs = const_unit_length_in_cgs;
-  us->UnitTime_in_cgs = 1.d / (const_unit_velocity_in_cgs / const_unit_length_in_cgs );
+  us->UnitTime_in_cgs = 1. / ((double) const_unit_velocity_in_cgs / ( (double)const_unit_length_in_cgs ));
   us->UnitCurrent_in_cgs = 1.;
   us->UnitTemperature_in_cgs = 1.;
 }
@@ -257,8 +257,7 @@ double generalConversionFactor(struct UnitSystem* us, float baseUnitsExponants[5
 
   for(i = 0 ; i < 5 ; ++i )
     if(baseUnitsExponants[i] != 0)
-	factor *= pow( getBaseUnit( us, i )  , baseUnitsExponants[i] );
-
+      factor *= pow( getBaseUnit( us, i )  , baseUnitsExponants[i] );
   return factor;	
 }
 
diff --git a/src/units.h b/src/units.h
index d89b7ada3ccae1234aae24463d32dbf14378c40f..40eb88f4fa0255849a5bdab3d6bebd59c5d9dad7 100644
--- a/src/units.h
+++ b/src/units.h
@@ -43,11 +43,11 @@ struct UnitSystem
  */
 enum BaseUnits
   {
-    UNIT_MASS,
-    UNIT_LENGTH,
-    UNIT_TIME,
-    UNIT_CURRENT,
-    UNIT_TEMPERATURE
+    UNIT_MASS = 0,
+    UNIT_LENGTH = 1,
+    UNIT_TIME = 2,
+    UNIT_CURRENT = 3,
+    UNIT_TEMPERATURE = 4
   };