diff --git a/examples/EAGLE_100/eagle_100.yml b/examples/EAGLE_100/eagle_100.yml
index 9cf1c9432ed6c79e4b91262cfdd30bad14833558..b3cbbccc7a89131fedc27aa1024ed8f460494582 100644
--- a/examples/EAGLE_100/eagle_100.yml
+++ b/examples/EAGLE_100/eagle_100.yml
@@ -37,15 +37,18 @@ Statistics:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration. 
-  epsilon:               0.001   # Softening length (in internal units).
-  theta:                 0.85      # Opening angle (Multipole acceptance criterion)
-  
+  eta:                    0.025    # Constant dimensionless multiplier for time integration. 
+  theta:                  0.85      # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
+
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   100      # (internal units)
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./EAGLE_ICs_100.hdf5     # The file to read
+  cleanup_h_factors: 1                 # Remove the h-factors inherited from Gadget
diff --git a/examples/EAGLE_100/run.sh b/examples/EAGLE_100/run.sh
index 6ef47d5d98172cc8a318242923ede37332bd5590..9310fc370acb51256b46e6ba0fb739fb2728caf9 100755
--- a/examples/EAGLE_100/run.sh
+++ b/examples/EAGLE_100/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -s -t 16 eagle_100.yml 2>&1 | tee output.log
+../swift -c -s -t 16 eagle_100.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_12/eagle_12.yml b/examples/EAGLE_12/eagle_12.yml
index d7aedf591a6988f89ad700f0a6729b3682bb6881..933f085ccd0bcbaf80a6ca83b7cb06c5763d4a20 100644
--- a/examples/EAGLE_12/eagle_12.yml
+++ b/examples/EAGLE_12/eagle_12.yml
@@ -38,16 +38,18 @@ Statistics:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration.
-  epsilon:               0.001    # Softening length (in internal units).
-  theta:                 0.85     # Opening angle (Multipole acceptance criterion)
+  eta:                    0.025     # Constant dimensionless multiplier for time integration.
+  theta:                  0.85      # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
   
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   100      # (internal units)
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./EAGLE_ICs_12.hdf5     # The file to read
-
+  cleanup_h_factors: 1               # Remove the h-factors inherited from Gadget
diff --git a/examples/EAGLE_12/run.sh b/examples/EAGLE_12/run.sh
index 21b965050ab1c786fd08c0dfd28b1612ac09e9e5..82d0e3e4d4418f0d00851f1279587a1ed45144df 100755
--- a/examples/EAGLE_12/run.sh
+++ b/examples/EAGLE_12/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -s -t 16 eagle_12.yml 2>&1 | tee output.log
+../swift -c -s -t 16 eagle_12.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_25/eagle_25.yml b/examples/EAGLE_25/eagle_25.yml
index 24daa13e06c2058d8a93243e9838b6f6b2cfe9bb..37ad91a29442825fcc843084cbbc4224203cab87 100644
--- a/examples/EAGLE_25/eagle_25.yml
+++ b/examples/EAGLE_25/eagle_25.yml
@@ -38,16 +38,19 @@ Statistics:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration. 
-  epsilon:               0.001    # Softening length (in internal units).
-  theta:                 0.85     # Opening angle (Multipole acceptance criterion)
-  
+  eta:                    0.025    # Constant dimensionless multiplier for time integration. 
+  theta:                  0.85     # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
+
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   100      # (internal units)
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./EAGLE_ICs_25.hdf5     # The file to read
+  cleanup_h_factors: 1               # Remove the h-factors inherited from Gadget
 
diff --git a/examples/EAGLE_25/run.sh b/examples/EAGLE_25/run.sh
index 21d0c7baf4482bdc6df83c552253a02d47432ba2..ae36e0d8e6ae6377682f259f506f720fbd585b29 100755
--- a/examples/EAGLE_25/run.sh
+++ b/examples/EAGLE_25/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -s -t 16 eagle_25.yml 2>&1 | tee output.log
+../swift -c -s -t 16 eagle_25.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_50/eagle_50.yml b/examples/EAGLE_50/eagle_50.yml
index adf64f6963e2a0bc545637757f5826efd0c027a9..021e6b8ab347d38b7ecaeddd5a198324ab57f31b 100644
--- a/examples/EAGLE_50/eagle_50.yml
+++ b/examples/EAGLE_50/eagle_50.yml
@@ -37,16 +37,19 @@ Statistics:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration.
-  epsilon:               0.001    # Softening length (in internal units).
-  theta:                 0.85     # Opening angle (Multipole acceptance criterion)
+  eta:                    0.025    # Constant dimensionless multiplier for time integration.
+  theta:                  0.85     # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
 
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   100      # (internal units)
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./EAGLE_ICs_50.hdf5     # The file to read
+  cleanup_h_factors: 1                # Remove the h-factors inherited from Gadget
 
diff --git a/examples/EAGLE_50/run.sh b/examples/EAGLE_50/run.sh
index 253e7e6eb11a04e1731c605e9ea067ba2bd13221..c3b93e84192ff58e445d4e164a4d6f66d19f85fe 100755
--- a/examples/EAGLE_50/run.sh
+++ b/examples/EAGLE_50/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -s -t 16 eagle_50.yml 2>&1 | tee output.log
+../swift -c -s -t 16 eagle_50.yml 2>&1 | tee output.log
 
diff --git a/examples/EAGLE_6/eagle_6.yml b/examples/EAGLE_6/eagle_6.yml
index d0055607d3cd7c1453e3b93ed8b21cd5ff2673d5..839ccf7e429248f7b7eb81635e20e43df7d1af9d 100644
--- a/examples/EAGLE_6/eagle_6.yml
+++ b/examples/EAGLE_6/eagle_6.yml
@@ -28,7 +28,7 @@ TimeIntegration:
 # Parameters governing the snapshots
 Snapshots:
   basename:            eagle # Common part of the name of output files
-  time_first:          0.    # Time of the first output (in internal units)
+  time_first:          1.    # Time of the first output (in internal units)
   delta_time:          1e-3  # Time difference between consecutive outputs (in internal units)
   compression:         4
 
@@ -38,16 +38,19 @@ Statistics:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration.
-  epsilon:               0.001    # Softening length (in internal units).
-  theta:                 0.85     # Opening angle (Multipole acceptance criterion)
+  eta:                    0.025    # Constant dimensionless multiplier for time integration.
+  theta:                  0.85     # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
   
 # Parameters for the hydrodynamics scheme
 SPH:
   resolution_eta:        1.2348   # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel).
   CFL_condition:         0.1      # Courant-Friedrich-Levy condition for time integration.
+  minimal_temperature:   100      # (internal units)
 
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  ./EAGLE_ICs_6.hdf5     # The file to read
+  cleanup_h_factors: 1               # Remove the h-factors inherited from Gadget
 
diff --git a/examples/EAGLE_6/run.sh b/examples/EAGLE_6/run.sh
index d8e5592467a115460bb455ab31bb5e1f4017a948..3e1d21954d8402c9e1929119db50708859332b6c 100755
--- a/examples/EAGLE_6/run.sh
+++ b/examples/EAGLE_6/run.sh
@@ -7,5 +7,5 @@ then
     ./getIC.sh
 fi
 
-../swift -s -t 16 eagle_6.yml 2>&1 | tee output.log
+../swift -c -s -t 16 eagle_6.yml 2>&1 | tee output.log
 
diff --git a/examples/EvrardCollapse_3D/evrard.yml b/examples/EvrardCollapse_3D/evrard.yml
index 94cd6e7a95d2671f7021ae3cd2ba40477cd8e7fd..a2b39fb1e7fa36098abe720945ece4b611eb4fe8 100644
--- a/examples/EvrardCollapse_3D/evrard.yml
+++ b/examples/EvrardCollapse_3D/evrard.yml
@@ -31,11 +31,10 @@ SPH:
 
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration.
-  epsilon:               0.001      # Softening length (in internal units).
-  theta:                 0.9
-  a_smooth:              1.25     # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value).
-  r_cut:                 4.5      # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value).
+  eta:                    0.025    # Constant dimensionless multiplier for time integration.
+  theta:                  0.9
+  comoving_softening:     0.001    # Comoving softening length (in internal units).
+  max_physical_softening: 0.001    # Physical softening length (in internal units).
 
 # Parameters related to the initial conditions
 InitialConditions:
diff --git a/examples/SedovBlast_3D/sedov.yml b/examples/SedovBlast_3D/sedov.yml
index 057e5a18acba2a1e8211d40f15ffde35b2019a9b..2df2c432cef8afec49c687b643a872b06f9abb60 100644
--- a/examples/SedovBlast_3D/sedov.yml
+++ b/examples/SedovBlast_3D/sedov.yml
@@ -31,6 +31,6 @@ SPH:
 
 # Parameters related to the initial conditions
 InitialConditions:
-  file_name:  ./sedov.hdf5          # The file to read
-  h_scaling:           3.33
+  file_name:                    ./sedov.hdf5          
+  smoothing_length_scaling:     3.33
 
diff --git a/examples/main.c b/examples/main.c
index 80e4dfb479172d9e2bca6fb19ee676371d130afe..f490465822859bc991eb31b9a857753c85934d6a 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -484,7 +484,7 @@ int main(int argc, char *argv[]) {
 #endif
 
   /* Common variables for restart and IC sections. */
-  int clean_h_values = 0;
+  int clean_smoothing_length_values = 0;
   int flag_entropy_ICs = 0;
 
   /* Work out where we will read and write restart files. */
@@ -609,20 +609,32 @@ int main(int argc, char *argv[]) {
     if (myrank == 0 && with_cosmology) cosmology_print(&cosmo);
 
     /* Initialise the hydro properties */
-    if (with_hydro) hydro_props_init(&hydro_properties, params);
+    if (with_hydro)
+      hydro_props_init(&hydro_properties, &prog_const, &us, params);
     if (with_hydro) eos_init(&eos, params);
 
     /* Initialise the gravity properties */
-    if (with_self_gravity) gravity_props_init(&gravity_properties, params);
+    if (with_self_gravity)
+      gravity_props_init(&gravity_properties, params, &cosmo);
 
     /* Read particles and space information from (GADGET) ICs */
     char ICfileName[200] = "";
     parser_get_param_string(params, "InitialConditions:file_name", ICfileName);
     const int replicate =
         parser_get_opt_param_int(params, "InitialConditions:replicate", 1);
-    clean_h_values =
-        parser_get_opt_param_int(params, "InitialConditions:cleanup_h", 0);
+    clean_smoothing_length_values = parser_get_opt_param_int(
+        params, "InitialConditions:cleanup_smoothing_lengths", 0);
+    const int cleanup_h = parser_get_opt_param_int(
+        params, "InitialConditions:cleanup_h_factors", 0);
+    const int generate_gas_in_ics = parser_get_opt_param_int(
+        params, "InitialConditions:generate_gas_in_ics", 0);
+    if (generate_gas_in_ics && flag_entropy_ICs)
+      error("Can't generate gas if the entropy flag is set in the ICs.");
+    if (generate_gas_in_ics && !with_cosmology)
+      error("Can't generate gas if the run is not cosmological.");
     if (myrank == 0) message("Reading ICs from file '%s'", ICfileName);
+    if (myrank == 0 && cleanup_h)
+      message("Cleaning up h-factors (h=%f)", cosmo.h);
     fflush(stdout);
 
     /* Get ready to read particles of all kinds */
@@ -635,20 +647,20 @@ int main(int argc, char *argv[]) {
     read_ic_parallel(ICfileName, &us, dim, &parts, &gparts, &sparts, &Ngas,
                      &Ngpart, &Nspart, &periodic, &flag_entropy_ICs, with_hydro,
                      (with_external_gravity || with_self_gravity), with_stars,
-                     myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL,
-                     nr_threads, dry_run);
+                     cleanup_h, cosmo.h, myrank, nr_nodes, MPI_COMM_WORLD,
+                     MPI_INFO_NULL, nr_threads, dry_run);
 #else
     read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &sparts, &Ngas,
                    &Ngpart, &Nspart, &periodic, &flag_entropy_ICs, with_hydro,
                    (with_external_gravity || with_self_gravity), with_stars,
-                   myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads,
-                   dry_run);
+                   cleanup_h, cosmo.h, myrank, nr_nodes, MPI_COMM_WORLD,
+                   MPI_INFO_NULL, nr_threads, dry_run);
 #endif
 #else
     read_ic_single(ICfileName, &us, dim, &parts, &gparts, &sparts, &Ngas,
                    &Ngpart, &Nspart, &periodic, &flag_entropy_ICs, with_hydro,
                    (with_external_gravity || with_self_gravity), with_stars,
-                   nr_threads, dry_run);
+                   cleanup_h, cosmo.h, nr_threads, dry_run);
 #endif
     if (myrank == 0) {
       clocks_gettime(&toc);
@@ -667,6 +679,9 @@ int main(int argc, char *argv[]) {
       for (size_t k = 0; k < Ngpart; ++k)
         if (gparts[k].type == swift_type_gas) error("Linking problem");
     }
+
+    /* Check that the other links are correctly set */
+    part_verify_links(parts, gparts, sparts, Ngas, Ngpart, Nspart, 1);
 #endif
 
     /* Get the total number of particles across all nodes. */
@@ -690,8 +705,9 @@ int main(int argc, char *argv[]) {
 
     /* Initialize the space with these data. */
     if (myrank == 0) clocks_gettime(&tic);
-    space_init(&s, params, dim, parts, gparts, sparts, Ngas, Ngpart, Nspart,
-               periodic, replicate, with_self_gravity, talking, dry_run);
+    space_init(&s, params, &cosmo, dim, parts, gparts, sparts, Ngas, Ngpart,
+               Nspart, periodic, replicate, generate_gas_in_ics,
+               with_self_gravity, talking, dry_run);
 
     if (myrank == 0) {
       clocks_gettime(&toc);
@@ -836,7 +852,7 @@ int main(int argc, char *argv[]) {
 #endif
 
     /* Initialise the particles */
-    engine_init_particles(&e, flag_entropy_ICs, clean_h_values);
+    engine_init_particles(&e, flag_entropy_ICs, clean_smoothing_length_values);
 
     /* Write the state of the system before starting time integration. */
     engine_dump_snapshot(&e);
@@ -1000,6 +1016,24 @@ int main(int argc, char *argv[]) {
            (double)runner_hist_bins[k]);
 #endif
 
+  /* Write final time information */
+  if (myrank == 0) {
+
+    /* Print some information to the screen */
+    printf("  %6d %14e %14e %14e %4d %4d %12zu %12zu %12zu %21.3f %6d\n",
+           e.step, e.time, e.cosmology->a, e.time_step, e.min_active_bin,
+           e.max_active_bin, e.updates, e.g_updates, e.s_updates,
+           e.wallclock_time, e.step_props);
+    fflush(stdout);
+
+    fprintf(e.file_timesteps,
+            "  %6d %14e %14e %14e %4d %4d %12zu %12zu %12zu %21.3f %6d\n",
+            e.step, e.time, e.cosmology->a, e.time_step, e.min_active_bin,
+            e.max_active_bin, e.updates, e.g_updates, e.s_updates,
+            e.wallclock_time, e.step_props);
+    fflush(e.file_timesteps);
+  }
+
   /* Write final output. */
   engine_drift_all(&e);
   engine_print_stats(&e);
diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml
index 4784a877a21e698af28f72aab473ac9c3cad605e..0a81716a3e34bbb305916b1148a9d8199b84fa5a 100644
--- a/examples/parameter_example.yml
+++ b/examples/parameter_example.yml
@@ -30,15 +30,19 @@ SPH:
   h_max:                 10.      # (Optional) Maximal allowed smoothing length in internal units. Defaults to FLT_MAX if unspecified.
   max_volume_change:     1.4      # (Optional) Maximal allowed change of kernel volume over one time-step.
   max_ghost_iterations:  30       # (Optional) Maximal number of iterations allowed to converge towards the smoothing length.
-
+  initial_temperature:   0        # (Optional) Initial temperature (in internal units) to set the gas particles at start-up. Value is ignored if set to 0.
+  minimal_temperature:   0        # (Optional) Minimal temperature (in internal units) allowed for the gas particles. Value is ignored if set to 0.
+  H_mass_fraction:       0.76     # (Optional) Hydrogen mass fraction used for initial conversion from temp to internal energy.
+  
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:          0.025    # Constant dimensionless multiplier for time integration.
-  theta:        0.7      # Opening angle (Multipole acceptance criterion)
-  epsilon:      0.1      # Softening length (in internal units).
-  a_smooth:     1.25     # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value).
-  r_cut_max:    4.5      # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value).
-  r_cut_min:    0.1      # (Optional) Cut-off in number of top-level cells below which no truncation of FMM forces are performed (this is the default value).
+  eta:          0.025               # Constant dimensionless multiplier for time integration.
+  theta:        0.7                 # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.0026994 # Comoving softening length (in internal units).
+  max_physical_softening: 0.0007    # Physical softening length (in internal units).
+  a_smooth:     1.25                # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value).
+  r_cut_max:    4.5                 # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value).
+  r_cut_min:    0.1                 # (Optional) Cut-off in number of top-level cells below which no truncation of FMM forces are performed (this is the default value).
 
 # Parameters for the task scheduling
 Scheduler:
@@ -81,12 +85,14 @@ Statistics:
 # Parameters related to the initial conditions
 InitialConditions:
   file_name:  SedovBlast/sedov.hdf5 # The file to read
-  cleanup_h:   0                    # (Optional) Clean the values of h that are read in. Set to 1 to activate.
-  h_scaling:  1.                    # (Optional) A scaling factor to apply to all smoothing lengths in the ICs.
+  generate_gas_in_ics:         0    # (Optional) Generate gas particles from the DM-only ICs (e.g. from panphasia).
+  cleanup_h_factors:           0    # (Optional) Clean up the h-factors used in the ICs (e.g. in Gadget files).
+  cleanup_smoothing_lengths:   0    # (Optional) Clean the values of the smoothing lengths that are read in to remove stupid values. Set to 1 to activate.
+  smoothing_length_scaling:    1.   # (Optional) A scaling factor to apply to all smoothing lengths in the ICs.
   shift_x:    0.                    # (Optional) A shift to apply to all particles read from the ICs (in internal units).
   shift_y:    0.
   shift_z:    0.
-  replicate:  2                     # (Optional) Replicate all particles along each axis a given number of times. Default 1.
+  replicate:  2                     # (Optional) Replicate all particles along each axis a given integer number of times. Default 1.
 
 # Parameters controlling restarts
 Restarts:
diff --git a/src/cell.c b/src/cell.c
index b415cc077b569c84c85462634458e68aa5e4833a..ea036c97081e625c4e4ca2bb1d06cd9ea8251bd3 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -1081,23 +1081,6 @@ void cell_sanitize(struct cell *c, int treated) {
   c->h_max = h_max;
 }
 
-/**
- * @brief Converts hydro quantities to a valid state after the initial density
- * calculation
- *
- * @param c Cell to act upon
- * @param data Unused parameter
- */
-void cell_convert_hydro(struct cell *c, void *data) {
-
-  struct part *p = c->parts;
-  struct xpart *xp = c->xparts;
-
-  for (int i = 0; i < c->count; ++i) {
-    hydro_convert_quantities(&p[i], &xp[i]);
-  }
-}
-
 /**
  * @brief Cleans the links in a given cell.
  *
diff --git a/src/cell.h b/src/cell.h
index 91663d45bf048fff6e4bbf02d404ec62d216365b..87af742baf935668b0f065e70f065b978b6c9b9f 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -492,7 +492,6 @@ int cell_getsize(struct cell *c);
 int cell_link_parts(struct cell *c, struct part *parts);
 int cell_link_gparts(struct cell *c, struct gpart *gparts);
 int cell_link_sparts(struct cell *c, struct spart *sparts);
-void cell_convert_hydro(struct cell *c, void *data);
 void cell_clean_links(struct cell *c, void *data);
 void cell_make_multipoles(struct cell *c, integertime_t ti_current);
 void cell_check_multipole(struct cell *c, void *data);
diff --git a/src/common_io.c b/src/common_io.c
index 67326817397118568e060f5dff49421bb32fba4d..19adc57fbd51972336840669dab473f846d23dee 100644
--- a/src/common_io.c
+++ b/src/common_io.c
@@ -457,6 +457,7 @@ void io_convert_part_f_mapper(void* restrict temp, int N,
 
   const struct io_props props = *((const struct io_props*)extra_data);
   const struct part* restrict parts = props.parts;
+  const struct xpart* restrict xparts = props.xparts;
   const struct engine* e = props.e;
   const size_t dim = props.dimension;
 
@@ -465,7 +466,8 @@ void io_convert_part_f_mapper(void* restrict temp, int N,
   const ptrdiff_t delta = (temp_f - props.start_temp_f) / dim;
 
   for (int i = 0; i < N; i++)
-    props.convert_part_f(e, parts + delta + i, &temp_f[i * dim]);
+    props.convert_part_f(e, parts + delta + i, xparts + delta + i,
+                         &temp_f[i * dim]);
 }
 
 /**
@@ -477,6 +479,7 @@ void io_convert_part_d_mapper(void* restrict temp, int N,
 
   const struct io_props props = *((const struct io_props*)extra_data);
   const struct part* restrict parts = props.parts;
+  const struct xpart* restrict xparts = props.xparts;
   const struct engine* e = props.e;
   const size_t dim = props.dimension;
 
@@ -485,7 +488,8 @@ void io_convert_part_d_mapper(void* restrict temp, int N,
   const ptrdiff_t delta = (temp_d - props.start_temp_d) / dim;
 
   for (int i = 0; i < N; i++)
-    props.convert_part_d(e, parts + delta + i, &temp_d[i * dim]);
+    props.convert_part_d(e, parts + delta + i, xparts + delta + i,
+                         &temp_d[i * dim]);
 }
 
 /**
@@ -704,7 +708,7 @@ void io_duplicate_hydro_gparts_mapper(void* restrict data, int Ngas,
     gparts[i + Ndm].type = swift_type_gas;
 
     /* Link the particles */
-    gparts[i + Ndm].id_or_neg_offset = -i;
+    gparts[i + Ndm].id_or_neg_offset = -(long long)(offset + i);
     parts[i].gpart = &gparts[i + Ndm];
   }
 }
@@ -760,7 +764,7 @@ void io_duplicate_hydro_sparts_mapper(void* restrict data, int Nstars,
     gparts[i + Ndm].type = swift_type_star;
 
     /* Link the particles */
-    gparts[i + Ndm].id_or_neg_offset = -i;
+    gparts[i + Ndm].id_or_neg_offset = -(long long)(offset + i);
     sparts[i].gpart = &gparts[i + Ndm];
   }
 }
diff --git a/src/cosmology.c b/src/cosmology.c
index b1bf71ad25451d2185d911320fb757193e990945..a5034240d07b9b9bf401d470c0bacbf6962a8006 100644
--- a/src/cosmology.c
+++ b/src/cosmology.c
@@ -130,9 +130,11 @@ double cosmology_get_time_since_big_bang(const struct cosmology *c, double a) {
  * @brief Update the cosmological parameters to the current simulation time.
  *
  * @param c The #cosmology struct.
+ * @param phys_const The physical constants in the internal units.
  * @param ti_current The current (integer) time.
  */
-void cosmology_update(struct cosmology *c, integertime_t ti_current) {
+void cosmology_update(struct cosmology *c, const struct phys_const *phys_const,
+                      integertime_t ti_current) {
 
   /* Get scale factor and powers of it */
   const double a = c->a_begin * exp(ti_current * c->time_base);
@@ -173,6 +175,10 @@ void cosmology_update(struct cosmology *c, integertime_t ti_current) {
   /* Expansion rate */
   c->a_dot = c->H * c->a;
 
+  /* Critical density */
+  c->critical_density =
+      3. * c->H * c->H / (8. * M_PI * phys_const->const_newton_G);
+
   /* Time-step conversion factor */
   c->time_step_factor = c->H;
 
@@ -284,8 +290,6 @@ double time_integrand(double a, void *param) {
  */
 void cosmology_init_tables(struct cosmology *c) {
 
-  const ticks tic = getticks();
-
 #ifdef HAVE_LIBGSL
 
   /* Retrieve some constants */
@@ -373,9 +377,6 @@ void cosmology_init_tables(struct cosmology *c) {
   error("Code not compiled with GSL. Can't compute cosmology integrals.");
 
 #endif
-
-  message("took %.3f %s.", clocks_from_ticks(getticks() - tic),
-          clocks_getunit());
 }
 
 /**
@@ -431,7 +432,7 @@ void cosmology_init(const struct swift_params *params,
   cosmology_init_tables(c);
 
   /* Set remaining variables to alid values */
-  cosmology_update(c, 0);
+  cosmology_update(c, phys_const, 0);
 
   /* Update the times */
   c->time_begin = cosmology_get_time_since_big_bang(c, c->a_begin);
@@ -454,7 +455,7 @@ void cosmology_init_no_cosmo(struct cosmology *c) {
   c->Omega_b = 0.;
   c->w_0 = 0.;
   c->w_a = 0.;
-  c->h = 0.;
+  c->h = 1.;
   c->w = 0.;
 
   c->a_begin = 1.;
@@ -474,6 +475,8 @@ void cosmology_init_no_cosmo(struct cosmology *c) {
   c->a_factor_hydro_accel = 1.;
   c->a_factor_grav_accel = 1.;
 
+  c->critical_density = 0.;
+
   c->time_step_factor = 1.;
 
   c->a_dot = 0.;
diff --git a/src/cosmology.h b/src/cosmology.h
index b541e20fa1dd4f55422f9ff1d0952783d8de0ad7..109b80a57d8dbc4eb942dd4ecbbc0db84198100b 100644
--- a/src/cosmology.h
+++ b/src/cosmology.h
@@ -70,6 +70,9 @@ struct cosmology {
   /*! Hubble constant at the current redshift (in internal units) */
   double H;
 
+  /*! The critical density at the current redshift (in internal units) */
+  double critical_density;
+
   /*! Conversion factor from internal time-step size to cosmological step */
   double time_step_factor;
 
@@ -160,7 +163,8 @@ struct cosmology {
   double universe_age_at_present_day;
 };
 
-void cosmology_update(struct cosmology *c, integertime_t ti_current);
+void cosmology_update(struct cosmology *c, const struct phys_const *phys_const,
+                      integertime_t ti_current);
 
 double cosmology_get_drift_factor(const struct cosmology *cosmo,
                                   integertime_t ti_start, integertime_t ti_end);
diff --git a/src/engine.c b/src/engine.c
index 18a3d4d39d390e435d1a6a5c4ee8b9fbdbc1506b..b66ceb4037f4de87252ce3203d0f7c2933d9ffb9 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -3665,10 +3665,10 @@ int engine_estimate_nr_tasks(struct engine *e) {
  * @brief Rebuild the space and tasks.
  *
  * @param e The #engine.
- * @param clean_h_values Are we cleaning up the values of h before building
- * the tasks ?
+ * @param clean_smoothing_length_values Are we cleaning up the values of
+ * the smoothing lengths before building the tasks ?
  */
-void engine_rebuild(struct engine *e, int clean_h_values) {
+void engine_rebuild(struct engine *e, int clean_smoothing_length_values) {
 
   const ticks tic = getticks();
 
@@ -3679,7 +3679,7 @@ void engine_rebuild(struct engine *e, int clean_h_values) {
   space_rebuild(e->s, e->verbose);
 
   /* Initial cleaning up session ? */
-  if (clean_h_values) space_sanitize(e->s);
+  if (clean_smoothing_length_values) space_sanitize(e->s);
 
 /* If in parallel, exchange the cell structure, top-level and neighbouring
  * multipoles. */
@@ -4395,7 +4395,7 @@ void engine_step(struct engine *e) {
 
   if (e->policy & engine_policy_cosmology) {
     e->time_old = e->time;
-    cosmology_update(e->cosmology, e->ti_current);
+    cosmology_update(e->cosmology, e->physical_constants, e->ti_current);
     e->time = e->cosmology->time;
     e->time_step = e->time - e->time_old;
   } else {
@@ -4404,6 +4404,10 @@ void engine_step(struct engine *e) {
     e->time_step = (e->ti_current - e->ti_old) * e->time_base;
   }
 
+  /* Update the softening lengths */
+  if (e->policy & engine_policy_self_gravity)
+    gravity_update(e->gravity_properties, e->cosmology);
+
   /* Prepare the tasks to be launched, rebuild or repartition if needed. */
   engine_prepare(e);
 
@@ -5193,7 +5197,7 @@ void engine_init(
     long long Ngas, long long Ndm, int policy, int verbose,
     struct repartition *reparttype, const struct unit_system *internal_units,
     const struct phys_const *physical_constants, struct cosmology *cosmo,
-    const struct hydro_props *hydro, const struct gravity_props *gravity,
+    const struct hydro_props *hydro, struct gravity_props *gravity,
     const struct external_potential *potential,
     const struct cooling_function_data *cooling_func,
     const struct chemistry_data *chemistry, struct sourceterms *sourceterms) {
diff --git a/src/engine.h b/src/engine.h
index 0fa8ca93b84760d0d92d9494f6e8e6224e3d1d9a..4c37aab593fdffc5f68ea16cb83b29ad782debf0 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -278,7 +278,7 @@ struct engine {
   const struct hydro_props *hydro_properties;
 
   /* Properties of the self-gravity scheme */
-  const struct gravity_props *gravity_properties;
+  struct gravity_props *gravity_properties;
 
   /* Properties of external gravitational potential */
   const struct external_potential *external_potential;
@@ -335,7 +335,7 @@ void engine_init(
     long long Ngas, long long Ndm, int policy, int verbose,
     struct repartition *reparttype, const struct unit_system *internal_units,
     const struct phys_const *physical_constants, struct cosmology *cosmo,
-    const struct hydro_props *hydro, const struct gravity_props *gravity,
+    const struct hydro_props *hydro, struct gravity_props *gravity,
     const struct external_potential *potential,
     const struct cooling_function_data *cooling_func,
     const struct chemistry_data *chemistry, struct sourceterms *sourceterms);
diff --git a/src/gravity.h b/src/gravity.h
index 85e42370bc456dceb577c42ee609e3f0724e14ea..33bef8ba329aa1264334e3319b6250c01b974338 100644
--- a/src/gravity.h
+++ b/src/gravity.h
@@ -24,16 +24,17 @@
 
 /* Local headers. */
 #include "const.h"
-#include "engine.h"
 #include "inline.h"
 #include "part.h"
-#include "space.h"
 
 /* So far only one model here */
 /* Straight-forward import */
 #include "./gravity/Default/gravity.h"
 #include "./gravity/Default/gravity_iact.h"
 
+struct engine;
+struct space;
+
 void gravity_exact_force_ewald_init(double boxSize);
 void gravity_exact_force_ewald_free();
 void gravity_exact_force_compute(struct space *s, const struct engine *e);
diff --git a/src/gravity/Default/gravity.h b/src/gravity/Default/gravity.h
index 099cbcd158436b414b9bc6a912727116b763cff9..eabc95fc7eb1e1d4039dc9cea6611f1d17451a37 100644
--- a/src/gravity/Default/gravity.h
+++ b/src/gravity/Default/gravity.h
@@ -21,8 +21,10 @@
 #define SWIFT_DEFAULT_GRAVITY_H
 
 #include <float.h>
+
 #include "cosmology.h"
 #include "gravity_properties.h"
+#include "kernel_gravity.h"
 #include "minmax.h"
 
 /**
@@ -40,11 +42,12 @@ __attribute__((always_inline)) INLINE static float gravity_get_mass(
  * @brief Returns the softening of a particle
  *
  * @param gp The particle of interest
+ * @param grav_props The global gravity properties.
  */
 __attribute__((always_inline)) INLINE static float gravity_get_softening(
-    const struct gpart* restrict gp) {
+    const struct gpart* gp, const struct gravity_props* restrict grav_props) {
 
-  return gp->epsilon;
+  return grav_props->epsilon_cur;
 }
 
 /**
@@ -102,12 +105,10 @@ gravity_compute_timestep_self(const struct gpart* const gp,
 
   const float ac_inv = (ac2 > 0.f) ? 1.f / sqrtf(ac2) : FLT_MAX;
 
-  // MATTHIEU cosmological evolution of the softening?
-  const float epsilon = gravity_get_softening(gp);
+  const float epsilon = gravity_get_softening(gp, grav_props);
 
-  /* Note that 0.66666667 = 2. (from Gadget) / 3. (Plummer softening) */
-  const float dt =
-      sqrtf(0.66666667f * cosmo->a * grav_props->eta * epsilon * ac_inv);
+  const float dt = sqrtf(2. * kernel_gravity_softening_plummer_equivalent_inv *
+                         cosmo->a * grav_props->eta * epsilon * ac_inv);
 
   return dt;
 }
@@ -183,7 +184,6 @@ __attribute__((always_inline)) INLINE static void gravity_first_init_gpart(
     struct gpart* gp, const struct gravity_props* grav_props) {
 
   gp->time_bin = 0;
-  gp->epsilon = grav_props->epsilon;
 
   gravity_init_gpart(gp);
 }
diff --git a/src/gravity/Default/gravity_debug.h b/src/gravity/Default/gravity_debug.h
index b83f8c73b4678145f2ecd6d94b136b5aadffccbd..dce038c58e1769446861bdf6c9a2a44415642c68 100644
--- a/src/gravity/Default/gravity_debug.h
+++ b/src/gravity/Default/gravity_debug.h
@@ -22,9 +22,9 @@
 __attribute__((always_inline)) INLINE static void gravity_debug_particle(
     const struct gpart* p) {
   printf(
-      "mass=%.3e epsilon=%.5e time_bin=%d\n"
+      "mass=%.3e time_bin=%d\n"
       "x=[%.5e,%.5e,%.5e], v_full=[%.5e,%.5e,%.5e], a=[%.5e,%.5e,%.5e]\n",
-      p->mass, p->epsilon, p->time_bin, p->x[0], p->x[1], p->x[2], p->v_full[0],
+      p->mass, p->time_bin, p->x[0], p->x[1], p->x[2], p->v_full[0],
       p->v_full[1], p->v_full[2], p->a_grav[0], p->a_grav[1], p->a_grav[2]);
 #ifdef SWIFT_DEBUG_CHECKS
   printf("num_interacted=%lld ti_drift=%lld ti_kick=%lld\n", p->num_interacted,
diff --git a/src/gravity/Default/gravity_io.h b/src/gravity/Default/gravity_io.h
index 26f7a6d15e11cf2e2d9ccd9978a1c67bab17d852..2508f69a636b93c218cdcb0770cf00ef969389c2 100644
--- a/src/gravity/Default/gravity_io.h
+++ b/src/gravity/Default/gravity_io.h
@@ -35,6 +35,38 @@ void convert_gpart_pos(const struct engine* e, const struct gpart* gp,
   }
 }
 
+void convert_gpart_vel(const struct engine* e, const struct gpart* gp,
+                       float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, gp->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, gp->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  ret[0] = gp->v_full[0] + gp->a_grav[0] * dt_kick_grav;
+  ret[1] = gp->v_full[1] + gp->a_grav[1] * dt_kick_grav;
+  ret[2] = gp->v_full[2] + gp->a_grav[2] * dt_kick_grav;
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
 /**
  * @brief Specifies which g-particle fields to read from a dataset
  *
@@ -69,20 +101,20 @@ void darkmatter_read_particles(struct gpart* gparts, struct io_props* list,
 void darkmatter_write_particles(const struct gpart* gparts,
                                 struct io_props* list, int* num_fields) {
 
-  /* Say how much we want to read */
+  /* Say how much we want to write */
   *num_fields = 5;
 
-  /* List what we want to read */
+  /* List what we want to write */
   list[0] = io_make_output_field_convert_gpart(
       "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, gparts, convert_gpart_pos);
-  list[1] = io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED,
-                                 gparts, v_full);
+  list[1] = io_make_output_field_convert_gpart(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, gparts, convert_gpart_vel);
   list[2] =
       io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, gparts, mass);
   list[3] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
                                  UNIT_CONV_NO_UNITS, gparts, id_or_neg_offset);
-  list[4] = io_make_output_field("Acceleration", FLOAT, 3,
-                                 UNIT_CONV_ACCELERATION, gparts, a_grav);
+  list[4] = io_make_output_field("Potential", FLOAT, 1, UNIT_CONV_POTENTIAL,
+                                 gparts, potential);
 }
 
 #endif /* SWIFT_DEFAULT_GRAVITY_IO_H */
diff --git a/src/gravity/Default/gravity_part.h b/src/gravity/Default/gravity_part.h
index 4c7a7b5d4af1c26ee96ac797963f5588d3303d77..06b9c52e14a655aa97b6c36ff9dca1f1cdd6e9a0 100644
--- a/src/gravity/Default/gravity_part.h
+++ b/src/gravity/Default/gravity_part.h
@@ -22,35 +22,32 @@
 /* Gravity particle. */
 struct gpart {
 
-  /* Particle ID. If negative, it is the negative offset of the #part with
+  /*! Particle ID. If negative, it is the negative offset of the #part with
      which this gpart is linked. */
   long long id_or_neg_offset;
 
-  /* Particle position. */
+  /*! Particle position. */
   double x[3];
 
-  /* Offset between current position and position at last tree rebuild. */
+  /*! Offset between current position and position at last tree rebuild. */
   float x_diff[3];
 
-  /* Particle velocity. */
+  /*! Particle velocity. */
   float v_full[3];
 
-  /* Particle acceleration. */
+  /*! Particle acceleration. */
   float a_grav[3];
 
-  /* Particle mass. */
+  /*! Particle mass. */
   float mass;
 
-  /* Gravitational potential */
+  /*! Gravitational potential */
   float potential;
 
-  /* Softening length */
-  float epsilon;
-
-  /* Time-step length */
+  /*! Time-step length */
   timebin_t time_bin;
 
-  /* Type of the #gpart (DM, gas, star, ...) */
+  /*! Type of the #gpart (DM, gas, star, ...) */
   enum part_type type;
 
 #ifdef SWIFT_DEBUG_CHECKS
diff --git a/src/gravity_cache.h b/src/gravity_cache.h
index be349cfd4a4583a493219eb020757341c98f540c..0012be193c657abccd5d83ed872e4d21764065a0 100644
--- a/src/gravity_cache.h
+++ b/src/gravity_cache.h
@@ -149,14 +149,16 @@ static INLINE void gravity_cache_init(struct gravity_cache *c, int count) {
  * @param shift A shift to apply to all the particles.
  * @param CoM The position of the multipole.
  * @param r_max2 The square of the multipole radius.
- * @param theta_crit2 The square of the opening angle.
  * @param cell The cell we play with (to get reasonable padding positions).
+ * @param grav_props The global gravity properties.
  */
 __attribute__((always_inline)) INLINE static void gravity_cache_populate(
     timebin_t max_active_bin, struct gravity_cache *c,
     const struct gpart *restrict gparts, int gcount, int gcount_padded,
-    const double shift[3], const float CoM[3], float r_max2, float theta_crit2,
-    const struct cell *cell) {
+    const double shift[3], const float CoM[3], float r_max2,
+    const struct cell *cell, const struct gravity_props *grav_props) {
+
+  const float theta_crit2 = grav_props->theta_crit2;
 
   /* Make the compiler understand we are in happy vectorization land */
   swift_declare_aligned_ptr(float, x, c->x, SWIFT_CACHE_ALIGNMENT);
@@ -174,7 +176,7 @@ __attribute__((always_inline)) INLINE static void gravity_cache_populate(
     x[i] = (float)(gparts[i].x[0] - shift[0]);
     y[i] = (float)(gparts[i].x[1] - shift[1]);
     z[i] = (float)(gparts[i].x[2] - shift[2]);
-    epsilon[i] = gparts[i].epsilon;
+    epsilon[i] = gravity_get_softening(&gparts[i], grav_props);
     m[i] = gparts[i].mass;
     active[i] = (int)(gparts[i].time_bin <= max_active_bin);
 
@@ -220,13 +222,15 @@ __attribute__((always_inline)) INLINE static void gravity_cache_populate(
  * multiple of the vector length.
  * @param shift A shift to apply to all the particles.
  * @param cell The cell we play with (to get reasonable padding positions).
+ * @param grav_props The global gravity properties.
  */
 __attribute__((always_inline)) INLINE static void
 gravity_cache_populate_no_mpole(timebin_t max_active_bin,
                                 struct gravity_cache *c,
                                 const struct gpart *restrict gparts, int gcount,
                                 int gcount_padded, const double shift[3],
-                                const struct cell *cell) {
+                                const struct cell *cell,
+                                const struct gravity_props *grav_props) {
 
   /* Make the compiler understand we are in happy vectorization land */
   swift_declare_aligned_ptr(float, x, c->x, SWIFT_CACHE_ALIGNMENT);
@@ -242,7 +246,7 @@ gravity_cache_populate_no_mpole(timebin_t max_active_bin,
     x[i] = (float)(gparts[i].x[0] - shift[0]);
     y[i] = (float)(gparts[i].x[1] - shift[1]);
     z[i] = (float)(gparts[i].x[2] - shift[2]);
-    epsilon[i] = gparts[i].epsilon;
+    epsilon[i] = gravity_get_softening(&gparts[i], grav_props);
     m[i] = gparts[i].mass;
     active[i] = (int)(gparts[i].time_bin <= max_active_bin);
   }
diff --git a/src/gravity_properties.c b/src/gravity_properties.c
index 1df421a8b21424dc99e52bc9dbc59560e54d14a5..79be11a8bab2389c19c58a59851379ea23d5fb3f 100644
--- a/src/gravity_properties.c
+++ b/src/gravity_properties.c
@@ -37,7 +37,8 @@
 #define gravity_props_default_r_cut_min 0.1f
 
 void gravity_props_init(struct gravity_props *p,
-                        const struct swift_params *params) {
+                        const struct swift_params *params,
+                        const struct cosmology *cosmo) {
 
   /* Tree-PM parameters */
   p->a_smooth = parser_get_opt_param_float(params, "Gravity:a_smooth",
@@ -56,11 +57,35 @@ void gravity_props_init(struct gravity_props *p,
   p->theta_crit2 = p->theta_crit * p->theta_crit;
   p->theta_crit_inv = 1. / p->theta_crit;
 
-  /* Softening lengths */
-  p->epsilon = 3. * parser_get_param_double(params, "Gravity:epsilon");
-  p->epsilon2 = p->epsilon * p->epsilon;
-  p->epsilon_inv = 1.f / p->epsilon;
-  p->epsilon_inv3 = p->epsilon_inv * p->epsilon_inv * p->epsilon_inv;
+  /* Softening parameters */
+  p->epsilon_comoving =
+      parser_get_param_double(params, "Gravity:comoving_softening");
+  p->epsilon_max_physical =
+      parser_get_param_double(params, "Gravity:max_physical_softening");
+
+  /* Set the softening to the current time */
+  gravity_update(p, cosmo);
+}
+
+void gravity_update(struct gravity_props *p, const struct cosmology *cosmo) {
+
+  /* Current softening lengths */
+  double softening;
+  if (p->epsilon_comoving * cosmo->a > p->epsilon_max_physical)
+    softening = p->epsilon_max_physical / cosmo->a;
+  else
+    softening = p->epsilon_comoving;
+
+  /* Plummer equivalent -> internal */
+  softening *= kernel_gravity_softening_plummer_equivalent;
+
+  /* Store things */
+  p->epsilon_cur = softening;
+
+  /* Other factors */
+  p->epsilon_cur2 = softening * softening;
+  p->epsilon_cur_inv = 1. / softening;
+  p->epsilon_cur_inv3 = 1. / (softening * softening * softening);
 }
 
 void gravity_props_print(const struct gravity_props *p) {
@@ -72,8 +97,17 @@ void gravity_props_print(const struct gravity_props *p) {
 
   message("Self-gravity opening angle:  theta=%.4f", p->theta_crit);
 
-  message("Self-gravity softening:    epsilon=%.4f (Plummer equivalent: %.4f)",
-          p->epsilon, p->epsilon / 3.);
+  message(
+      "Self-gravity comoving softening:    epsilon=%.4f (Plummer equivalent: "
+      "%.4f)",
+      p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent,
+      p->epsilon_comoving);
+
+  message(
+      "Self-gravity maximal physical softening:    epsilon=%.4f (Plummer "
+      "equivalent: %.4f)",
+      p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent,
+      p->epsilon_max_physical);
 
   message("Self-gravity mesh smoothing-scale: a_smooth=%f", p->a_smooth);
 
@@ -86,9 +120,18 @@ void gravity_props_print_snapshot(hid_t h_grpgrav,
                                   const struct gravity_props *p) {
 
   io_write_attribute_f(h_grpgrav, "Time integration eta", p->eta);
-  io_write_attribute_f(h_grpgrav, "Softening length", p->epsilon);
-  io_write_attribute_f(h_grpgrav, "Softening length (Plummer equivalent)",
-                       p->epsilon / 3.);
+  io_write_attribute_f(
+      h_grpgrav, "Comoving softening length",
+      p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent);
+  io_write_attribute_f(h_grpgrav,
+                       "Comoving Softening length (Plummer equivalent)",
+                       p->epsilon_comoving);
+  io_write_attribute_f(
+      h_grpgrav, "Maximal physical softening length",
+      p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent);
+  io_write_attribute_f(h_grpgrav,
+                       "Maximal physical softening length (Plummer equivalent)",
+                       p->epsilon_max_physical);
   io_write_attribute_f(h_grpgrav, "Opening angle", p->theta_crit);
   io_write_attribute_d(h_grpgrav, "MM order", SELF_GRAVITY_MULTIPOLE_ORDER);
   io_write_attribute_f(h_grpgrav, "Mesh a_smooth", p->a_smooth);
diff --git a/src/gravity_properties.h b/src/gravity_properties.h
index 826ffd0de05d376b930523c8a5d937e457c6d795..f36a39a6e187b8b397a5f597692f5a37c982aa7a 100644
--- a/src/gravity_properties.h
+++ b/src/gravity_properties.h
@@ -27,6 +27,7 @@
 #endif
 
 /* Local includes. */
+#include "cosmology.h"
 #include "parser.h"
 #include "restart.h"
 
@@ -58,22 +59,30 @@ struct gravity_props {
   /*! Inverse of opening angle */
   double theta_crit_inv;
 
-  /*! Softening length */
-  float epsilon;
+  /*! Comoving softening */
+  double epsilon_comoving;
 
-  /*! Square of softening length */
-  float epsilon2;
+  /*! Maxium physical softening */
+  double epsilon_max_physical;
 
-  /*! Inverse of softening length */
-  float epsilon_inv;
+  /*! Current sftening length */
+  float epsilon_cur;
 
-  /*! Cube of the inverse of softening length */
-  float epsilon_inv3;
+  /*! Square of current softening length */
+  float epsilon_cur2;
+
+  /*! Inverse of current softening length */
+  float epsilon_cur_inv;
+
+  /*! Cube of the inverse of current oftening length */
+  float epsilon_cur_inv3;
 };
 
 void gravity_props_print(const struct gravity_props *p);
 void gravity_props_init(struct gravity_props *p,
-                        const struct swift_params *params);
+                        const struct swift_params *params,
+                        const struct cosmology *cosmo);
+void gravity_update(struct gravity_props *p, const struct cosmology *cosmo);
 
 #if defined(HAVE_HDF5)
 void gravity_props_print_snapshot(hid_t h_grpsph,
diff --git a/src/hydro/Default/hydro.h b/src/hydro/Default/hydro.h
index 1228aa69abfe812e5b2e73f066bb13be3292aa20..7da005456233b800e05e75389922395ea3c1702c 100644
--- a/src/hydro/Default/hydro.h
+++ b/src/hydro/Default/hydro.h
@@ -160,6 +160,18 @@ __attribute__((always_inline)) INLINE static float hydro_get_mass(
   return p->mass;
 }
 
+/**
+ * @brief Sets the mass of a particle
+ *
+ * @param p The particle of interest
+ * @param m The mass to set.
+ */
+__attribute__((always_inline)) INLINE static void hydro_set_mass(
+    struct part *restrict p, float m) {
+
+  p->mass = m;
+}
+
 /**
  * @brief Returns the velocities drifted to the current time of a particle.
  *
@@ -492,7 +504,8 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param dt_therm The time-step for this kick (for thermodynamic quantities)
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part *restrict p, struct xpart *restrict xp, float dt_therm) {}
+    struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {}
 
 /**
  *  @brief Converts hydro quantity of a particle at the start of a run
@@ -500,9 +513,12 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
  * Requires the density to be known
  *
  * @param p The particle to act upon
+ * @param xp The extended data.
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part *restrict p, struct xpart *restrict xp) {}
+    struct part *restrict p, struct xpart *restrict xp,
+    const struct cosmology *cosmo) {}
 
 /**
  * @brief Initialises the particles for the first time
@@ -529,4 +545,21 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   hydro_init_part(p, NULL);
 }
 
+/**
+ * @brief Overwrite the initial internal energy of a particle.
+ *
+ * Note that in the cases where the thermodynamic variable is not
+ * internal energy but gets converted later, we must overwrite that
+ * field. The conversion to the actual variable happens later after
+ * the initial fake time-step.
+ *
+ * @param p The #part to write to.
+ * @param u_init The new initial internal energy.
+ */
+__attribute__((always_inline)) INLINE static void
+hydro_set_init_internal_energy(struct part *p, float u_init) {
+
+  p->u = u_init;
+}
+
 #endif /* SWIFT_DEFAULT_HYDRO_H */
diff --git a/src/hydro/Default/hydro_io.h b/src/hydro/Default/hydro_io.h
index bfff08dcdf061d86986ffdeabee6e7a84cba1c7b..e70a26f9edc3f7497dd4c548efd464726efe0e39 100644
--- a/src/hydro/Default/hydro_io.h
+++ b/src/hydro/Default/hydro_io.h
@@ -54,7 +54,7 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
 }
 
 void convert_part_pos(const struct engine* e, const struct part* p,
-                      double* ret) {
+                      const struct xpart* xp, double* ret) {
 
   if (e->s->periodic) {
     ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
@@ -67,6 +67,49 @@ void convert_part_pos(const struct engine* e, const struct part* p,
   }
 }
 
+void convert_part_vel(const struct engine* e, const struct part* p,
+                      const struct xpart* xp, float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, p->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, p->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav, dt_kick_hydro;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+    dt_kick_hydro = cosmology_get_hydro_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_hydro -=
+        cosmology_get_hydro_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+    dt_kick_hydro = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  hydro_get_drifted_velocities(p, xp, dt_kick_hydro, dt_kick_grav, ret);
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
+void convert_part_potential(const struct engine* e, const struct part* p,
+                            const struct xpart* xp, float* ret) {
+
+  if (p->gpart != NULL)
+    ret[0] = gravity_get_comoving_potential(p->gpart);
+  else
+    ret[0] = 0.f;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
@@ -74,16 +117,17 @@ void convert_part_pos(const struct engine* e, const struct part* p,
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void hydro_write_particles(struct part* parts, struct io_props* list,
-                           int* num_fields) {
+void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
+                           struct io_props* list, int* num_fields) {
 
-  *num_fields = 7;
+  *num_fields = 8;
 
   /* List what we want to write */
-  list[0] = io_make_output_field_convert_part(
-      "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, parts, convert_part_pos);
-  list[1] =
-      io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
+  list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
+                                              UNIT_CONV_LENGTH, parts, xparts,
+                                              convert_part_pos);
+  list[1] = io_make_output_field_convert_part(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, xparts, convert_part_vel);
   list[2] =
       io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass);
   list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
@@ -94,6 +138,9 @@ void hydro_write_particles(struct part* parts, struct io_props* list,
                                  UNIT_CONV_NO_UNITS, parts, id);
   list[6] =
       io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
+  list[7] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+                                              UNIT_CONV_POTENTIAL, parts,
+                                              xparts, convert_part_potential);
 }
 
 /**
diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h
index 185a98b6d207bb851512a686be51414341fe7740..bc06a24e2a8245556a1042f2459273b8d750489e 100644
--- a/src/hydro/Gadget2/hydro.h
+++ b/src/hydro/Gadget2/hydro.h
@@ -170,6 +170,18 @@ __attribute__((always_inline)) INLINE static float hydro_get_mass(
   return p->mass;
 }
 
+/**
+ * @brief Sets the mass of a particle
+ *
+ * @param p The particle of interest
+ * @param m The mass to set.
+ */
+__attribute__((always_inline)) INLINE static void hydro_set_mass(
+    struct part *restrict p, float m) {
+
+  p->mass = m;
+}
+
 /**
  * @brief Returns the velocities drifted to the current time of a particle.
  *
@@ -513,19 +525,29 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param p The particle to act upon
  * @param xp The particle extended data to act upon
  * @param dt_therm The time-step for this kick (for thermodynamic quantities)
+ * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part *restrict p, struct xpart *restrict xp, float dt_therm) {
+    struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the entropy by more than a factor of 2 */
   if (dt_therm > 0. && p->entropy_dt * dt_therm < -0.5f * xp->entropy_full) {
-    /* message("Warning! Limiting entropy_dt. Possible cooling error.\n
-     * entropy_full = %g \n entropy_dt * dt =%g \n", */
-    /* 	     xp->entropy_full,p->entropy_dt * dt); */
     p->entropy_dt = -0.5f * xp->entropy_full / dt_therm;
   }
   xp->entropy_full += p->entropy_dt * dt_therm;
 
+  /* Apply the minimal energy limit */
+  const float density = p->rho * cosmo->a3_inv;
+  const float min_energy = hydro_props->minimal_internal_energy;
+  const float min_entropy =
+      gas_entropy_from_internal_energy(density, min_energy);
+  if (xp->entropy_full < min_entropy) {
+    xp->entropy_full = min_entropy;
+    p->entropy_dt = 0.f;
+  }
+
   /* Compute the pressure */
   const float pressure = gas_pressure_from_entropy(p->rho, xp->entropy_full);
 
@@ -545,13 +567,18 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
  *
  * Requires the density to be known
  *
- * @param p The particle to act upon
+ * @param p The particle to act upon.
+ * @param xp The extended data.
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part *restrict p, struct xpart *restrict xp) {
+    struct part *restrict p, struct xpart *restrict xp,
+    const struct cosmology *cosmo) {
 
-  /* We read u in the entropy field. We now get S from u */
-  xp->entropy_full = gas_entropy_from_internal_energy(p->rho, p->entropy);
+  /* We read u in the entropy field. We now get (comoving) S from (physical) u
+   * and (physical) rho. Note that comoving S == physical S */
+  xp->entropy_full =
+      gas_entropy_from_internal_energy(p->rho * cosmo->a3_inv, p->entropy);
   p->entropy = xp->entropy_full;
 
   /* Compute the pressure */
@@ -593,4 +620,21 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   hydro_init_part(p, NULL);
 }
 
+/**
+ * @brief Overwrite the initial internal energy of a particle.
+ *
+ * Note that in the cases where the thermodynamic variable is not
+ * internal energy but gets converted later, we must overwrite that
+ * field. The conversion to the actual variable happens later after
+ * the initial fake time-step.
+ *
+ * @param p The #part to write to.
+ * @param u_init The new initial internal energy.
+ */
+__attribute__((always_inline)) INLINE static void
+hydro_set_init_internal_energy(struct part *p, float u_init) {
+
+  p->entropy = u_init;
+}
+
 #endif /* SWIFT_GADGET2_HYDRO_H */
diff --git a/src/hydro/Gadget2/hydro_io.h b/src/hydro/Gadget2/hydro_io.h
index 5c329e9d7297109c378e04f0e4931a0717e07278..28c0eea4772f51fab35a08d43c0564472694eeeb 100644
--- a/src/hydro/Gadget2/hydro_io.h
+++ b/src/hydro/Gadget2/hydro_io.h
@@ -55,18 +55,20 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
                                 UNIT_CONV_DENSITY, parts, rho);
 }
 
-void convert_u(const struct engine* e, const struct part* p, float* ret) {
+void convert_part_u(const struct engine* e, const struct part* p,
+                    const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_internal_energy(p);
 }
 
-void convert_P(const struct engine* e, const struct part* p, float* ret) {
+void convert_part_P(const struct engine* e, const struct part* p,
+                    const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_pressure(p);
 }
 
 void convert_part_pos(const struct engine* e, const struct part* p,
-                      double* ret) {
+                      const struct xpart* xp, double* ret) {
 
   if (e->s->periodic) {
     ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
@@ -79,6 +81,49 @@ void convert_part_pos(const struct engine* e, const struct part* p,
   }
 }
 
+void convert_part_vel(const struct engine* e, const struct part* p,
+                      const struct xpart* xp, float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, p->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, p->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav, dt_kick_hydro;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+    dt_kick_hydro = cosmology_get_hydro_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_hydro -=
+        cosmology_get_hydro_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+    dt_kick_hydro = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  hydro_get_drifted_velocities(p, xp, dt_kick_hydro, dt_kick_grav, ret);
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
+void convert_part_potential(const struct engine* e, const struct part* p,
+                            const struct xpart* xp, float* ret) {
+
+  if (p->gpart != NULL)
+    ret[0] = gravity_get_comoving_potential(p->gpart);
+  else
+    ret[0] = 0.f;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
@@ -86,16 +131,17 @@ void convert_part_pos(const struct engine* e, const struct part* p,
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void hydro_write_particles(const struct part* parts, struct io_props* list,
-                           int* num_fields) {
+void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
+                           struct io_props* list, int* num_fields) {
 
-  *num_fields = 9;
+  *num_fields = 10;
 
   /* List what we want to write */
-  list[0] = io_make_output_field_convert_part(
-      "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, parts, convert_part_pos);
-  list[1] =
-      io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
+  list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
+                                              UNIT_CONV_LENGTH, parts, xparts,
+                                              convert_part_pos);
+  list[1] = io_make_output_field_convert_part(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, xparts, convert_part_vel);
   list[2] =
       io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass);
   list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
@@ -108,9 +154,13 @@ void hydro_write_particles(const struct part* parts, struct io_props* list,
       io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
   list[7] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1,
                                               UNIT_CONV_ENERGY_PER_UNIT_MASS,
-                                              parts, convert_u);
+                                              parts, xparts, convert_part_u);
   list[8] = io_make_output_field_convert_part(
-      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, convert_P);
+      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_part_P);
+
+  list[9] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+                                              UNIT_CONV_POTENTIAL, parts,
+                                              xparts, convert_part_potential);
 
 #ifdef DEBUG_INTERACTIONS_SPH
 
diff --git a/src/hydro/Gizmo/hydro.h b/src/hydro/Gizmo/hydro.h
index 0faa4bf39ae533ee9942898bdc08118ee4078868..bc90a6790fa8123b19badf63761a6dd1378197f6 100644
--- a/src/hydro/Gizmo/hydro.h
+++ b/src/hydro/Gizmo/hydro.h
@@ -517,7 +517,7 @@ __attribute__((always_inline)) INLINE static void hydro_reset_predicted_values(
  * @param p The particle to act upon.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part* p, struct xpart* xp) {}
+    struct part* p, struct xpart* xp, const struct cosmology* cosmo) {}
 
 /**
  * @brief Extra operations to be done during the drift
@@ -611,7 +611,8 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param half_dt Half the physical time step.
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part* p, struct xpart* xp, float dt) {
+    struct part* p, struct xpart* xp, float dt, const struct cosmology* cosmo,
+    const struct hydro_props* hydro_props) {
 
   float a_grav[3];
 
@@ -628,6 +629,14 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
   p->conserved.energy += p->conserved.flux.energy * dt;
 #endif
 
+  /* Apply the minimal energy limit */
+  const float min_energy =
+      hydro_props->minimal_internal_energy * cosmo->a_factor_internal_energy;
+  if (p->conserved.energy < min_energy) {
+    p->conserved.energy = min_energy;
+    p->conserved.flux.energy = 0.f;
+  }
+
   gizmo_check_physical_quantity("mass", p->conserved.mass);
   gizmo_check_physical_quantity("energy", p->conserved.energy);
 
@@ -812,6 +821,18 @@ __attribute__((always_inline)) INLINE static float hydro_get_mass(
   return p->conserved.mass;
 }
 
+/**
+ * @brief Sets the mass of a particle
+ *
+ * @param p The particle of interest
+ * @param m The mass to set.
+ */
+__attribute__((always_inline)) INLINE static void hydro_set_mass(
+    struct part* restrict p, float m) {
+
+  p->conserved.mass = m;
+}
+
 /**
  * @brief Returns the velocities drifted to the current time of a particle.
  *
@@ -917,4 +938,29 @@ __attribute__((always_inline)) INLINE static void hydro_set_entropy(
   p->primitives.P = S * pow_gamma(p->primitives.rho);
 }
 
+/**
+ * @brief Overwrite the initial internal energy of a particle.
+ *
+ * Note that in the cases where the thermodynamic variable is not
+ * internal energy but gets converted later, we must overwrite that
+ * field. The conversion to the actual variable happens later after
+ * the initial fake time-step.
+ *
+ * @param p The #part to write to.
+ * @param u_init The new initial internal energy.
+ */
+__attribute__((always_inline)) INLINE static void
+hydro_set_init_internal_energy(struct part* p, float u_init) {
+
+  p->conserved.energy = u_init * p->conserved.mass;
+#ifdef GIZMO_TOTAL_ENERGY
+  /* add the kinetic energy */
+  p->conserved.energy += 0.5f * p->conserved.mass *
+                         (p->conserved.momentum[0] * p->primitives.v[0] +
+                          p->conserved.momentum[1] * p->primitives.v[1] +
+                          p->conserved.momentum[2] * p->primitives.v[2]);
+#endif
+  p->primitives.P = hydro_gamma_minus_one * p->primitives.rho * u_init;
+}
+
 #endif /* SWIFT_GIZMO_HYDRO_H */
diff --git a/src/hydro/Gizmo/hydro_io.h b/src/hydro/Gizmo/hydro_io.h
index b8e2e30646c3aafb73d387010ab7ea0b0a663a77..7aa56b3bde5247f4839b8f4f60cdb3de67253392 100644
--- a/src/hydro/Gizmo/hydro_io.h
+++ b/src/hydro/Gizmo/hydro_io.h
@@ -72,7 +72,8 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
  * @param p Particle.
  * @param ret (return) Internal energy of the particle
  */
-void convert_u(const struct engine* e, const struct part* p, float* ret) {
+void convert_u(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_internal_energy(p);
 }
@@ -84,7 +85,8 @@ void convert_u(const struct engine* e, const struct part* p, float* ret) {
  * @param p Particle.
  * @param ret (return) Entropic function of the particle
  */
-void convert_A(const struct engine* e, const struct part* p, float* ret) {
+void convert_A(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
   ret[0] = hydro_get_comoving_entropy(p);
 }
 
@@ -95,7 +97,8 @@ void convert_A(const struct engine* e, const struct part* p, float* ret) {
  * @param p Particle.
  * @return Total energy of the particle
  */
-void convert_Etot(const struct engine* e, const struct part* p, float* ret) {
+void convert_Etot(const struct engine* e, const struct part* p,
+                  const struct xpart* xp, float* ret) {
 #ifdef GIZMO_TOTAL_ENERGY
   ret[0] = p->conserved.energy;
 #else
@@ -110,7 +113,7 @@ void convert_Etot(const struct engine* e, const struct part* p, float* ret) {
 }
 
 void convert_part_pos(const struct engine* e, const struct part* p,
-                      double* ret) {
+                      const struct xpart* xp, double* ret) {
 
   if (e->s->periodic) {
     ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
@@ -123,6 +126,49 @@ void convert_part_pos(const struct engine* e, const struct part* p,
   }
 }
 
+void convert_part_vel(const struct engine* e, const struct part* p,
+                      const struct xpart* xp, float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, p->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, p->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav, dt_kick_hydro;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+    dt_kick_hydro = cosmology_get_hydro_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_hydro -=
+        cosmology_get_hydro_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+    dt_kick_hydro = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  hydro_get_drifted_velocities(p, xp, dt_kick_hydro, dt_kick_grav, ret);
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
+void convert_part_potential(const struct engine* e, const struct part* p,
+                            const struct xpart* xp, float* ret) {
+
+  if (p->gpart != NULL)
+    ret[0] = gravity_get_comoving_potential(p->gpart);
+  else
+    ret[0] = 0.f;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
@@ -130,33 +176,39 @@ void convert_part_pos(const struct engine* e, const struct part* p,
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void hydro_write_particles(struct part* parts, struct io_props* list,
-                           int* num_fields) {
+void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
+                           struct io_props* list, int* num_fields) {
 
-  *num_fields = 10;
+  *num_fields = 11;
 
   /* List what we want to write */
-  list[0] = io_make_output_field_convert_part(
-      "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, parts, convert_part_pos);
-  list[1] = io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts,
-                                 primitives.v);
+  list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
+                                              UNIT_CONV_LENGTH, parts, xparts,
+                                              convert_part_pos);
+  list[1] = io_make_output_field_convert_part(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, xparts, convert_part_vel);
+
   list[2] = io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts,
                                  conserved.mass);
   list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
                                  parts, h);
   list[4] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1,
                                               UNIT_CONV_ENERGY_PER_UNIT_MASS,
-                                              parts, convert_u);
+                                              parts, xparts, convert_u);
   list[5] = io_make_output_field("ParticleIDs", ULONGLONG, 1,
                                  UNIT_CONV_NO_UNITS, parts, id);
   list[6] = io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts,
                                  primitives.rho);
   list[7] = io_make_output_field_convert_part(
-      "Entropy", FLOAT, 1, UNIT_CONV_ENTROPY, parts, convert_A);
+      "Entropy", FLOAT, 1, UNIT_CONV_ENTROPY, parts, xparts, convert_A);
   list[8] = io_make_output_field("Pressure", FLOAT, 1, UNIT_CONV_PRESSURE,
                                  parts, primitives.P);
   list[9] = io_make_output_field_convert_part(
-      "TotEnergy", FLOAT, 1, UNIT_CONV_ENERGY, parts, convert_Etot);
+      "TotEnergy", FLOAT, 1, UNIT_CONV_ENERGY, parts, xparts, convert_Etot);
+
+  list[10] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+                                               UNIT_CONV_POTENTIAL, parts,
+                                               xparts, convert_part_potential);
 }
 
 /**
diff --git a/src/hydro/Minimal/hydro.h b/src/hydro/Minimal/hydro.h
index 97cd5ef577dcfd7b07c5183a92349313096a6412..3f9d99683bde4ed6db64d8aaa5b111e2f67f0969 100644
--- a/src/hydro/Minimal/hydro.h
+++ b/src/hydro/Minimal/hydro.h
@@ -197,6 +197,18 @@ __attribute__((always_inline)) INLINE static float hydro_get_mass(
   return p->mass;
 }
 
+/**
+ * @brief Sets the mass of a particle
+ *
+ * @param p The particle of interest
+ * @param m The mass to set.
+ */
+__attribute__((always_inline)) INLINE static void hydro_set_mass(
+    struct part *restrict p, float m) {
+
+  p->mass = m;
+}
+
 /**
  * @brief Returns the velocities drifted to the current time of a particle.
  *
@@ -510,9 +522,12 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param p The particle to act upon.
  * @param xp The particle extended data to act upon.
  * @param dt_therm The time-step for this kick (for thermodynamic quantities).
+ * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part *restrict p, struct xpart *restrict xp, float dt_therm) {
+    struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the energy by more than a factor of 2*/
   if (dt_therm > 0. && p->u_dt * dt_therm < -0.5f * xp->u_full) {
@@ -520,6 +535,14 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
   }
   xp->u_full += p->u_dt * dt_therm;
 
+  /* Apply the minimal energy limit */
+  const float min_energy =
+      hydro_props->minimal_internal_energy * cosmo->a_factor_internal_energy;
+  if (xp->u_full < min_energy) {
+    xp->u_full = min_energy;
+    p->u_dt = 0.f;
+  }
+
   /* Compute the pressure */
   const float pressure = gas_pressure_from_internal_energy(p->rho, xp->u_full);
 
@@ -540,9 +563,11 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
  *
  * @param p The particle to act upon
  * @param xp The extended particle to act upon
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part *restrict p, struct xpart *restrict xp) {
+    struct part *restrict p, struct xpart *restrict xp,
+    const struct cosmology *cosmo) {
 
   /* Compute the pressure */
   const float pressure = gas_pressure_from_internal_energy(p->rho, p->u);
@@ -580,4 +605,21 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   hydro_init_part(p, NULL);
 }
 
+/**
+ * @brief Overwrite the initial internal energy of a particle.
+ *
+ * Note that in the cases where the thermodynamic variable is not
+ * internal energy but gets converted later, we must overwrite that
+ * field. The conversion to the actual variable happens later after
+ * the initial fake time-step.
+ *
+ * @param p The #part to write to.
+ * @param u_init The new initial internal energy.
+ */
+__attribute__((always_inline)) INLINE static void
+hydro_set_init_internal_energy(struct part *p, float u_init) {
+
+  p->u = u_init;
+}
+
 #endif /* SWIFT_MINIMAL_HYDRO_H */
diff --git a/src/hydro/Minimal/hydro_io.h b/src/hydro/Minimal/hydro_io.h
index 2ff70fd2f7e95344c17ba0f3237c3b2ee131752c..380d6120e05acf2e015ece6f133df02fad3b761d 100644
--- a/src/hydro/Minimal/hydro_io.h
+++ b/src/hydro/Minimal/hydro_io.h
@@ -69,18 +69,20 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
                                 UNIT_CONV_DENSITY, parts, rho);
 }
 
-void convert_S(const struct engine* e, const struct part* p, float* ret) {
+void convert_S(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_entropy(p);
 }
 
-void convert_P(const struct engine* e, const struct part* p, float* ret) {
+void convert_P(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_pressure(p);
 }
 
 void convert_part_pos(const struct engine* e, const struct part* p,
-                      double* ret) {
+                      const struct xpart* xp, double* ret) {
 
   if (e->s->periodic) {
     ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
@@ -93,23 +95,68 @@ void convert_part_pos(const struct engine* e, const struct part* p,
   }
 }
 
+void convert_part_vel(const struct engine* e, const struct part* p,
+                      const struct xpart* xp, float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, p->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, p->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav, dt_kick_hydro;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+    dt_kick_hydro = cosmology_get_hydro_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_hydro -=
+        cosmology_get_hydro_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+    dt_kick_hydro = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  hydro_get_drifted_velocities(p, xp, dt_kick_hydro, dt_kick_grav, ret);
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
+void convert_part_potential(const struct engine* e, const struct part* p,
+                            const struct xpart* xp, float* ret) {
+
+  if (p->gpart != NULL)
+    ret[0] = gravity_get_comoving_potential(p->gpart);
+  else
+    ret[0] = 0.f;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
  * @param parts The particle array.
+ * @param xparts The extended particle array.
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void hydro_write_particles(struct part* parts, struct io_props* list,
-                           int* num_fields) {
+void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
+                           struct io_props* list, int* num_fields) {
 
-  *num_fields = 9;
+  *num_fields = 10;
 
   /* List what we want to write */
-  list[0] = io_make_output_field_convert_part(
-      "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, parts, convert_part_pos);
-  list[1] =
-      io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
+  list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
+                                              UNIT_CONV_LENGTH, parts, xparts,
+                                              convert_part_pos);
+  list[1] = io_make_output_field_convert_part(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, xparts, convert_part_vel);
   list[2] =
       io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass);
   list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
@@ -120,10 +167,15 @@ void hydro_write_particles(struct part* parts, struct io_props* list,
                                  UNIT_CONV_NO_UNITS, parts, id);
   list[6] =
       io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
-  list[7] = io_make_output_field_convert_part(
-      "Entropy", FLOAT, 1, UNIT_CONV_ENTROPY_PER_UNIT_MASS, parts, convert_S);
+  list[7] = io_make_output_field_convert_part("Entropy", FLOAT, 1,
+                                              UNIT_CONV_ENTROPY_PER_UNIT_MASS,
+                                              parts, xparts, convert_S);
   list[8] = io_make_output_field_convert_part(
-      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, convert_P);
+      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P);
+
+  list[9] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+                                              UNIT_CONV_POTENTIAL, parts,
+                                              xparts, convert_part_potential);
 }
 
 /**
diff --git a/src/hydro/PressureEntropy/hydro.h b/src/hydro/PressureEntropy/hydro.h
index 37de855b375a5ac11f8a33f3993f7d2101c58522..87d46c6d43f0d4f6de6d18f5400b38f0fc4d0f55 100644
--- a/src/hydro/PressureEntropy/hydro.h
+++ b/src/hydro/PressureEntropy/hydro.h
@@ -170,6 +170,18 @@ __attribute__((always_inline)) INLINE static float hydro_get_mass(
   return p->mass;
 }
 
+/**
+ * @brief Sets the mass of a particle
+ *
+ * @param p The particle of interest
+ * @param m The mass to set.
+ */
+__attribute__((always_inline)) INLINE static void hydro_set_mass(
+    struct part *restrict p, float m) {
+
+  p->mass = m;
+}
+
 /**
  * @brief Returns the velocities drifted to the current time of a particle.
  *
@@ -524,9 +536,12 @@ __attribute__((always_inline)) INLINE static void hydro_end_force(
  * @param p The particle to act upon
  * @param xp The particle extended data to act upon
  * @param dt_therm The time-step for this kick (for thermodynamic quantities)
+ * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme
  */
 __attribute__((always_inline)) INLINE static void hydro_kick_extra(
-    struct part *restrict p, struct xpart *restrict xp, float dt_therm) {
+    struct part *restrict p, struct xpart *restrict xp, float dt_therm,
+    const struct cosmology *cosmo, const struct hydro_props *hydro_props) {
 
   /* Do not decrease the entropy (temperature) by more than a factor of 2*/
   if (dt_therm > 0. && p->entropy_dt * dt_therm < -0.5f * xp->entropy_full) {
@@ -534,6 +549,16 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
   }
   xp->entropy_full += p->entropy_dt * dt_therm;
 
+  /* Apply the minimal energy limit */
+  const float density = p->rho_bar * cosmo->a3_inv;
+  const float min_energy = hydro_props->minimal_internal_energy;
+  const float min_entropy =
+      gas_entropy_from_internal_energy(density, min_energy);
+  if (xp->entropy_full < min_entropy) {
+    xp->entropy_full = min_entropy;
+    p->entropy_dt = 0.f;
+  }
+
   /* Compute the pressure */
   const float pressure =
       gas_pressure_from_entropy(p->rho_bar, xp->entropy_full);
@@ -556,12 +581,16 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
  * Requires the density to be known
  *
  * @param p The particle to act upon
+ * @param xp The extended data.
+ * @param cosmo The cosmological model.
  */
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
-    struct part *restrict p, struct xpart *restrict xp) {
+    struct part *restrict p, struct xpart *restrict xp,
+    const struct cosmology *cosmo) {
 
   /* We read u in the entropy field. We now get S from u */
-  xp->entropy_full = gas_entropy_from_internal_energy(p->rho_bar, p->entropy);
+  xp->entropy_full =
+      gas_entropy_from_internal_energy(p->rho_bar * cosmo->a3_inv, p->entropy);
   p->entropy = xp->entropy_full;
   p->entropy_one_over_gamma = pow_one_over_gamma(p->entropy);
 
@@ -605,4 +634,21 @@ __attribute__((always_inline)) INLINE static void hydro_first_init_part(
   hydro_init_part(p, NULL);
 }
 
+/**
+ * @brief Overwrite the initial internal energy of a particle.
+ *
+ * Note that in the cases where the thermodynamic variable is not
+ * internal energy but gets converted later, we must overwrite that
+ * field. The conversion to the actual variable happens later after
+ * the initial fake time-step.
+ *
+ * @param p The #part to write to.
+ * @param u_init The new initial internal energy.
+ */
+__attribute__((always_inline)) INLINE static void
+hydro_set_init_internal_energy(struct part *p, float u_init) {
+
+  p->entropy = u_init;
+}
+
 #endif /* SWIFT_PRESSURE_ENTROPY_HYDRO_H */
diff --git a/src/hydro/PressureEntropy/hydro_io.h b/src/hydro/PressureEntropy/hydro_io.h
index ed8e0e45d240ea37ebfb7df6339afd454dc0e4c4..78371c1eb21fafed56e89d46690d0cf1e0f2a0f0 100644
--- a/src/hydro/PressureEntropy/hydro_io.h
+++ b/src/hydro/PressureEntropy/hydro_io.h
@@ -67,18 +67,20 @@ void hydro_read_particles(struct part* parts, struct io_props* list,
                                 UNIT_CONV_DENSITY, parts, rho);
 }
 
-void convert_u(const struct engine* e, const struct part* p, float* ret) {
+void convert_u(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_internal_energy(p);
 }
 
-void convert_P(const struct engine* e, const struct part* p, float* ret) {
+void convert_P(const struct engine* e, const struct part* p,
+               const struct xpart* xp, float* ret) {
 
   ret[0] = hydro_get_comoving_pressure(p);
 }
 
 void convert_part_pos(const struct engine* e, const struct part* p,
-                      double* ret) {
+                      const struct xpart* xp, double* ret) {
 
   if (e->s->periodic) {
     ret[0] = box_wrap(p->x[0], 0.0, e->s->dim[0]);
@@ -91,6 +93,49 @@ void convert_part_pos(const struct engine* e, const struct part* p,
   }
 }
 
+void convert_part_vel(const struct engine* e, const struct part* p,
+                      const struct xpart* xp, float* ret) {
+
+  const int with_cosmology = (e->policy & engine_policy_cosmology);
+  const struct cosmology* cosmo = e->cosmology;
+  const integertime_t ti_current = e->ti_current;
+  const double time_base = e->time_base;
+
+  const integertime_t ti_beg = get_integer_time_begin(ti_current, p->time_bin);
+  const integertime_t ti_end = get_integer_time_end(ti_current, p->time_bin);
+
+  /* Get time-step since the last kick */
+  float dt_kick_grav, dt_kick_hydro;
+  if (with_cosmology) {
+    dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_grav -=
+        cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+    dt_kick_hydro = cosmology_get_hydro_kick_factor(cosmo, ti_beg, ti_current);
+    dt_kick_hydro -=
+        cosmology_get_hydro_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2);
+  } else {
+    dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+    dt_kick_hydro = (ti_current - ((ti_beg + ti_end) / 2)) * time_base;
+  }
+
+  /* Extrapolate the velocites to the current time */
+  hydro_get_drifted_velocities(p, xp, dt_kick_hydro, dt_kick_grav, ret);
+
+  /* Conversion from internal units to peculiar velocities */
+  ret[0] *= cosmo->a2_inv;
+  ret[1] *= cosmo->a2_inv;
+  ret[2] *= cosmo->a2_inv;
+}
+
+void convert_part_potential(const struct engine* e, const struct part* p,
+                            const struct xpart* xp, float* ret) {
+
+  if (p->gpart != NULL)
+    ret[0] = gravity_get_comoving_potential(p->gpart);
+  else
+    ret[0] = 0.f;
+}
+
 /**
  * @brief Specifies which particle fields to write to a dataset
  *
@@ -98,16 +143,17 @@ void convert_part_pos(const struct engine* e, const struct part* p,
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void hydro_write_particles(struct part* parts, struct io_props* list,
-                           int* num_fields) {
+void hydro_write_particles(const struct part* parts, const struct xpart* xparts,
+                           struct io_props* list, int* num_fields) {
 
-  *num_fields = 10;
+  *num_fields = 11;
 
   /* List what we want to write */
-  list[0] = io_make_output_field_convert_part(
-      "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, parts, convert_part_pos);
-  list[1] =
-      io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, v);
+  list[0] = io_make_output_field_convert_part("Coordinates", DOUBLE, 3,
+                                              UNIT_CONV_LENGTH, parts, xparts,
+                                              convert_part_pos);
+  list[1] = io_make_output_field_convert_part(
+      "Velocities", FLOAT, 3, UNIT_CONV_SPEED, parts, xparts, convert_part_vel);
   list[2] =
       io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, parts, mass);
   list[3] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH,
@@ -120,11 +166,14 @@ void hydro_write_particles(struct part* parts, struct io_props* list,
       io_make_output_field("Density", FLOAT, 1, UNIT_CONV_DENSITY, parts, rho);
   list[7] = io_make_output_field_convert_part("InternalEnergy", FLOAT, 1,
                                               UNIT_CONV_ENERGY_PER_UNIT_MASS,
-                                              parts, convert_u);
+                                              parts, xparts, convert_u);
   list[8] = io_make_output_field_convert_part(
-      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, convert_P);
+      "Pressure", FLOAT, 1, UNIT_CONV_PRESSURE, parts, xparts, convert_P);
   list[9] = io_make_output_field("WeightedDensity", FLOAT, 1, UNIT_CONV_DENSITY,
                                  parts, rho_bar);
+  list[10] = io_make_output_field_convert_part("Potential", FLOAT, 1,
+                                               UNIT_CONV_POTENTIAL, parts,
+                                               xparts, convert_part_potential);
 }
 
 /**
diff --git a/src/hydro_properties.c b/src/hydro_properties.c
index 31e18913b7414110db68c6202c512de5fb90a3c1..bd8328946d4bfd078bd10b439e96b35dce457c49 100644
--- a/src/hydro_properties.c
+++ b/src/hydro_properties.c
@@ -36,8 +36,13 @@
 #define hydro_props_default_volume_change 1.4f
 #define hydro_props_default_h_max FLT_MAX
 #define hydro_props_default_h_tolerance 1e-4
+#define hydro_props_default_init_temp 0.f
+#define hydro_props_default_min_temp 0.f
+#define hydro_props_default_H_fraction 0.76
 
 void hydro_props_init(struct hydro_props *p,
+                      const struct phys_const *phys_const,
+                      const struct unit_system *us,
                       const struct swift_params *params) {
 
   /* Kernel properties */
@@ -73,6 +78,53 @@ void hydro_props_init(struct hydro_props *p,
   const float max_volume_change = parser_get_opt_param_float(
       params, "SPH:max_volume_change", hydro_props_default_volume_change);
   p->log_max_h_change = logf(powf(max_volume_change, hydro_dimension_inv));
+
+  /* Initial temperature */
+  p->initial_temperature = parser_get_opt_param_float(
+      params, "SPH:initial_temperature", hydro_props_default_init_temp);
+
+  /* Initial temperature */
+  p->minimal_temperature = parser_get_opt_param_float(
+      params, "SPH:minimal_temperature", hydro_props_default_min_temp);
+
+  if ((p->initial_temperature != 0.) &&
+      (p->initial_temperature < p->minimal_temperature))
+    error("Initial temperature lower than minimal allowed temperature!");
+
+  /* Hydrogen mass fraction */
+  p->hydrogen_mass_fraction = parser_get_opt_param_double(
+      params, "SPH:H_mass_fraction", hydro_props_default_H_fraction);
+
+  /* Compute the initial energy (Note the temp. read is in internal units) */
+  double u_init = phys_const->const_boltzmann_k / phys_const->const_proton_mass;
+  u_init *= p->initial_temperature;
+  u_init *= hydro_one_over_gamma_minus_one;
+
+  /* Correct for hydrogen mass fraction */
+  double mean_molecular_weight;
+  if (p->initial_temperature *
+          units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE) >
+      1e4)
+    mean_molecular_weight = 4. / (8. - 5. * (1. - p->hydrogen_mass_fraction));
+  else
+    mean_molecular_weight = 4. / (1. + 3. * p->hydrogen_mass_fraction);
+
+  p->initial_internal_energy = u_init / mean_molecular_weight;
+
+  /* Compute the minimal energy (Note the temp. read is in internal units) */
+  double u_min = phys_const->const_boltzmann_k / phys_const->const_proton_mass;
+  u_min *= p->initial_temperature;
+  u_min *= hydro_one_over_gamma_minus_one;
+
+  /* Correct for hydrogen mass fraction */
+  if (p->minimal_temperature *
+          units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE) >
+      1e4)
+    mean_molecular_weight = 4. / (8. - 5. * (1. - p->hydrogen_mass_fraction));
+  else
+    mean_molecular_weight = 4. / (1. + 3. * p->hydrogen_mass_fraction);
+
+  p->minimal_internal_energy = u_min / mean_molecular_weight;
 }
 
 void hydro_props_print(const struct hydro_props *p) {
@@ -103,6 +155,12 @@ void hydro_props_print(const struct hydro_props *p) {
   if (p->max_smoothing_iterations != hydro_props_default_max_iterations)
     message("Maximal iterations in ghost task set to %d (default is %d)",
             p->max_smoothing_iterations, hydro_props_default_max_iterations);
+
+  if (p->initial_temperature != hydro_props_default_init_temp)
+    message("Initial gas temperature set to %f", p->initial_temperature);
+
+  if (p->minimal_temperature != hydro_props_default_min_temp)
+    message("Minimal gas temperature set to %f", p->minimal_temperature);
 }
 
 #if defined(HAVE_HDF5)
@@ -125,6 +183,12 @@ void hydro_props_print_snapshot(hid_t h_grpsph, const struct hydro_props *p) {
                        pow_dimension(expf(p->log_max_h_change)));
   io_write_attribute_i(h_grpsph, "Max ghost iterations",
                        p->max_smoothing_iterations);
+  io_write_attribute_f(h_grpsph, "Minimal temperature", p->minimal_temperature);
+  io_write_attribute_f(h_grpsph, "Initial temperature", p->initial_temperature);
+  io_write_attribute_f(h_grpsph, "Initial energy per unit mass",
+                       p->initial_internal_energy);
+  io_write_attribute_f(h_grpsph, "Hydrogen mass fraction",
+                       p->hydrogen_mass_fraction);
 }
 #endif
 
diff --git a/src/hydro_properties.h b/src/hydro_properties.h
index 6d325c35d6ae6a9bcddbfff9ccc4601e026fc4e6..2799f6c86eec7f0ebf140643c5ab7fa9b60e6273 100644
--- a/src/hydro_properties.h
+++ b/src/hydro_properties.h
@@ -33,7 +33,9 @@
 
 /* Local includes. */
 #include "parser.h"
+#include "physical_constants.h"
 #include "restart.h"
+#include "units.h"
 
 /**
  * @brief Contains all the constants and parameters of the hydro scheme
@@ -63,10 +65,28 @@ struct hydro_props {
 
   /*! Maximal change of h over one time-step */
   float log_max_h_change;
+
+  /*! Minimal temperature allowed */
+  float minimal_temperature;
+
+  /*! Minimal internal energy per unit mass */
+  float minimal_internal_energy;
+
+  /*! Initial temperature */
+  float initial_temperature;
+
+  /*! Initial internal energy per unit mass */
+  float initial_internal_energy;
+
+  /*! Primoridal hydrogen mass fraction for initial energy conversion */
+  float hydrogen_mass_fraction;
 };
 
 void hydro_props_print(const struct hydro_props *p);
-void hydro_props_init(struct hydro_props *p, const struct swift_params *params);
+void hydro_props_init(struct hydro_props *p,
+                      const struct phys_const *phys_const,
+                      const struct unit_system *us,
+                      const struct swift_params *params);
 
 #if defined(HAVE_HDF5)
 void hydro_props_print_snapshot(hid_t h_grpsph, const struct hydro_props *p);
diff --git a/src/io_properties.h b/src/io_properties.h
index 17db123ba8325ede0c7af4e4b005e359cace7a7f..55e128e890b75db2d01911bd3c3b46388b0c6597 100644
--- a/src/io_properties.h
+++ b/src/io_properties.h
@@ -34,9 +34,11 @@ enum DATA_IMPORTANCE { COMPULSORY = 1, OPTIONAL = 0, UNUSED = -1 };
 
 /* Helper typedefs */
 typedef void (*conversion_func_part_float)(const struct engine*,
-                                           const struct part*, float*);
+                                           const struct part*,
+                                           const struct xpart*, float*);
 typedef void (*conversion_func_part_double)(const struct engine*,
-                                            const struct part*, double*);
+                                            const struct part*,
+                                            const struct xpart*, double*);
 typedef void (*conversion_func_gpart_float)(const struct engine*,
                                             const struct gpart*, float*);
 typedef void (*conversion_func_gpart_double)(const struct engine*,
@@ -78,6 +80,7 @@ struct io_props {
 
   /* The particle arrays */
   const struct part* parts;
+  const struct xpart* xparts;
   const struct gpart* gparts;
 
   /* Are we converting? */
@@ -125,6 +128,7 @@ INLINE static struct io_props io_make_input_field_(
   r.field = field;
   r.partSize = partSize;
   r.parts = NULL;
+  r.xparts = NULL;
   r.gparts = NULL;
   r.conversion = 0;
   r.convert_part_f = NULL;
@@ -179,10 +183,10 @@ INLINE static struct io_props io_make_output_field_(
 /**
  * @brief Constructs an #io_props (with conversion) from its parameters
  */
-#define io_make_output_field_convert_part(name, type, dim, units, part, \
-                                          convert)                      \
-  io_make_output_field_convert_part_##type(name, type, dim, units,      \
-                                           sizeof(part[0]), part, convert)
+#define io_make_output_field_convert_part(name, type, dim, units, part, xpart, \
+                                          convert)                             \
+  io_make_output_field_convert_part_##type(                                    \
+      name, type, dim, units, sizeof(part[0]), part, xpart, convert)
 
 /**
  * @brief Construct an #io_props from its parameters
@@ -193,6 +197,7 @@ INLINE static struct io_props io_make_output_field_(
  * @param units The units of the dataset
  * @param partSize The size in byte of the particle
  * @param parts The particle array
+ * @param xparts The xparticle array
  * @param functionPtr The function used to convert a particle to a float
  *
  * Do not call this function directly. Use the macro defined above.
@@ -200,7 +205,8 @@ INLINE static struct io_props io_make_output_field_(
 INLINE static struct io_props io_make_output_field_convert_part_FLOAT(
     const char name[FIELD_BUFFER_SIZE], enum IO_DATA_TYPE type, int dimension,
     enum unit_conversion_factor units, size_t partSize,
-    const struct part* parts, conversion_func_part_float functionPtr) {
+    const struct part* parts, const struct xpart* xparts,
+    conversion_func_part_float functionPtr) {
 
   struct io_props r;
   strcpy(r.name, name);
@@ -211,6 +217,7 @@ INLINE static struct io_props io_make_output_field_convert_part_FLOAT(
   r.field = NULL;
   r.partSize = partSize;
   r.parts = parts;
+  r.xparts = xparts;
   r.gparts = NULL;
   r.conversion = 1;
   r.convert_part_f = functionPtr;
@@ -230,6 +237,7 @@ INLINE static struct io_props io_make_output_field_convert_part_FLOAT(
  * @param units The units of the dataset
  * @param partSize The size in byte of the particle
  * @param parts The particle array
+ * @param xparts The xparticle array
  * @param functionPtr The function used to convert a particle to a float
  *
  * Do not call this function directly. Use the macro defined above.
@@ -237,7 +245,8 @@ INLINE static struct io_props io_make_output_field_convert_part_FLOAT(
 INLINE static struct io_props io_make_output_field_convert_part_DOUBLE(
     const char name[FIELD_BUFFER_SIZE], enum IO_DATA_TYPE type, int dimension,
     enum unit_conversion_factor units, size_t partSize,
-    const struct part* parts, conversion_func_part_double functionPtr) {
+    const struct part* parts, const struct xpart* xparts,
+    conversion_func_part_double functionPtr) {
 
   struct io_props r;
   strcpy(r.name, name);
@@ -248,6 +257,7 @@ INLINE static struct io_props io_make_output_field_convert_part_DOUBLE(
   r.field = NULL;
   r.partSize = partSize;
   r.parts = parts;
+  r.xparts = xparts;
   r.gparts = NULL;
   r.conversion = 1;
   r.convert_part_f = NULL;
@@ -293,6 +303,7 @@ INLINE static struct io_props io_make_output_field_convert_gpart_FLOAT(
   r.field = NULL;
   r.partSize = gpartSize;
   r.parts = NULL;
+  r.xparts = NULL;
   r.gparts = gparts;
   r.conversion = 1;
   r.convert_part_f = NULL;
@@ -330,6 +341,7 @@ INLINE static struct io_props io_make_output_field_convert_gpart_DOUBLE(
   r.field = NULL;
   r.partSize = gpartSize;
   r.parts = NULL;
+  r.xparts = NULL;
   r.gparts = gparts;
   r.conversion = 1;
   r.convert_part_f = NULL;
diff --git a/src/kernel_gravity.h b/src/kernel_gravity.h
index 24d30136c8213dab6db424f2f459766c45ec6b1e..dc9db63f9d59ad0b3e72792b33b38a961ea6c30f 100644
--- a/src/kernel_gravity.h
+++ b/src/kernel_gravity.h
@@ -26,6 +26,10 @@
 #include "inline.h"
 #include "minmax.h"
 
+/*! Conversion factor between Plummer softening and internal softening */
+#define kernel_gravity_softening_plummer_equivalent 3.
+#define kernel_gravity_softening_plummer_equivalent_inv (1. / 3.)
+
 /**
  * @brief Computes the gravity softening function for potential.
  *
diff --git a/src/kick.h b/src/kick.h
index 9b1f4f18112a1cb2affcff70e7773ba4c48681b5..9d10f1e78d3934c4277c14217cbbc46514e87033 100644
--- a/src/kick.h
+++ b/src/kick.h
@@ -68,13 +68,16 @@ __attribute__((always_inline)) INLINE static void kick_gpart(
  * @param dt_kick_hydro The kick time-step for hydro accelerations.
  * @param dt_kick_grav The kick time-step for gravity accelerations.
  * @param dt_kick_therm The kick time-step for changes in thermal state.
+ * @param cosmo The cosmological model.
+ * @param hydro_props The constants used in the scheme
  * @param ti_start The starting (integer) time of the kick (for debugging
  * checks).
  * @param ti_end The ending (integer) time of the kick (for debugging checks).
  */
 __attribute__((always_inline)) INLINE static void kick_part(
     struct part *restrict p, struct xpart *restrict xp, double dt_kick_hydro,
-    double dt_kick_grav, double dt_kick_therm, integertime_t ti_start,
+    double dt_kick_grav, double dt_kick_therm, const struct cosmology *cosmo,
+    const struct hydro_props *hydro_props, integertime_t ti_start,
     integertime_t ti_end) {
 
 #ifdef SWIFT_DEBUG_CHECKS
@@ -107,7 +110,7 @@ __attribute__((always_inline)) INLINE static void kick_part(
   }
 
   /* Extra kick work */
-  hydro_kick_extra(p, xp, dt_kick_therm);
+  hydro_kick_extra(p, xp, dt_kick_therm, cosmo, hydro_props);
   if (p->gpart != NULL) gravity_kick_extra(p->gpart, dt_kick_grav);
 }
 
diff --git a/src/logger.c b/src/logger.c
index 38cb220b94dd14680584e9edca75883e1df16907..5fd4145aa1b042ed806dd3fe5487d094600b66c4 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -218,12 +218,6 @@ void logger_log_gpart(struct gpart *p, unsigned int mask, size_t *offset,
     buff += 3 * sizeof(float);
   }
 
-  /* Particle smoothing length as a single float. */
-  if (mask & logger_mask_h) {
-    memcpy(buff, &p->epsilon, sizeof(float));
-    buff += sizeof(float);
-  }
-
   /* Particle constants, which is a bit more complicated. */
   if (mask & logger_mask_rho) {
     memcpy(buff, &p->mass, sizeof(float));
@@ -385,12 +379,6 @@ int logger_read_gpart(struct gpart *p, size_t *offset, const char *buff) {
     buff += 3 * sizeof(float);
   }
 
-  /* Particle smoothing length as a single float. */
-  if (mask & logger_mask_h) {
-    memcpy(&p->epsilon, buff, sizeof(float));
-    buff += sizeof(float);
-  }
-
   /* Particle constants, which is a bit more complicated. */
   if (mask & logger_mask_rho) {
     memcpy(&p->mass, buff, sizeof(float));
diff --git a/src/multipole.h b/src/multipole.h
index 852976ad552b3ccf16f3e084612166c9212df2a6..dd74c4a40d79cc393e252bfe061591dd868f2a55 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -1524,8 +1524,8 @@ INLINE static void gravity_M2L(struct grav_tensor *l_b,
                                const double dim[3]) {
 
   /* Recover some constants */
-  const float eps = props->epsilon;
-  const float eps_inv = props->epsilon_inv;
+  const float eps = props->epsilon_cur;
+  const float eps_inv = props->epsilon_cur_inv;
 
   /* Compute distance vector */
   float dx = (float)(pos_b[0] - pos_a[0]);
@@ -2380,6 +2380,7 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb,
   gp->a_grav[2] += a_grav[2];
   gp->potential += pot;
 }
+
 /**
  * @brief Checks whether a cell-cell interaction can be appromixated by a M-M
  * interaction using the distance and cell radius.
diff --git a/src/parallel_io.c b/src/parallel_io.c
index d3f5f8dc36dd63ad1b7cf4d65311751cd15f887b..51c88e95396eb6af1ab7f7eb2d1ed48eada59e0d 100644
--- a/src/parallel_io.c
+++ b/src/parallel_io.c
@@ -69,11 +69,14 @@
  * @param offset Offset in the array where this mpi task starts writing.
  * @param internal_units The #unit_system used internally.
  * @param ic_units The #unit_system used in the snapshots.
+ * @param cleanup_h Are we removing h-factors from the ICs?
+ * @param h The value of the reduced Hubble constant to use for cleaning.
  */
 void readArray_chunk(hid_t h_data, hid_t h_plist_id,
                      const struct io_props props, size_t N, long long offset,
                      const struct unit_system* internal_units,
-                     const struct unit_system* ic_units) {
+                     const struct unit_system* ic_units, int cleanup_h,
+                     double h) {
 
   const size_t typeSize = io_sizeof_type(props.type);
   const size_t copySize = typeSize * props.dimension;
@@ -136,6 +139,23 @@ void readArray_chunk(hid_t h_data, hid_t h_plist_id,
     }
   }
 
+  /* Clean-up h if necessary */
+  const float h_factor_exp = units_h_factor(internal_units, props.units);
+  if (cleanup_h && h_factor_exp != 0.f) {
+    const double h_factor = pow(h, h_factor_exp);
+
+    /* message("Multipltying '%s' by h^%f=%f", props.name, h_factor_exp,
+     * h_factor); */
+
+    if (io_is_double_precision(props.type)) {
+      double* temp_d = (double*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= h_factor;
+    } else {
+      float* temp_f = (float*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= h_factor;
+    }
+  }
+
   /* Copy temporary buffer to particle data */
   char* temp_c = (char*)temp;
   for (size_t i = 0; i < N; ++i)
@@ -158,11 +178,13 @@ void readArray_chunk(hid_t h_data, hid_t h_plist_id,
  * @param offset The offset in the array on disk for this rank.
  * @param internal_units The #unit_system used internally.
  * @param ic_units The #unit_system used in the ICs.
+ * @param cleanup_h Are we removing h-factors from the ICs?
+ * @param h The value of the reduced Hubble constant to use for cleaning.
  */
 void readArray(hid_t grp, struct io_props props, size_t N, long long N_total,
                int mpi_rank, long long offset,
                const struct unit_system* internal_units,
-               const struct unit_system* ic_units) {
+               const struct unit_system* ic_units, int cleanup_h, double h) {
 
   const size_t typeSize = io_sizeof_type(props.type);
   const size_t copySize = typeSize * props.dimension;
@@ -207,7 +229,7 @@ void readArray(hid_t grp, struct io_props props, size_t N, long long N_total,
     /* Write the first chunk */
     const size_t this_chunk = (N > max_chunk_size) ? max_chunk_size : N;
     readArray_chunk(h_data, h_plist_id, props, this_chunk, offset,
-                    internal_units, ic_units);
+                    internal_units, ic_units, cleanup_h, h);
 
     /* Compute how many items are left */
     if (N > max_chunk_size) {
@@ -309,8 +331,7 @@ void prepareArray(struct engine* e, hid_t grp, char* fileName, FILE* xmfFile,
   io_write_attribute_d(
       h_data, "CGS conversion factor",
       units_cgs_conversion_factor(snapshot_units, props.units));
-  io_write_attribute_f(h_data, "h-scale exponent",
-                       units_h_factor(snapshot_units, props.units));
+  io_write_attribute_f(h_data, "h-scale exponent", 0);
   io_write_attribute_f(h_data, "a-scale exponent",
                        units_a_factor(snapshot_units, props.units));
   io_write_attribute_s(h_data, "Conversion factor", buffer);
@@ -541,6 +562,8 @@ void writeArray(struct engine* e, hid_t grp, char* fileName,
  * @param with_hydro Are we running with hydro ?
  * @param with_gravity Are we running with gravity ?
  * @param with_stars Are we running with stars ?
+ * @param cleanup_h Are we cleaning-up h-factors from the quantities we read?
+ * @param h The value of the reduced Hubble constant to use for correction.
  * @param mpi_rank The MPI rank of this node
  * @param mpi_size The number of MPI ranks
  * @param comm The MPI communicator
@@ -554,8 +577,9 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
                       struct spart** sparts, size_t* Ngas, size_t* Ngparts,
                       size_t* Nstars, int* periodic, int* flag_entropy,
                       int with_hydro, int with_gravity, int with_stars,
-                      int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                      int n_threads, int dry_run) {
+                      int cleanup_h, double h, int mpi_rank, int mpi_size,
+                      MPI_Comm comm, MPI_Info info, int n_threads,
+                      int dry_run) {
 
   hid_t h_file = 0, h_grp = 0;
   /* GADGET has only cubic boxes (in cosmological mode) */
@@ -626,6 +650,13 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
   else if (hydro_dimension == 1)
     dim[2] = dim[1] = dim[0];
 
+  /* Convert the box size if we want to clean-up h-factors */
+  if (cleanup_h) {
+    dim[0] /= h;
+    dim[1] /= h;
+    dim[2] /= h;
+  }
+
   /* message("Found %lld particles in a %speriodic box of size [%f %f %f].", */
   /* 	  N_total[0], (periodic ? "": "non-"), dim[0], */
   /* 	  dim[1], dim[2]); */
@@ -771,7 +802,7 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
     if (!dry_run)
       for (int i = 0; i < num_fields; ++i)
         readArray(h_grp, list[i], Nparticles, N_total[ptype], mpi_rank,
-                  offset[ptype], internal_units, ic_units);
+                  offset[ptype], internal_units, ic_units, cleanup_h, h);
 
     /* Close particle group */
     H5Gclose(h_grp);
@@ -821,9 +852,10 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6],
                   const struct unit_system* internal_units,
                   const struct unit_system* snapshot_units) {
 
-  struct part* parts = e->s->parts;
-  struct gpart* gparts = e->s->gparts;
-  struct spart* sparts = e->s->sparts;
+  const struct part* parts = e->s->parts;
+  const struct xpart* xparts = e->s->xparts;
+  const struct gpart* gparts = e->s->gparts;
+  const struct spart* sparts = e->s->sparts;
   FILE* xmfFile = 0;
   int periodic = e->s->periodic;
   int numFiles = 1;
@@ -980,7 +1012,7 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6],
     switch (ptype) {
 
       case swift_type_gas:
-        hydro_write_particles(parts, list, &num_fields);
+        hydro_write_particles(parts, xparts, list, &num_fields);
         num_fields += chemistry_write_particles(parts, list + num_fields);
         break;
 
@@ -1045,10 +1077,11 @@ void write_output_parallel(struct engine* e, const char* baseName,
   const size_t Ngas = e->s->nr_parts;
   const size_t Nstars = e->s->nr_sparts;
   const size_t Ntot = e->s->nr_gparts;
-  struct part* parts = e->s->parts;
-  struct gpart* gparts = e->s->gparts;
+  const struct part* parts = e->s->parts;
+  const struct xpart* xparts = e->s->xparts;
+  const struct gpart* gparts = e->s->gparts;
   struct gpart* dmparts = NULL;
-  struct spart* sparts = e->s->sparts;
+  const struct spart* sparts = e->s->sparts;
 
   /* Number of unassociated gparts */
   const size_t Ndm = Ntot > 0 ? Ntot - (Ngas + Nstars) : 0;
@@ -1208,7 +1241,7 @@ void write_output_parallel(struct engine* e, const char* baseName,
 
       case swift_type_gas:
         Nparticles = Ngas;
-        hydro_write_particles(parts, list, &num_fields);
+        hydro_write_particles(parts, xparts, list, &num_fields);
         num_fields += chemistry_write_particles(parts, list + num_fields);
         break;
 
diff --git a/src/parallel_io.h b/src/parallel_io.h
index 207e478c341488deb056761b37fb9c7370744b38..5ad3b34cdc4320d6fe3eb860615db33958ad612f 100644
--- a/src/parallel_io.h
+++ b/src/parallel_io.h
@@ -22,6 +22,8 @@
 /* Config parameters. */
 #include "../config.h"
 
+#if defined(HAVE_HDF5) && defined(WITH_MPI) && defined(HAVE_PARALLEL_HDF5)
+
 /* MPI headers. */
 #ifdef WITH_MPI
 #include <mpi.h>
@@ -32,15 +34,14 @@
 #include "part.h"
 #include "units.h"
 
-#if defined(HAVE_HDF5) && defined(WITH_MPI) && defined(HAVE_PARALLEL_HDF5)
-
 void read_ic_parallel(char* fileName, const struct unit_system* internal_units,
                       double dim[3], struct part** parts, struct gpart** gparts,
                       struct spart** sparts, size_t* Ngas, size_t* Ngparts,
                       size_t* Nsparts, int* periodic, int* flag_entropy,
                       int with_hydro, int with_gravity, int with_stars,
-                      int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                      int nr_threads, int dry_run);
+                      int cleanup_h, double h, int mpi_rank, int mpi_size,
+                      MPI_Comm comm, MPI_Info info, int nr_threads,
+                      int dry_run);
 
 void write_output_parallel(struct engine* e, const char* baseName,
                            const struct unit_system* internal_units,
diff --git a/src/part.c b/src/part.c
index 712a13d42a629355290bcf89f31b94fb9670a215..c43ffa4820504282b4fb02e63b5cfc4196f3be77 100644
--- a/src/part.c
+++ b/src/part.c
@@ -119,7 +119,7 @@ void part_verify_links(struct part *parts, struct gpart *gparts,
     if (gparts[k].type == swift_type_dark_matter) {
 
       /* Check that it's not linked */
-      if (gparts[k].id_or_neg_offset < 0)
+      if (gparts[k].id_or_neg_offset <= 0)
         error("DM gpart particle linked to something !");
     }
 
diff --git a/src/partition.c b/src/partition.c
index 8203c255d484672254b249042db22f5952579b4e..8feae3b7a8dce7c78310a3b35762d31b439c69e3 100644
--- a/src/partition.c
+++ b/src/partition.c
@@ -48,6 +48,7 @@
 
 /* Local headers. */
 #include "debug.h"
+#include "engine.h"
 #include "error.h"
 #include "partition.h"
 #include "restart.h"
diff --git a/src/runner.c b/src/runner.c
index 1b8f9a2fc84b08c590396f1251a6bf3c5cc3189e..35996a3ba9a760d5f019ede35abc207bbdcbe1b3 100644
--- a/src/runner.c
+++ b/src/runner.c
@@ -981,6 +981,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) {
 
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
+  const struct hydro_props *hydro_props = e->hydro_properties;
   const int with_cosmology = (e->policy & engine_policy_cosmology);
   struct part *restrict parts = c->parts;
   struct xpart *restrict xparts = c->xparts;
@@ -1044,8 +1045,8 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) {
         }
 
         /* do the kick */
-        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, ti_begin,
-                  ti_begin + ti_step / 2);
+        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, cosmo,
+                  hydro_props, ti_begin, ti_begin + ti_step / 2);
 
         /* Update the accelerations to be used in the drift for hydro */
         if (p->gpart != NULL) {
@@ -1150,6 +1151,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) {
 
   const struct engine *e = r->e;
   const struct cosmology *cosmo = e->cosmology;
+  const struct hydro_props *hydro_props = e->hydro_properties;
   const int with_cosmology = (e->policy & engine_policy_cosmology);
   const int count = c->count;
   const int gcount = c->gcount;
@@ -1209,8 +1211,8 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) {
         }
 
         /* Finish the time-step with a second half-kick */
-        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm,
-                  ti_begin + ti_step / 2, ti_begin + ti_step);
+        kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, cosmo,
+                  hydro_props, ti_begin + ti_step / 2, ti_begin + ti_step);
 
 #ifdef SWIFT_DEBUG_CHECKS
         /* Check that kick and the drift are synchronized */
diff --git a/src/runner_doiact_grav.h b/src/runner_doiact_grav.h
index cec450d84449d2b8cbb6790fcf9a596bb24649be..4f353a317e9f312f5ae6627cfaf0c06d176e8fad 100644
--- a/src/runner_doiact_grav.h
+++ b/src/runner_doiact_grav.h
@@ -466,7 +466,6 @@ static INLINE void runner_dopair_grav_pp(struct runner *r, struct cell *ci,
   struct space *s = e->s;
   const int periodic = s->periodic;
   const double cell_width = s->width[0];
-  const float theta_crit2 = e->gravity_properties->theta_crit2;
   const double a_smooth = e->gravity_properties->a_smooth;
   const double r_cut_min = e->gravity_properties->r_cut_min;
   const double rlr = cell_width * a_smooth;
@@ -532,11 +531,11 @@ static INLINE void runner_dopair_grav_pp(struct runner *r, struct cell *ci,
 
   /* Fill the caches */
   gravity_cache_populate(e->max_active_bin, ci_cache, ci->gparts, gcount_i,
-                         gcount_padded_i, shift_i, CoM_j, rmax2_j, theta_crit2,
-                         ci);
+                         gcount_padded_i, shift_i, CoM_j, rmax2_j, ci,
+                         e->gravity_properties);
   gravity_cache_populate(e->max_active_bin, cj_cache, cj->gparts, gcount_j,
-                         gcount_padded_j, shift_j, CoM_i, rmax2_i, theta_crit2,
-                         cj);
+                         gcount_padded_j, shift_j, CoM_i, rmax2_i, cj,
+                         e->gravity_properties);
 
   /* Can we use the Newtonian version or do we need the truncated one ? */
   if (!periodic) {
@@ -675,7 +674,7 @@ static INLINE void runner_doself_grav_pp_full(struct runner *r,
   const int gcount_padded = gcount - (gcount % VEC_SIZE) + VEC_SIZE;
 
   gravity_cache_populate_no_mpole(e->max_active_bin, ci_cache, gparts, gcount,
-                                  gcount_padded, loc, c);
+                                  gcount_padded, loc, c, e->gravity_properties);
 
   /* Ok... Here we go ! */
 
@@ -805,7 +804,7 @@ static INLINE void runner_doself_grav_pp_truncated(struct runner *r,
   const int gcount_padded = gcount - (gcount % VEC_SIZE) + VEC_SIZE;
 
   gravity_cache_populate_no_mpole(e->max_active_bin, ci_cache, gparts, gcount,
-                                  gcount_padded, loc, c);
+                                  gcount_padded, loc, c, e->gravity_properties);
 
   /* Ok... Here we go ! */
 
diff --git a/src/runner_doiact_vec.c b/src/runner_doiact_vec.c
index 0daea0cf8a8d868ccb14f7d9b27f04aca5a677c8..2e86280d64491ee1750f41c2cd22ab01c08e30b8 100644
--- a/src/runner_doiact_vec.c
+++ b/src/runner_doiact_vec.c
@@ -1689,7 +1689,7 @@ void runner_dopair_subset_density_vec(struct runner *r,
                                       struct cell *restrict cj, const int sid,
                                       const int flipped, const double *shift) {
 
-#ifdef WITH_VECTORIZATION
+#if defined(WITH_VECTORIZATION) && defined(GADGET2_SPH)
 
   TIMER_TIC;
 
diff --git a/src/scheduler.c b/src/scheduler.c
index 072235be1807db972208514739409cdb1e76c0d6..151304293749a29abe9bd9680d8f8f81bc845884 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -1435,7 +1435,8 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) {
     switch (t->type) {
       case task_type_self:
       case task_type_sub_self:
-        if (t->subtype == task_subtype_grav || t->subtype == task_subtype_external_grav)
+        if (t->subtype == task_subtype_grav ||
+            t->subtype == task_subtype_external_grav)
           qid = t->ci->super_gravity->owner;
         else
           qid = t->ci->super_hydro->owner;
diff --git a/src/serial_io.c b/src/serial_io.c
index aa8d126e4c6f3e19aed7d205c7ced39f7eded6f8..dd623f946ce6ec32415586e5048979de3adb58fa 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -67,6 +67,8 @@
  * @param offset The offset position where this rank starts reading.
  * @param internal_units The #unit_system used internally
  * @param ic_units The #unit_system used in the ICs
+ * @param cleanup_h Are we removing h-factors from the ICs?
+ * @param h The value of the reduced Hubble constant to use for cleaning.
  *
  * @todo A better version using HDF5 hyper-slabs to read the file directly into
  * the part array will be written once the structures have been stabilized.
@@ -74,7 +76,7 @@
 void readArray(hid_t grp, const struct io_props props, size_t N,
                long long N_total, long long offset,
                const struct unit_system* internal_units,
-               const struct unit_system* ic_units) {
+               const struct unit_system* ic_units, int cleanup_h, double h) {
 
   const size_t typeSize = io_sizeof_type(props.type);
   const size_t copySize = typeSize * props.dimension;
@@ -161,6 +163,23 @@ void readArray(hid_t grp, const struct io_props props, size_t N,
     }
   }
 
+  /* Clean-up h if necessary */
+  const float h_factor_exp = units_h_factor(internal_units, props.units);
+  if (cleanup_h && h_factor_exp != 0.f && exist != 0) {
+    const double h_factor = pow(h, h_factor_exp);
+
+    /* message("Multipltying '%s' by h^%f=%f", props.name, h_factor_exp,
+     * h_factor); */
+
+    if (io_is_double_precision(props.type)) {
+      double* temp_d = (double*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= h_factor;
+    } else {
+      float* temp_f = (float*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= h_factor;
+    }
+  }
+
   /* Copy temporary buffer to particle data */
   char* temp_c = temp;
   for (size_t i = 0; i < N; ++i)
@@ -256,8 +275,7 @@ void prepareArray(const struct engine* e, hid_t grp, char* fileName,
   io_write_attribute_d(
       h_data, "CGS conversion factor",
       units_cgs_conversion_factor(snapshot_units, props.units));
-  io_write_attribute_f(h_data, "h-scale exponent",
-                       units_h_factor(snapshot_units, props.units));
+  io_write_attribute_f(h_data, "h-scale exponent", 0);
   io_write_attribute_f(h_data, "a-scale exponent",
                        units_a_factor(snapshot_units, props.units));
   io_write_attribute_s(h_data, "Conversion factor", buffer);
@@ -382,6 +400,8 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
  * @param with_hydro Are we reading gas particles ?
  * @param with_gravity Are we reading/creating #gpart arrays ?
  * @param with_stars Are we reading star particles ?
+ * @param cleanup_h Are we cleaning-up h-factors from the quantities we read?
+ * @param h The value of the reduced Hubble constant to use for correction.
  * @param mpi_rank The MPI rank of this node
  * @param mpi_size The number of MPI ranks
  * @param comm The MPI communicator
@@ -402,8 +422,8 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
                     struct spart** sparts, size_t* Ngas, size_t* Ngparts,
                     size_t* Nstars, int* periodic, int* flag_entropy,
                     int with_hydro, int with_gravity, int with_stars,
-                    int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                    int n_threads, int dry_run) {
+                    int cleanup_h, double h, int mpi_rank, int mpi_size,
+                    MPI_Comm comm, MPI_Info info, int n_threads, int dry_run) {
 
   hid_t h_file = 0, h_grp = 0;
   /* GADGET has only cubic boxes (in cosmological mode) */
@@ -476,6 +496,13 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
     else if (hydro_dimension == 1)
       dim[2] = dim[1] = dim[0];
 
+    /* Convert the box size if we want to clean-up h-factors */
+    if (cleanup_h) {
+      dim[0] /= h;
+      dim[1] /= h;
+      dim[2] /= h;
+    }
+
     /* message("Found %lld particles in a %speriodic box of size [%f %f %f].",
      */
     /* 	    N_total, (periodic ? "": "non-"), dim[0], dim[1], dim[2]); */
@@ -641,7 +668,7 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
         if (!dry_run)
           for (int i = 0; i < num_fields; ++i)
             readArray(h_grp, list[i], Nparticles, N_total[ptype], offset[ptype],
-                      internal_units, ic_units);
+                      internal_units, ic_units, cleanup_h, h);
 
         /* Close particle group */
         H5Gclose(h_grp);
@@ -712,10 +739,11 @@ void write_output_serial(struct engine* e, const char* baseName,
   const size_t Ntot = e->s->nr_gparts;
   int periodic = e->s->periodic;
   int numFiles = 1;
-  struct part* parts = e->s->parts;
-  struct gpart* gparts = e->s->gparts;
+  const struct part* parts = e->s->parts;
+  const struct xpart* xparts = e->s->xparts;
+  const struct gpart* gparts = e->s->gparts;
   struct gpart* dmparts = NULL;
-  struct spart* sparts = e->s->sparts;
+  const struct spart* sparts = e->s->sparts;
   FILE* xmfFile = 0;
 
   /* Number of unassociated gparts */
@@ -962,7 +990,7 @@ void write_output_serial(struct engine* e, const char* baseName,
 
           case swift_type_gas:
             Nparticles = Ngas;
-            hydro_write_particles(parts, list, &num_fields);
+            hydro_write_particles(parts, xparts, list, &num_fields);
             num_fields += chemistry_write_particles(parts, list + num_fields);
             break;
 
diff --git a/src/serial_io.h b/src/serial_io.h
index 025faffc0087a8b26d4149914e621a978e63c9be..cad428916f400bc9b144dcf4c23f9d38c75c1e9d 100644
--- a/src/serial_io.h
+++ b/src/serial_io.h
@@ -22,6 +22,8 @@
 /* Config parameters. */
 #include "../config.h"
 
+#if defined(HAVE_HDF5) && defined(WITH_MPI) && !defined(HAVE_PARALLEL_HDF5)
+
 /* MPI headers. */
 #ifdef WITH_MPI
 #include <mpi.h>
@@ -32,15 +34,13 @@
 #include "part.h"
 #include "units.h"
 
-#if defined(HAVE_HDF5) && defined(WITH_MPI) && !defined(HAVE_PARALLEL_HDF5)
-
 void read_ic_serial(char* fileName, const struct unit_system* internal_units,
                     double dim[3], struct part** parts, struct gpart** gparts,
                     struct spart** sparts, size_t* Ngas, size_t* Ngparts,
                     size_t* Nstars, int* periodic, int* flag_entropy,
                     int with_hydro, int with_gravity, int with_stars,
-                    int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                    int nr_threads, int dry_run);
+                    int cleanup_h, double h, int mpi_rank, int mpi_size,
+                    MPI_Comm comm, MPI_Info info, int nr_threads, int dry_run);
 
 void write_output_serial(struct engine* e, const char* baseName,
                          const struct unit_system* internal_units,
diff --git a/src/single_io.c b/src/single_io.c
index 0fecd724908f7ce2779526792ce8512b9236d58e..2170bcffc4ce3ab21f1edd168d1dc37b2b4af963 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -64,13 +64,15 @@
  * @param N The number of particles.
  * @param internal_units The #unit_system used internally
  * @param ic_units The #unit_system used in the ICs
+ * @param cleanup_h Are we removing h-factors from the ICs?
+ * @param The value of the reduced Hubble constant.
  *
  * @todo A better version using HDF5 hyper-slabs to read the file directly into
  * the part array will be written once the structures have been stabilized.
  */
 void readArray(hid_t h_grp, const struct io_props prop, size_t N,
                const struct unit_system* internal_units,
-               const struct unit_system* ic_units) {
+               const struct unit_system* ic_units, int cleanup_h, double h) {
 
   const size_t typeSize = io_sizeof_type(prop.type);
   const size_t copySize = typeSize * prop.dimension;
@@ -124,18 +126,35 @@ void readArray(hid_t h_grp, const struct io_props prop, size_t N,
   }
 
   /* Unit conversion if necessary */
-  const double factor =
+  const double unit_factor =
       units_conversion_factor(ic_units, internal_units, prop.units);
-  if (factor != 1. && exist != 0) {
+  if (unit_factor != 1. && exist != 0) {
 
     /* message("Converting ! factor=%e", factor); */
 
     if (io_is_double_precision(prop.type)) {
       double* temp_d = (double*)temp;
-      for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= factor;
+      for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= unit_factor;
     } else {
       float* temp_f = (float*)temp;
-      for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= factor;
+      for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= unit_factor;
+    }
+  }
+
+  /* Clean-up h if necessary */
+  const float h_factor_exp = units_h_factor(internal_units, prop.units);
+  if (cleanup_h && h_factor_exp != 0.f && exist != 0) {
+    const double h_factor = pow(h, h_factor_exp);
+
+    /* message("Multipltying '%s' by h^%f=%f", prop.name, h_factor_exp,
+     * h_factor); */
+
+    if (io_is_double_precision(prop.type)) {
+      double* temp_d = (double*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_d[i] *= h_factor;
+    } else {
+      float* temp_f = (float*)temp;
+      for (size_t i = 0; i < num_elements; ++i) temp_f[i] *= h_factor;
     }
   }
 
@@ -270,8 +289,7 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
   io_write_attribute_d(
       h_data, "CGS conversion factor",
       units_cgs_conversion_factor(snapshot_units, props.units));
-  io_write_attribute_f(h_data, "h-scale exponent",
-                       units_h_factor(snapshot_units, props.units));
+  io_write_attribute_f(h_data, "h-scale exponent", 0);
   io_write_attribute_f(h_data, "a-scale exponent",
                        units_a_factor(snapshot_units, props.units));
   io_write_attribute_s(h_data, "Conversion factor", buffer);
@@ -301,6 +319,9 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName,
  * @param with_hydro Are we reading gas particles ?
  * @param with_gravity Are we reading/creating #gpart arrays ?
  * @param with_stars Are we reading star particles ?
+ * @param cleanup_h Are we cleaning-up h-factors from the quantities we read?
+ * @param h The value of the reduced Hubble constant to use for correction.
+ * @prarm n_threads The number of threads to use for the temporary threadpool.
  * @param dry_run If 1, don't read the particle. Only allocates the arrays.
  *
  * Opens the HDF5 file fileName and reads the particles contained
@@ -316,7 +337,7 @@ void read_ic_single(char* fileName, const struct unit_system* internal_units,
                     struct spart** sparts, size_t* Ngas, size_t* Ngparts,
                     size_t* Nstars, int* periodic, int* flag_entropy,
                     int with_hydro, int with_gravity, int with_stars,
-                    int n_threads, int dry_run) {
+                    int cleanup_h, double h, int n_threads, int dry_run) {
 
   hid_t h_file = 0, h_grp = 0;
   /* GADGET has only cubic boxes (in cosmological mode) */
@@ -384,6 +405,13 @@ void read_ic_single(char* fileName, const struct unit_system* internal_units,
   else if (hydro_dimension == 1)
     dim[2] = dim[1] = dim[0];
 
+  /* Convert the box size if we want to clean-up h-factors */
+  if (cleanup_h) {
+    dim[0] /= h;
+    dim[1] /= h;
+    dim[2] /= h;
+  }
+
   /* message("Found %d particles in a %speriodic box of size [%f %f %f].",  */
   /* 	  *N, (periodic ? "": "non-"), dim[0], dim[1], dim[2]);  */
 
@@ -517,7 +545,8 @@ void read_ic_single(char* fileName, const struct unit_system* internal_units,
     /* Read everything */
     if (!dry_run)
       for (int i = 0; i < num_fields; ++i)
-        readArray(h_grp, list[i], Nparticles, internal_units, ic_units);
+        readArray(h_grp, list[i], Nparticles, internal_units, ic_units,
+                  cleanup_h, h);
 
     /* Close particle group */
     H5Gclose(h_grp);
@@ -578,10 +607,11 @@ void write_output_single(struct engine* e, const char* baseName,
   const size_t Ntot = e->s->nr_gparts;
   int periodic = e->s->periodic;
   int numFiles = 1;
-  struct part* parts = e->s->parts;
-  struct gpart* gparts = e->s->gparts;
+  const struct part* parts = e->s->parts;
+  const struct xpart* xparts = e->s->xparts;
+  const struct gpart* gparts = e->s->gparts;
   struct gpart* dmparts = NULL;
-  struct spart* sparts = e->s->sparts;
+  const struct spart* sparts = e->s->sparts;
 
   /* Number of unassociated gparts */
   const size_t Ndm = Ntot > 0 ? Ntot - (Ngas + Nstars) : 0;
@@ -779,7 +809,7 @@ void write_output_single(struct engine* e, const char* baseName,
 
       case swift_type_gas:
         N = Ngas;
-        hydro_write_particles(parts, list, &num_fields);
+        hydro_write_particles(parts, xparts, list, &num_fields);
         num_fields += chemistry_write_particles(parts, list + num_fields);
         break;
 
diff --git a/src/single_io.h b/src/single_io.h
index efed4ef27ade61f7726777d71a2fdc586ea26030..26b849716e3e018d9a10c5c5c513ad26c7ccb274 100644
--- a/src/single_io.h
+++ b/src/single_io.h
@@ -22,24 +22,24 @@
 /* Config parameters. */
 #include "../config.h"
 
+#if defined(HAVE_HDF5) && !defined(WITH_MPI)
+
 /* Includes. */
 #include "engine.h"
 #include "part.h"
 #include "units.h"
 
-#if defined(HAVE_HDF5) && !defined(WITH_MPI)
-
 void read_ic_single(char* fileName, const struct unit_system* internal_units,
                     double dim[3], struct part** parts, struct gpart** gparts,
                     struct spart** sparts, size_t* Ngas, size_t* Ndm,
                     size_t* Nstars, int* periodic, int* flag_entropy,
                     int with_hydro, int with_gravity, int with_stars,
-                    int nr_threads, int dry_run);
+                    int cleanup_h, double h, int nr_threads, int dry_run);
 
 void write_output_single(struct engine* e, const char* baseName,
                          const struct unit_system* internal_units,
                          const struct unit_system* snapshot_units);
 
-#endif
+#endif /* HAVE_HDF5 && !WITH_MPI */
 
 #endif /* SWIFT_SINGLE_IO_H */
diff --git a/src/space.c b/src/space.c
index 329526fe14e38220750903058bc5201ef7486f63..273e01858f443174d5fb90477cc38e19d4375d67 100644
--- a/src/space.c
+++ b/src/space.c
@@ -2647,8 +2647,20 @@ void space_first_init_parts(struct space *s,
   struct part *restrict p = s->parts;
   struct xpart *restrict xp = s->xparts;
 
+  const struct cosmology *cosmo = s->e->cosmology;
+  const float a_factor_vel = cosmo->a * cosmo->a;
+
+  const struct hydro_props *hydro_props = s->e->hydro_properties;
+  const float u_init = hydro_props->initial_internal_energy;
+  const float u_min = hydro_props->minimal_internal_energy;
+
   for (size_t i = 0; i < nr_parts; ++i) {
 
+    /* Convert velocities to internal units */
+    p[i].v[0] *= a_factor_vel;
+    p[i].v[1] *= a_factor_vel;
+    p[i].v[2] *= a_factor_vel;
+
 #ifdef HYDRO_DIMENSION_2D
     p[i].x[2] = 0.f;
     p[i].v[2] = 0.f;
@@ -2661,6 +2673,10 @@ void space_first_init_parts(struct space *s,
 
     hydro_first_init_part(&p[i], &xp[i]);
 
+    /* Overwrite the internal energy? */
+    if (u_init > 0.f) hydro_set_init_internal_energy(&p[i], u_init);
+    if (u_min > 0.f) hydro_set_init_internal_energy(&p[i], u_min);
+
     /* Also initialise the chemistry */
     chemistry_first_init_part(&p[i], &xp[i], chemistry);
 
@@ -2684,9 +2700,16 @@ void space_first_init_gparts(struct space *s,
 
   const size_t nr_gparts = s->nr_gparts;
   struct gpart *restrict gp = s->gparts;
+  const struct cosmology *cosmo = s->e->cosmology;
+  const float a_factor_vel = cosmo->a * cosmo->a;
 
   for (size_t i = 0; i < nr_gparts; ++i) {
 
+    /* Convert velocities to internal units */
+    gp[i].v_full[0] *= a_factor_vel;
+    gp[i].v_full[1] *= a_factor_vel;
+    gp[i].v_full[2] *= a_factor_vel;
+
 #ifdef HYDRO_DIMENSION_2D
     gp[i].x[2] = 0.f;
     gp[i].v_full[2] = 0.f;
@@ -2715,9 +2738,16 @@ void space_first_init_sparts(struct space *s) {
 
   const size_t nr_sparts = s->nr_sparts;
   struct spart *restrict sp = s->sparts;
+  const struct cosmology *cosmo = s->e->cosmology;
+  const float a_factor_vel = cosmo->a * cosmo->a;
 
   for (size_t i = 0; i < nr_sparts; ++i) {
 
+    /* Convert velocities to internal units */
+    sp[i].v[0] *= a_factor_vel;
+    sp[i].v[1] *= a_factor_vel;
+    sp[i].v[2] *= a_factor_vel;
+
 #ifdef HYDRO_DIMENSION_2D
     sp[i].x[2] = 0.f;
     sp[i].v[2] = 0.f;
@@ -2792,11 +2822,12 @@ void space_init_gparts(struct space *s, int verbose) {
 void space_convert_quantities_mapper(void *restrict map_data, int count,
                                      void *restrict extra_data) {
   struct space *s = (struct space *)extra_data;
+  const struct cosmology *cosmo = s->e->cosmology;
   struct part *restrict parts = (struct part *)map_data;
   const ptrdiff_t index = parts - s->parts;
   struct xpart *restrict xparts = s->xparts + index;
   for (int k = 0; k < count; k++)
-    hydro_convert_quantities(&parts[k], &xparts[k]);
+    hydro_convert_quantities(&parts[k], &xparts[k], cosmo);
 }
 
 /**
@@ -2824,6 +2855,7 @@ void space_convert_quantities(struct space *s, int verbose) {
  *
  * @param s The #space to initialize.
  * @param params The parsed parameter file.
+ * @param cosmo The current cosmological model.
  * @param dim Spatial dimensions of the domain.
  * @param parts Array of Gas particles.
  * @param gparts Array of Gravity particles.
@@ -2832,8 +2864,9 @@ void space_convert_quantities(struct space *s, int verbose) {
  * @param Ngpart The number of Gravity particles in the space.
  * @param Nspart The number of star particles in the space.
  * @param periodic flag whether the domain is periodic or not.
- * @param replicate How many replications along each direction do we want ?
- * @param gravity flag whether we are doing gravity or not.
+ * @param replicate How many replications along each direction do we want?
+ * @param generate_gas_in_ics Are we generating gas particles from the gparts?
+ * @param self_gravity flag whether we are doing gravity or not?
  * @param verbose Print messages to stdout or not.
  * @param dry_run If 1, just initialise stuff, don't do anything with the parts.
  *
@@ -2843,9 +2876,10 @@ void space_convert_quantities(struct space *s, int verbose) {
  * recursively.
  */
 void space_init(struct space *s, const struct swift_params *params,
-                double dim[3], struct part *parts, struct gpart *gparts,
-                struct spart *sparts, size_t Npart, size_t Ngpart,
-                size_t Nspart, int periodic, int replicate, int gravity,
+                const struct cosmology *cosmo, double dim[3],
+                struct part *parts, struct gpart *gparts, struct spart *sparts,
+                size_t Npart, size_t Ngpart, size_t Nspart, int periodic,
+                int replicate, int generate_gas_in_ics, int self_gravity,
                 int verbose, int dry_run) {
 
   /* Clean-up everything */
@@ -2856,7 +2890,7 @@ void space_init(struct space *s, const struct swift_params *params,
   s->dim[1] = dim[1];
   s->dim[2] = dim[2];
   s->periodic = periodic;
-  s->gravity = gravity;
+  s->gravity = self_gravity;
   s->nr_parts = Npart;
   s->size_parts = Npart;
   s->parts = parts;
@@ -2868,6 +2902,19 @@ void space_init(struct space *s, const struct swift_params *params,
   s->sparts = sparts;
   s->nr_queues = 1; /* Temporary value until engine construction */
 
+  /* Are we generating gas from the DM-only ICs? */
+  if (generate_gas_in_ics) {
+    space_generate_gas(s, cosmo, verbose);
+    parts = s->parts;
+    gparts = s->gparts;
+    Npart = s->nr_parts;
+    Ngpart = s->nr_gparts;
+
+#ifdef SWIFT_DEBUG_CHECKS
+    part_verify_links(parts, gparts, sparts, Npart, Ngpart, Nspart, 1);
+#endif
+  }
+
   /* Are we replicating the space ? */
   if (replicate < 1)
     error("Value of 'InitialConditions:replicate' (%d) is too small",
@@ -2880,6 +2927,10 @@ void space_init(struct space *s, const struct swift_params *params,
     Npart = s->nr_parts;
     Ngpart = s->nr_gparts;
     Nspart = s->nr_sparts;
+
+#ifdef SWIFT_DEBUG_CHECKS
+    part_verify_links(parts, gparts, sparts, Npart, Ngpart, Nspart, 1);
+#endif
   }
 
   /* Decide on the minimal top-level cell size */
@@ -2926,8 +2977,8 @@ void space_init(struct space *s, const struct swift_params *params,
   }
 
   /* Apply h scaling */
-  const double scaling =
-      parser_get_opt_param_double(params, "InitialConditions:h_scaling", 1.0);
+  const double scaling = parser_get_opt_param_double(
+      params, "InitialConditions:smoothing_length_scaling", 1.0);
   if (scaling != 1.0 && !dry_run) {
     message("Re-scaling smoothing lengths by a factor %e", scaling);
     for (size_t k = 0; k < Npart; k++) parts[k].h *= scaling;
@@ -3144,6 +3195,97 @@ void space_replicate(struct space *s, int replicate, int verbose) {
 #endif
 }
 
+void space_generate_gas(struct space *s, const struct cosmology *cosmo,
+                        int verbose) {
+
+  if (verbose) message("Generating gas particles from gparts");
+
+  /* Store the current values */
+  const size_t nr_parts = s->nr_parts;
+  const size_t nr_gparts = s->nr_gparts;
+
+  if (nr_parts != 0)
+    error("Generating gas particles from DM but gas already exists!");
+
+  s->size_parts = s->nr_parts = nr_gparts;
+  s->size_gparts = s->nr_gparts = 2 * nr_gparts;
+
+  /* Allocate space for new particles */
+  struct part *parts = NULL;
+  struct gpart *gparts = NULL;
+
+  if (posix_memalign((void **)&parts, part_align,
+                     s->nr_parts * sizeof(struct part)) != 0)
+    error("Failed to allocate new part array.");
+
+  if (posix_memalign((void **)&gparts, gpart_align,
+                     s->nr_gparts * sizeof(struct gpart)) != 0)
+    error("Failed to allocate new gpart array.");
+
+  /* Start by copying the gparts */
+  memcpy(gparts, s->gparts, nr_gparts * sizeof(struct gpart));
+  memcpy(gparts + nr_gparts, s->gparts, nr_gparts * sizeof(struct gpart));
+
+  /* And zero the parts */
+  bzero(parts, s->nr_parts * sizeof(struct part));
+
+  /* Compute some constants */
+  const double mass_ratio = cosmo->Omega_b / cosmo->Omega_m;
+  const double bg_density = cosmo->Omega_m * cosmo->critical_density;
+  const double bg_density_inv = 1. / bg_density;
+
+  /* Update the particle properties */
+  for (size_t i = 0; i < nr_gparts; ++i) {
+
+    struct part *p = &parts[i];
+    struct gpart *gp_gas = &gparts[i];
+    struct gpart *gp_dm = &gparts[nr_gparts + i];
+
+    /* Set the IDs */
+    p->id = gp_gas->id_or_neg_offset * 2 + 1;
+    gp_dm->id_or_neg_offset *= 2;
+
+    /* Set the links correctly */
+    p->gpart = gp_gas;
+    gp_gas->id_or_neg_offset = -i;
+    gp_gas->type = swift_type_gas;
+
+    /* Compute positions shift */
+    const double d = cbrt(gp_dm->mass * bg_density_inv);
+    const double shift_dm = d * mass_ratio;
+    const double shift_gas = d * (1. - mass_ratio);
+
+    /* Set the masses */
+    gp_dm->mass *= (1. - mass_ratio);
+    gp_gas->mass *= mass_ratio;
+    hydro_set_mass(p, gp_gas->mass);
+
+    /* Set the new positions */
+    gp_dm->x[0] += shift_dm;
+    gp_dm->x[1] += shift_dm;
+    gp_dm->x[2] += shift_dm;
+    gp_gas->x[0] += shift_gas;
+    gp_gas->x[1] += shift_gas;
+    gp_gas->x[2] += shift_gas;
+    p->x[0] = gp_gas->x[0];
+    p->x[1] = gp_gas->x[1];
+    p->x[2] = gp_gas->x[2];
+
+    /* Also copy the velocities */
+    p->v[0] = gp_gas->v_full[0];
+    p->v[1] = gp_gas->v_full[1];
+    p->v[2] = gp_gas->v_full[2];
+
+    /* Set the smoothing length to the mean inter-particle separation */
+    p->h = d;
+  }
+
+  /* Replace the content of the space */
+  free(s->gparts);
+  s->parts = parts;
+  s->gparts = gparts;
+}
+
 /**
  * @brief Cleans-up all the cell links in the space
  *
diff --git a/src/space.h b/src/space.h
index 11cbaabdc9fc3ae17024c042ae868d464954d501..76ff2ea9908195d618663eb1874eb48bec463bb7 100644
--- a/src/space.h
+++ b/src/space.h
@@ -38,6 +38,7 @@
 
 /* Avoid cyclic inclusions */
 struct cell;
+struct cosmology;
 
 /* Some constants. */
 #define space_cellallocchunk 1000
@@ -182,9 +183,10 @@ void space_getcells(struct space *s, int nr_cells, struct cell **cells);
 int space_getsid(struct space *s, struct cell **ci, struct cell **cj,
                  double *shift);
 void space_init(struct space *s, const struct swift_params *params,
-                double dim[3], struct part *parts, struct gpart *gparts,
-                struct spart *sparts, size_t Npart, size_t Ngpart,
-                size_t Nspart, int periodic, int replicate, int gravity,
+                const struct cosmology *cosmo, double dim[3],
+                struct part *parts, struct gpart *gparts, struct spart *sparts,
+                size_t Npart, size_t Ngpart, size_t Nspart, int periodic,
+                int replicate, int generate_gas_in_ics, int gravity,
                 int verbose, int dry_run);
 void space_sanitize(struct space *s);
 void space_map_cells_pre(struct space *s, int full,
@@ -239,6 +241,8 @@ void space_check_top_multipoles_drift_point(struct space *s,
                                             integertime_t ti_drift);
 void space_check_timesteps(struct space *s);
 void space_replicate(struct space *s, int replicate, int verbose);
+void space_generate_gas(struct space *s, const struct cosmology *cosmo,
+                        int verbose);
 void space_reset_task_counters(struct space *s);
 void space_clean(struct space *s);
 void space_free_cells(struct space *s);
diff --git a/src/stars/Default/star_io.h b/src/stars/Default/star_io.h
index 96bbdce6d83dc241d05e7dd1754f476dc0b8e5f9..c3dc31096383533e1e15fa65615d2c9aac0f43e3 100644
--- a/src/stars/Default/star_io.h
+++ b/src/stars/Default/star_io.h
@@ -52,7 +52,7 @@ void star_read_particles(struct spart* sparts, struct io_props* list,
  * @param list The list of i/o properties to write.
  * @param num_fields The number of i/o fields to write.
  */
-void star_write_particles(struct spart* sparts, struct io_props* list,
+void star_write_particles(const struct spart* sparts, struct io_props* list,
                           int* num_fields) {
 
   /* Say how much we want to read */
diff --git a/src/units.c b/src/units.c
index 5c50bb063b9411f47357407678458e6094f69e2b..4b632e735b7c6e1c12afe8aebc16aa44abc5b597 100644
--- a/src/units.c
+++ b/src/units.c
@@ -220,6 +220,11 @@ void units_get_base_unit_exponants_array(float baseUnitsExp[5],
       baseUnitsExp[UNIT_TIME] = -2.f;
       break;
 
+    case UNIT_CONV_POTENTIAL:
+      baseUnitsExp[UNIT_LENGTH] = 2.f;
+      baseUnitsExp[UNIT_TIME] = -2.f;
+      break;
+
     case UNIT_CONV_FORCE:
       baseUnitsExp[UNIT_MASS] = 1.f;
       baseUnitsExp[UNIT_LENGTH] = 1.f;
diff --git a/src/units.h b/src/units.h
index 5ac70a909a77146ba5f7a441d7747acfc80c3dfa..87c44cc6eb4934980027a60642dd135f03029f7c 100644
--- a/src/units.h
+++ b/src/units.h
@@ -73,6 +73,7 @@ enum unit_conversion_factor {
   UNIT_CONV_DENSITY,
   UNIT_CONV_SPEED,
   UNIT_CONV_ACCELERATION,
+  UNIT_CONV_POTENTIAL,
   UNIT_CONV_FORCE,
   UNIT_CONV_ENERGY,
   UNIT_CONV_ENERGY_PER_UNIT_MASS,
diff --git a/tests/fft_params.yml b/tests/fft_params.yml
index 05d6d8f0b0578d11645fc1d78c1a6322160ae87a..6938e3658148874e58f50ab768a5e1fbc41d9573 100644
--- a/tests/fft_params.yml
+++ b/tests/fft_params.yml
@@ -3,8 +3,9 @@ Scheduler:
   
 # Parameters for the self-gravity scheme
 Gravity:
-  eta:                   0.025    # Constant dimensionless multiplier for time integration. 
-  theta:                 0.7      # Opening angle (Multipole acceptance criterion)
-  epsilon:               0.00001  # Softening length (in internal units).
-  a_smooth:              0.
-  r_cut:                 0.
+  eta:                    0.025      # Constant dimensionless multiplier for time integration.
+  theta:                  0.7        # Opening angle (Multipole acceptance criterion)
+  comoving_softening:     0.00001    # Comoving softening length (in internal units).
+  max_physical_softening: 0.00001    # Physical softening length (in internal units).
+  a_smooth:               0.
+  r_cut:                  0.
diff --git a/tests/testFFT.c b/tests/testFFT.c
index ba737935afc4568a1509d2c43a3534b60a6ef867..7b67181ebd3e29bffbf564d00f702e6c15669fab 100644
--- a/tests/testFFT.c
+++ b/tests/testFFT.c
@@ -57,15 +57,18 @@ int main() {
   struct swift_params *params = malloc(sizeof(struct swift_params));
   parser_read_file("fft_params.yml", params);
 
+  struct cosmology cosmo;
+  cosmology_init_no_cosmo(&cosmo);
+
   /* Initialise the gravity properties */
   struct gravity_props gravity_properties;
-  gravity_props_init(&gravity_properties, params);
+  gravity_props_init(&gravity_properties, params, &cosmo);
 
   /* Build the infrastructure */
   struct space space;
   double dim[3] = {1., 1., 1.};
-  space_init(&space, params, dim, NULL, gparts, NULL, 0, nr_gparts, 0, 1, 1, 1,
-             0, 0);
+  space_init(&space, params, &cosmo, dim, NULL, gparts, NULL, 0, nr_gparts, 0,
+             1, 1, 0, 1, 0, 0);
 
   struct engine engine;
   engine.s = &space;
diff --git a/tests/testPotentialPair.c b/tests/testPotentialPair.c
index 5fbfb04ecd0b4a8c05c07d622dd77bd38af970ae..53fc54ccdd63a9a9150b6701c1a76ac20af91d4c 100644
--- a/tests/testPotentialPair.c
+++ b/tests/testPotentialPair.c
@@ -106,6 +106,7 @@ int main() {
   props.a_smooth = 1.25;
   props.r_cut_min = 0.;
   props.theta_crit2 = 0.;
+  props.epsilon_cur = eps;
   e.gravity_properties = &props;
 
   struct runner r;
@@ -178,7 +179,6 @@ int main() {
     gp->x[1] = 0.5;
     gp->x[2] = 0.5;
     gp->mass = 0.;
-    gp->epsilon = eps;
     gp->time_bin = 1;
     gp->type = swift_type_dark_matter;
     gp->id_or_neg_offset = n + 1;
@@ -196,7 +196,6 @@ int main() {
   ci.gparts[0].x[1] = 0.5;
   ci.gparts[0].x[2] = 0.5;
   ci.gparts[0].mass = 1.;
-  ci.gparts[0].epsilon = eps;
   ci.gparts[0].time_bin = 1;
   ci.gparts[0].type = swift_type_dark_matter;
   ci.gparts[0].id_or_neg_offset = 1;
@@ -211,11 +210,12 @@ int main() {
   for (int n = 0; n < num_tests; ++n) {
     const struct gpart *gp = &cj.gparts[n];
     const struct gpart *gp2 = &ci.gparts[0];
+    const double epsilon = gravity_get_softening(gp, &props);
 
     double pot_true =
-        potential(ci.gparts[0].mass, gp->x[0] - gp2->x[0], gp->epsilon, rlr);
+        potential(ci.gparts[0].mass, gp->x[0] - gp2->x[0], epsilon, rlr);
     double acc_true =
-        acceleration(ci.gparts[0].mass, gp->x[0] - gp2->x[0], gp->epsilon, rlr);
+        acceleration(ci.gparts[0].mass, gp->x[0] - gp2->x[0], epsilon, rlr);
 
     message("x=%e f=%e f_true=%e pot=%e pot_true=%e", gp->x[0] - gp2->x[0],
             gp->a_grav[0], acc_true, gp->potential, pot_true);
@@ -252,12 +252,12 @@ int main() {
   for (int n = 0; n < num_tests; ++n) {
     const struct gpart *gp = &cj.gparts[n];
     const struct gravity_tensors *mpole = ci.multipole;
+    const double epsilon = gravity_get_softening(gp, &props);
 
     double pot_true = potential(mpole->m_pole.M_000, gp->x[0] - mpole->CoM[0],
-                                gp->epsilon, rlr * FLT_MAX);
-    double acc_true =
-        acceleration(mpole->m_pole.M_000, gp->x[0] - mpole->CoM[0], gp->epsilon,
-                     rlr * FLT_MAX);
+                                epsilon, rlr * FLT_MAX);
+    double acc_true = acceleration(
+        mpole->m_pole.M_000, gp->x[0] - mpole->CoM[0], epsilon, rlr * FLT_MAX);
 
     message("x=%e f=%e f_true=%e pot=%e pot_true=%e", gp->x[0] - mpole->CoM[0],
             gp->a_grav[0], acc_true, gp->potential, pot_true);
@@ -304,7 +304,6 @@ int main() {
 
     ci.gparts[n].mass = 1. / 8.;
 
-    ci.gparts[n].epsilon = eps;
     ci.gparts[n].time_bin = 1;
     ci.gparts[n].type = swift_type_dark_matter;
     ci.gparts[n].id_or_neg_offset = 1;
@@ -333,18 +332,19 @@ int main() {
 
     for (int i = 0; i < 8; ++i) {
       const struct gpart *gp2 = &ci.gparts[i];
+      const double epsilon = gravity_get_softening(gp, &props);
 
       const double dx[3] = {gp2->x[0] - gp->x[0], gp2->x[1] - gp->x[1],
                             gp2->x[2] - gp->x[2]};
       const double d = sqrt(dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]);
 
-      pot_true += potential(gp2->mass, d, gp->epsilon, rlr * FLT_MAX);
+      pot_true += potential(gp2->mass, d, epsilon, rlr * FLT_MAX);
       acc_true[0] -=
-          acceleration(gp2->mass, d, gp->epsilon, rlr * FLT_MAX) * dx[0] / d;
+          acceleration(gp2->mass, d, epsilon, rlr * FLT_MAX) * dx[0] / d;
       acc_true[1] -=
-          acceleration(gp2->mass, d, gp->epsilon, rlr * FLT_MAX) * dx[1] / d;
+          acceleration(gp2->mass, d, epsilon, rlr * FLT_MAX) * dx[1] / d;
       acc_true[2] -=
-          acceleration(gp2->mass, d, gp->epsilon, rlr * FLT_MAX) * dx[2] / d;
+          acceleration(gp2->mass, d, epsilon, rlr * FLT_MAX) * dx[2] / d;
     }
 
     message("x=%e f=%e f_true=%e pot=%e pot_true=%e %e %e",
diff --git a/tests/testPotentialSelf.c b/tests/testPotentialSelf.c
index 33fe574e34bcc49ff8bac6f19f22b55fda19f186..246139ba243a37dbc5f6cafbc488cb1bf6cdd8eb 100644
--- a/tests/testPotentialSelf.c
+++ b/tests/testPotentialSelf.c
@@ -103,6 +103,7 @@ int main() {
 
   struct gravity_props props;
   props.a_smooth = 1.25;
+  props.epsilon_cur = eps;
   e.gravity_properties = &props;
 
   struct runner r;
@@ -139,7 +140,6 @@ int main() {
   c.gparts[0].x[1] = 0.5;
   c.gparts[0].x[2] = 0.5;
   c.gparts[0].mass = 1.;
-  c.gparts[0].epsilon = eps;
   c.gparts[0].time_bin = 1;
   c.gparts[0].type = swift_type_dark_matter;
   c.gparts[0].id_or_neg_offset = 1;
@@ -156,7 +156,6 @@ int main() {
     gp->x[1] = 0.5;
     gp->x[2] = 0.5;
     gp->mass = 0.;
-    gp->epsilon = eps;
     gp->time_bin = 1;
     gp->type = swift_type_dark_matter;
     gp->id_or_neg_offset = n + 1;
@@ -172,9 +171,10 @@ int main() {
   for (int n = 1; n < num_tests + 1; ++n) {
     const struct gpart *gp = &c.gparts[n];
 
-    double pot_true = potential(c.gparts[0].mass, gp->x[0], gp->epsilon, rlr);
-    double acc_true =
-        acceleration(c.gparts[0].mass, gp->x[0], gp->epsilon, rlr);
+    const double epsilon = gravity_get_softening(gp, &props);
+
+    double pot_true = potential(c.gparts[0].mass, gp->x[0], epsilon, rlr);
+    double acc_true = acceleration(c.gparts[0].mass, gp->x[0], epsilon, rlr);
 
     // message("x=%e f=%e f_true=%e", gp->x[0], gp->a_grav[0], acc_true);
 
diff --git a/tests/testReading.c b/tests/testReading.c
index f5e2757c2fe3bd507e877f134e8c768aba0ae645..ca1e0ef69078c5e384a9cd4eab1098923ce9f279 100644
--- a/tests/testReading.c
+++ b/tests/testReading.c
@@ -48,7 +48,8 @@ int main() {
 
   /* Read data */
   read_ic_single("input.hdf5", &us, dim, &parts, &gparts, &sparts, &Ngas,
-                 &Ngpart, &Nspart, &periodic, &flag_entropy_ICs, 1, 1, 0, 1, 0);
+                 &Ngpart, &Nspart, &periodic, &flag_entropy_ICs, 1, 1, 0, 0, 1.,
+                 1, 0);
 
   /* Check global properties read are correct */
   assert(dim[0] == boxSize);