diff --git a/examples/Makefile.am b/examples/Makefile.am
index ce5007d37733daefea82bf46a4754954a5389921..361de521c051eea0613e524505648f68ef03021c 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -21,6 +21,8 @@ AUTOMAKE_OPTIONS=gnu
 # Add the source directory and debug to CFLAGS
 AM_CFLAGS = -g -Wall -Werror -I../src $(OPENMP_CFLAGS) -DCPU_TPS=2.67e9
 
+AM_LDFLAGS = $(HDF5_LDFLAGS)
+
 # Set-up the library
 bin_PROGRAMS = test
 
diff --git a/examples/test.c b/examples/test.c
index 0498a9d024108cceac4d4e637750a7803cdbf0fa..5bcec2a09b20d51a9d3497f98c8592a67d03f5c5 100644
--- a/examples/test.c
+++ b/examples/test.c
@@ -628,108 +628,176 @@ int main ( int argc , char *argv[] ) {
     int nr_threads = 1, nr_queues = -1, runs = 1;
     int data[2];
     double dim[3] = { 1.0 , 1.0 , 1.0 }, shift[3] = { 0.0 , 0.0 , 0.0 };
-    double r_min = 0.01, r_max = 0.1, h_max = -1.0 , scaling = 1.0, rho = 0.0;
+    double /*r_min = 0.01, r_max = 0.1,*/ h_max = -1.0 , scaling = 1.0, rho = 0.0;
     struct part *parts = NULL, *p;
     struct space s;
     struct engine e;
+    char ICfileName[200];
     ticks tic;
     
     /* Init the space. */
     bzero( &s , sizeof(struct space) );
-    
-    /* Parse the options. */
-    while ( ( c = getopt( argc , argv  , "a:b:p:d:N:c:h:v:m:s:t:q:r:i:m:z:" ) ) != -1 )
-        switch ( c ) {
-            case 'N':
-                if ( sscanf( optarg , "%d" , &N ) != 1 )
-                    error( "Error parsing number of particles." );
-                if ( posix_memalign( (void *)&parts , 32 , N * sizeof(struct part) ) != 0 )
-                    error( "Call to posix_memalign failed." );
-                for ( k = 0 ; k < N ; k++ ) {
-                    parts[k].x[0] = ((double)rand()) / RAND_MAX * dim[0];
-                    parts[k].x[1] = ((double)rand()) / RAND_MAX * dim[1];
-                    parts[k].x[2] = ((double)rand()) / RAND_MAX * dim[2];
-                    parts[k].id = k;
-                    parts[k].h = r_min + ((r_max - r_min)*rand())/RAND_MAX;
-                    parts[k].mass = 1.0f;
-                    parts[k].u = 1.0f;
-                    }
-                printf( "main: allocated memory for %i parts.\n" , N ); fflush(stdout);
-                break;
-            case 'a':
-                if ( sscanf( optarg , "%lf" , &scaling ) != 1 )
-                    error( "Error parsing cutoff scaling." );
-                printf( "main: scaling cutoff by %.3f.\n" , scaling ); fflush(stdout);
-                for ( k = 0 ; k < N ; k++ )
-                    parts[k].h *= scaling;
-                break;
-            case 'b':
-                if ( sscanf( optarg , "%lf %lf %lf" , &dim[0] , &dim[1] , &dim[2] ) != 3 )
-                    error( "Error parsing box dimensions." );
-                break;
-            case 'c':
-                printf( "main: reading parts from %s...\n" , optarg ); fflush(stdout);
-                if ( parts == NULL && posix_memalign( (void *)&parts , 16 , N * sizeof(struct part) ) != 0 )
-                    error( "Call to calloc failed." );
-                read_coords( optarg , parts , N );
-                break;
-            case 'd':
-                printf( "main: reading dt from %s...\n" , optarg ); fflush(stdout);
-                read_dt( optarg , parts , N );
-                break;
-            case 'h':
-                printf( "main: reading cutoffs from %s...\n" , optarg ); fflush(stdout);
-                read_cutoffs( optarg , parts , N );
-                break;
-            case 'i':
-                printf( "main: reading ids from %s...\n" , optarg ); fflush(stdout);
-                read_id( optarg , parts , N );
-                break;
-            case 'm':
-                if ( sscanf( optarg , "%lf" , &h_max ) != 1 )
-                    error( "Error parsing h_max." );
-                printf( "main: maximum h set to %e.\n" , h_max );
-                break;
-            case 'p':
-                if ( sscanf( optarg , "%d" , &periodic ) != 1 )
-                    error( "Error parsing periodicity." );
-                printf( "main: periodicity switched %s.\n" , periodic ? "on" : "off" );
-                break;
-            case 'q':
-                if ( sscanf( optarg , "%d" , &nr_queues ) != 1 )
-                    error( "Error parsing number of queues." );
-                break;
-            case 'r':
-                if ( sscanf( optarg , "%d" , &runs ) != 1 )
-                    error( "Error parsing number of runs." );
-                break;
-            case 's':
-                if ( sscanf( optarg , "%lf %lf %lf" , &shift[0] , &shift[1] , &shift[2] ) != 3 )
-                    error( "Error parsing shift." );
-                for ( k = 0 ; k < N ; k++ ) {
-                    parts[k].x[0] += shift[0];
-                    parts[k].x[1] += shift[1];
-                    parts[k].x[2] += shift[2];
-                    }
-                printf( "main: shifted parts by [ %.3f %.3f %.3f ].\n" , shift[0] , shift[1] , shift[2] );
-                break;
-            case 't':
-                if ( sscanf( optarg , "%d" , &nr_threads ) != 1 )
-                    error( "Error parsing number of threads." );
-                omp_set_num_threads( nr_threads );
-                break;
-            case 'z':
-                if ( sscanf( optarg , "%d" , &space_splitsize ) != 1 )
-                    error( "Error parsing split size." );
-                printf( "main: split size set to %i.\n" , space_splitsize );
-                break;
-            case '?':
-                error( "Unknown option." );
-                break;
-            }
+
+    /* Parse the options */
+    while ( ( c = getopt( argc , argv  , "f:a:m:s:t:q:r:z:" ) ) != -1 )
+      switch( c )
+	{
+	case 'f':
+	  if( !strcpy(ICfileName, optarg))
+	    error("Error parsing IC file name.");
+	  printf("main: IC to be read from file '%s'\n", ICfileName);
+	  break;
+	case 'a':
+	  if ( sscanf( optarg , "%lf" , &scaling ) != 1 )
+	    error( "Error parsing cutoff scaling." );
+	  printf( "main: scaling cutoff by %.3f.\n" , scaling ); fflush(stdout);
+	  break;
+	case 'm':
+	  if ( sscanf( optarg , "%lf" , &h_max ) != 1 )
+	    error( "Error parsing h_max." );
+	  printf( "main: maximum h set to %e.\n" , h_max ); fflush(stdout);
+	  break;
+	case 'q':
+	  if ( sscanf( optarg , "%d" , &nr_queues ) != 1 )
+	    error( "Error parsing number of queues." );
+	  break;
+	case 'r':
+	  if ( sscanf( optarg , "%d" , &runs ) != 1 )
+	    error( "Error parsing number of runs." );
+	  break;
+	case 's':
+	  if ( sscanf( optarg , "%lf %lf %lf" , &shift[0] , &shift[1] , &shift[2] ) != 3 )
+	    error( "Error parsing shift." );
+	  printf( "main: will shift parts by [ %.3f %.3f %.3f ].\n" , shift[0] , shift[1] , shift[2] );
+	  break;
+	case 't':
+	  if ( sscanf( optarg , "%d" , &nr_threads ) != 1 )
+	    error( "Error parsing number of threads." );
+	  omp_set_num_threads( nr_threads );
+	  break;
+	case 'z':
+	  if ( sscanf( optarg , "%d" , &space_splitsize ) != 1 )
+	    error( "Error parsing split size." );
+	  printf( "main: split size set to %i.\n" , space_splitsize );
+	  break;
+	case '?':
+	  error( "Unknown option." );
+	  break;
+
+	}
+
+    /* while ( ( c = getopt( argc , argv  , "a:b:p:d:N:c:h:v:m:s:t:q:r:i:m:z:" ) ) != -1 ) */
+    /*     switch ( c ) { */
+    /*         case 'N': */
+    /*             if ( sscanf( optarg , "%d" , &N ) != 1 ) */
+    /*                 error( "Error parsing number of particles." ); */
+    /*             if ( posix_memalign( (void *)&parts , 32 , N * sizeof(struct part) ) != 0 ) */
+    /*                 error( "Call to posix_memalign failed." ); */
+    /*             for ( k = 0 ; k < N ; k++ ) { */
+    /*                 parts[k].x[0] = ((double)rand()) / RAND_MAX * dim[0]; */
+    /*                 parts[k].x[1] = ((double)rand()) / RAND_MAX * dim[1]; */
+    /*                 parts[k].x[2] = ((double)rand()) / RAND_MAX * dim[2]; */
+    /*                 parts[k].id = k; */
+    /*                 parts[k].h = r_min + ((r_max - r_min)*rand())/RAND_MAX; */
+    /*                 parts[k].mass = 1.0f; */
+    /*                 parts[k].u = 1.0f; */
+    /*                 } */
+    /*             printf( "main: allocated memory for %i parts.\n" , N ); fflush(stdout); */
+    /*             break; */
+    /*         case 'a': */
+    /*             if ( sscanf( optarg , "%lf" , &scaling ) != 1 ) */
+    /*                 error( "Error parsing cutoff scaling." ); */
+    /*             printf( "main: scaling cutoff by %.3f.\n" , scaling ); fflush(stdout); */
+    /*             for ( k = 0 ; k < N ; k++ ) */
+    /*                 parts[k].h *= scaling; */
+    /*             break; */
+    /*         case 'b': */
+    /*             if ( sscanf( optarg , "%lf %lf %lf" , &dim[0] , &dim[1] , &dim[2] ) != 3 ) */
+    /*                 error( "Error parsing box dimensions." ); */
+    /*             break; */
+    /*         case 'c': */
+    /*             printf( "main: reading parts from %s...\n" , optarg ); fflush(stdout); */
+    /*             if ( parts == NULL && posix_memalign( (void *)&parts , 16 , N * sizeof(struct part) ) != 0 ) */
+    /*                 error( "Call to calloc failed." ); */
+    /*             read_coords( optarg , parts , N ); */
+    /*             break; */
+    /*         case 'd': */
+    /*             printf( "main: reading dt from %s...\n" , optarg ); fflush(stdout); */
+    /*             read_dt( optarg , parts , N ); */
+    /*             break; */
+    /*         case 'h': */
+    /*             printf( "main: reading cutoffs from %s...\n" , optarg ); fflush(stdout); */
+    /*             read_cutoffs( optarg , parts , N ); */
+    /*             break; */
+    /*         case 'i': */
+    /*             printf( "main: reading ids from %s...\n" , optarg ); fflush(stdout); */
+    /*             read_id( optarg , parts , N ); */
+    /*             break; */
+    /*         case 'm': */
+    /*             if ( sscanf( optarg , "%lf" , &h_max ) != 1 ) */
+    /*                 error( "Error parsing h_max." ); */
+    /*             printf( "main: maximum h set to %e.\n" , h_max ); */
+    /*             break; */
+    /*         case 'p': */
+    /*             if ( sscanf( optarg , "%d" , &periodic ) != 1 ) */
+    /*                 error( "Error parsing periodicity." ); */
+    /*             printf( "main: periodicity switched %s.\n" , periodic ? "on" : "off" ); */
+    /*             break; */
+    /*         case 'q': */
+    /*             if ( sscanf( optarg , "%d" , &nr_queues ) != 1 ) */
+    /*                 error( "Error parsing number of queues." ); */
+    /*             break; */
+    /*         case 'r': */
+    /*             if ( sscanf( optarg , "%d" , &runs ) != 1 ) */
+    /*                 error( "Error parsing number of runs." ); */
+    /*             break; */
+    /*         case 's': */
+    /*             if ( sscanf( optarg , "%lf %lf %lf" , &shift[0] , &shift[1] , &shift[2] ) != 3 ) */
+    /*                 error( "Error parsing shift." ); */
+    /*             for ( k = 0 ; k < N ; k++ ) { */
+    /*                 parts[k].x[0] += shift[0]; */
+    /*                 parts[k].x[1] += shift[1]; */
+    /*                 parts[k].x[2] += shift[2]; */
+    /*                 } */
+    /*             printf( "main: shifted parts by [ %.3f %.3f %.3f ].\n" , shift[0] , shift[1] , shift[2] ); */
+    /*             break; */
+    /*         case 't': */
+    /*             if ( sscanf( optarg , "%d" , &nr_threads ) != 1 ) */
+    /*                 error( "Error parsing number of threads." ); */
+    /*             omp_set_num_threads( nr_threads ); */
+    /*             break; */
+    /*         case 'z': */
+    /*             if ( sscanf( optarg , "%d" , &space_splitsize ) != 1 ) */
+    /*                 error( "Error parsing split size." ); */
+    /*             printf( "main: split size set to %i.\n" , space_splitsize ); */
+    /*             break; */
+    /*         case '?': */
+    /*             error( "Unknown option." ); */
+    /*             break; */
+    /*         } */
             
+
     /* How large are the parts? */
-    printf( "main: sizeof(struct part) is %li bytes.\n" , (long int)sizeof( struct part ) );
+    printf( "main: sizeof(struct part) is %li bytes.\n" , (long int)sizeof( struct part ));
+
+    /* Read particles and space information from (GADGET) IC */
+    tic = getticks();
+    read_ic(ICfileName, dim, &parts, &N, &periodic);
+    printf( "main: reading particle properties took %.3f ms.\n" , ((double)(getticks() - tic)) / CPU_TPS * 1000 ); fflush(stdout);
+    
+    /* Apply h scaling */
+    if(scaling != 1.0)
+      for ( k = 0 ; k < N ; k++ )
+	parts[k].h *= scaling;
+    
+    /* Apply shift */
+    if(shift[0] !=0 || shift[1] !=0 || shift[2] !=0 )
+      for ( k = 0 ; k < N ; k++ ) {
+	parts[k].x[0] += shift[0];
+	parts[k].x[1] += shift[1];
+	parts[k].x[2] += shift[2];
+      }
+
             
     /* Dump the kernel to make sure its ok. */
     // kernel_dump( 100 );
diff --git a/src/Makefile.am b/src/Makefile.am
index addcde017e28d45a15efcc94ab77576b7a90755e..33907eb666c96b038a9cd7a1e89abfc7df847167 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS=gnu
 AM_CFLAGS = -g -O3 -Wall -Werror -ffast-math -fstrict-aliasing $(SIMD_FLAGS) $(CFLAGS) $(OPENMP_CFLAGS) -DTIMER -DCOUNTER -DCPU_TPS=2.67e9
 
 # Assign a "safe" version number
-AM_LDFLAGS = $(LAPACK_LIBS) $(BLAS_LIBS) -version-info 0:0:0
+AM_LDFLAGS = $(LAPACK_LIBS) $(BLAS_LIBS) $(HDF5_LDFLAGS) -version-info 0:0:0
 
 # Build the libgadgetsmp library
 lib_LTLIBRARIES = libgadgetsmp.la
@@ -32,3 +32,10 @@ libgadgetsmp_la_SOURCES = space.c runner.c queue.c task.c cell.c engine.c ic.c
 include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \
     engine.h gadgetsmp.h ic.h
 
+# Set-up the library
+#bin_PROGRAMS = test
+
+# Sources for test
+#test_SOURCES = main.c
+#test_CFLAGS = -DCOUNTER -DTIMER $(AM_CFLAGS)
+#test_LDADD = ../src/.libs/libgadgetsmp.a
diff --git a/src/gadgetsmp.h b/src/gadgetsmp.h
index 3193cc8200cab4906a027faa775659e128cf3d62..67a01137a8b0f61b7bdfad57465a26e1890eaba5 100644
--- a/src/gadgetsmp.h
+++ b/src/gadgetsmp.h
@@ -32,4 +32,4 @@
 #include "runner_iact.h"
 #include "engine.h"
 #include "runner.h"
-
+#include "ic.h"
diff --git a/src/ic.c b/src/ic.c
index 315395fa26760474c767e6f509b725b2e08bb01b..11025277e2443d0cfdf0d289df098b45f0f55b2b 100644
--- a/src/ic.c
+++ b/src/ic.c
@@ -22,31 +22,287 @@
 
 #ifdef HAVE_HDF5
 
+
 /* Some standard headers. */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stddef.h>
 #include <hdf5.h>
 
+
 #include "task.h"
 #include "lock.h"
 #include "part.h"
 #include "space.h"
 
+/* Error macro. */
+#define error(s) { printf( "%s:%s():%i: %s\n" , __FILE__ , __FUNCTION__ , __LINE__ , s ); abort(); }
+
+
+/**
+ * @brief The different types of data used in the GADGET IC files.
+ *
+ * (This is admittedly a poor substitute to C++ templates...)
+ */
+enum DATA_TYPE{INT, LONG, LONGLONG, UINT, ULONG, ULONGLONG, FLOAT, DOUBLE};
+
+/**
+ * @brief Converts a C data type to the HDF5 equivalent. 
+ *
+ * This function is a trivial wrapper around the HDF5 types but allows
+ * to change the exact storage types matching the code types in a transparent way.
+ */
+hid_t hdf5Type(enum DATA_TYPE type)
+{
+  switch(type)
+    {
+    case INT: return H5T_NATIVE_INT;
+    case UINT: return H5T_NATIVE_UINT;
+    case LONG: return H5T_NATIVE_LONG;
+    case ULONG: return H5T_NATIVE_ULONG;
+    case LONGLONG: return H5T_NATIVE_LLONG;
+    case ULONGLONG: return H5T_NATIVE_ULLONG;
+    case FLOAT: return H5T_NATIVE_FLOAT;
+    case DOUBLE: return H5T_NATIVE_DOUBLE;
+    default: error("Unknown type");
+    }
+}
+
+
+/**
+ * @brief Returns the memory size of the data type
+ */
+size_t sizeOfType(enum DATA_TYPE type)
+{
+  switch(type)
+    {
+    case INT: return sizeof(int);
+    case UINT: return sizeof(unsigned int);
+    case LONG: return sizeof(long);
+    case ULONG: return sizeof(unsigned long);
+    case LONGLONG: return sizeof(long long);
+    case ULONGLONG: return sizeof(unsigned long long);
+    case FLOAT: return sizeof(float);
+    case DOUBLE: return sizeof(double);
+    default: error("Unknown type");
+    }
+}
+
+
+/**
+ * @brief Reads an attribute from a given HDF5 group.
+ *
+ * @param grp The group from which to read.
+ * @param name The name of the attribute to read.
+ * @param type The #DATA_TYPE of the attribute.
+ * @param data (output) The attribute read from the HDF5 group.
+ *
+ * Calls #error() if an error occurs.
+ */
+void readAttribute(hid_t grp, char* name, enum DATA_TYPE type, void* data)
+{
+  hid_t h_attr=0, h_err=0;
+
+  h_attr = H5Aopen(grp, name, H5P_DEFAULT);
+  if(h_attr < 0)
+    {
+      char buf[100];
+      sprintf(buf, "Error while opening attribute '%s'\n", name);
+      error(buf);
+    }
+
+  h_err = H5Aread(h_attr, hdf5Type(type), data);
+  if(h_err < 0)
+    {
+      char buf[100];
+      sprintf(buf, "Error while reading attribute '%s'\n", name);
+      error(buf);
+    }
+
+  H5Aclose(h_attr);
+}
+
+
+/**
+ * @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
+ *
+ * @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)
+{
+  hid_t h_data=0, h_err=0, h_type=0;
+  void* temp;
+  int i=0;
+  size_t typeSize = sizeOfType(type);
+  size_t copySize = typeSize * dim;
+  size_t partSize = sizeof(struct part);
+  char* temp_c = 0;
+
+  printf("readArray: Reading '%s' array...\n", name);
+
+  /* Open data space */
+  h_data = H5Dopen(grp, name);
+  if(h_data < 0)
+    {
+      char buf[100];
+      sprintf(buf, "Error while opening data space '%s'\n", name);
+      error(buf);
+    }
+
+  /* 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)
+    {
+      char buf[100];
+      sprintf(buf, "Error while reading data array '%s'\n", name);
+      error(buf);
+    }
+
+  /* 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
+ *
+ */
+#define readArray(grp, name, type, N, dim, part, field) readArrayBackEnd(grp, name, type, N, dim, (char*)(&(part[0]).field))
 
 /**
- * @brief Reads an HDF5 initial condition file 
+ * @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 ( char* fileName, struct part *parts,  int* N)
+void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int* periodic)
 {
+  hid_t h_file=0, h_grp=0;
+  double boxSize=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 */
+  printf("read_ic: Opening file '%s' as IC.\n", fileName);
+  h_file = H5Fopen(fileName, H5F_ACC_RDONLY, H5P_DEFAULT);
+  if(h_file < 0)
+    {
+      char buf[200];
+      sprintf(buf, "Error while opening file '%s'", fileName);
+      error(buf);
+    }
+
+  /* Open header to read simulation properties */
+  printf("read_ic: Reading runtime parameters...\n");
+  h_grp = H5Gopen(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 */
+  printf("read_ic: Reading file header...\n");
+  h_grp = H5Gopen(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] = dim[1] = dim[2] = boxSize;
 
+  printf("read_ic: Found %d particles in a %speriodic box of size [%f %f %f]\n", 
+  	 *N, (periodic ? "": "non-"), dim[0], dim[1], dim[2]);
+
+  /* Close header */
+  H5Gclose(h_grp);
+
+  /* Allocate memory to store particles */
+  if(posix_memalign( (void*)parts , 32 , *N * sizeof(struct part)) != 0)
+    error("Error while allocating memory for particles");
+
+  printf("read_ic: Allocated %8.2f MB for particles.\n", *N * sizeof(struct part) / (1024.*1024.));
+		  
+  /* Open SPH particles group */
+  printf("read_ic: Reading particle arrays...\n");
+  h_grp = H5Gopen(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);
+  readArray(h_grp, "Velocity", FLOAT, *N, 3, *parts, v);
+  readArray(h_grp, "Mass", FLOAT, *N, 1, *parts, mass);
+  readArray(h_grp, "SmoothingLength", FLOAT, *N, 1, *parts, h);
+  readArray(h_grp, "InternalEnergy", FLOAT, *N, 1, *parts, u);
+  readArray(h_grp, "ParticleIDs", ULONG, *N, 1, *parts, id);
+
+  /* Close particle group */
+  H5Gclose(h_grp);
+
+  printf("read_ic: Done Reading particles...\n");
+
+  /* Close file */
+  H5Fclose(h_file);
 }
 
 #endif  /* HAVE_HDF5 */
 
+
diff --git a/src/ic.h b/src/ic.h
index c604b9a66ba7de2a2a4558468cca55ce9d140750..10216bfb8c410695b6aadc14792e0f072be8d5a5 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -18,5 +18,8 @@
  ******************************************************************************/
 
 
-void read_ic ( char* fileName, struct space *s,  int* N);
-void space_init ( struct space *s , double dim[3] , struct part *parts , int N , int periodic , double h_max );
+
+
+void read_ic ( char* fileName, double dim[3], struct part **parts,  int* N, int* periodic);
+
+