diff --git a/examples/main.c b/examples/main.c
index e795e210ca84b87410e1503c063d30c9a114ae83..56664f8dde5c6bb2667bfed6181e480b52977bd2 100644
--- a/examples/main.c
+++ b/examples/main.c
@@ -745,12 +745,6 @@ int main(int argc, char *argv[]) {
     const int generate_gas_in_ics = parser_get_opt_param_int(
         params, "InitialConditions:generate_gas_in_ics", 0);
 
-    /* Some checks that we are not doing something stupid */
-    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.");
-
     /* Initialise the cosmology */
     if (with_cosmology)
       cosmology_init(params, &us, &prog_const, &cosmo);
@@ -804,12 +798,6 @@ int main(int argc, char *argv[]) {
     } else
       bzero(&black_holes_properties, sizeof(struct black_holes_props));
 
-    /* Initialise the gravity properties */
-    bzero(&gravity_properties, sizeof(struct gravity_props));
-    if (with_self_gravity)
-      gravity_props_init(&gravity_properties, params, &prog_const, &cosmo,
-                         with_cosmology, periodic);
-
       /* Initialise the cooling function properties */
 #ifdef COOLING_NONE
     if (with_cooling || with_temperature) {
@@ -867,24 +855,26 @@ int main(int argc, char *argv[]) {
 #if defined(HAVE_HDF5)
 #if defined(WITH_MPI)
 #if defined(HAVE_PARALLEL_HDF5)
-    read_ic_parallel(
-        ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, &Ngas, &Ngpart,
-        &Ngpart_background, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro,
-        (with_external_gravity || with_self_gravity), with_stars,
-        with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a, myrank,
-        nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads, dry_run);
+    read_ic_parallel(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts,
+                     &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart,
+                     &flag_entropy_ICs, &high_res_DM_mass, with_hydro,
+                     (with_external_gravity || with_self_gravity), with_stars,
+                     with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h,
+                     cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL,
+                     nr_threads, dry_run);
 #else
-    read_ic_serial(
-        ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, &Ngas, &Ngpart,
-        &Ngpart_background, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro,
-        (with_external_gravity || with_self_gravity), with_stars,
-        with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a, myrank,
-        nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads, dry_run);
+    read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts,
+                   &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart,
+                   &flag_entropy_ICs, &high_res_DM_mass, with_hydro,
+                   (with_external_gravity || with_self_gravity), with_stars,
+                   with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h,
+                   cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL,
+                   nr_threads, dry_run);
 #endif
 #else
     read_ic_single(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts,
                    &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart,
-                   &flag_entropy_ICs, with_hydro,
+                   &flag_entropy_ICs, &high_res_DM_mass, with_hydro,
                    (with_external_gravity || with_self_gravity), with_stars,
                    with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h,
                    cosmo.a, nr_threads, dry_run);
@@ -897,6 +887,12 @@ int main(int argc, char *argv[]) {
       fflush(stdout);
     }
 
+    /* Some checks that we are not doing something stupid */
+    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.");
+
 #ifdef SWIFT_DEBUG_CHECKS
     /* Check once and for all that we don't have unwanted links */
     if (!with_stars && !dry_run) {
@@ -970,6 +966,12 @@ int main(int argc, char *argv[]) {
       fflush(stdout);
     }
 
+    /* Initialise the gravity properties */
+    bzero(&gravity_properties, sizeof(struct gravity_props));
+    if (with_self_gravity)
+      gravity_props_init(&gravity_properties, params, &cosmo, high_res_DM_mass,
+                         with_cosmology, periodic);
+
     /* Initialise the external potential properties */
     bzero(&potential, sizeof(struct external_potential));
     if (with_external_gravity)
diff --git a/src/cell.c b/src/cell.c
index 80c5798c2b5a13bcb3c283eb16fa58d537d63bf6..dfae80d5a2cf4a46fe8bc42052220be559efe31b 100644
--- a/src/cell.c
+++ b/src/cell.c
@@ -2175,8 +2175,11 @@ void cell_reset_task_counters(struct cell *c) {
  *
  * @param c The #cell.
  * @param ti_current The current integer time.
+ * @param grav_props The properties of the gravity scheme.
  */
-void cell_make_multipoles(struct cell *c, integertime_t ti_current) {
+void cell_make_multipoles(struct cell *c, integertime_t ti_current,
+                          const struct gravity_props *const grav_props) {
+
   /* Reset everything */
   gravity_reset(c->grav.multipole);
 
@@ -2184,7 +2187,7 @@ void cell_make_multipoles(struct cell *c, integertime_t ti_current) {
     /* Start by recursing */
     for (int k = 0; k < 8; ++k) {
       if (c->progeny[k] != NULL)
-        cell_make_multipoles(c->progeny[k], ti_current);
+        cell_make_multipoles(c->progeny[k], ti_current, grav_props);
     }
 
     /* Compute CoM of all progenies */
@@ -2245,7 +2248,7 @@ void cell_make_multipoles(struct cell *c, integertime_t ti_current) {
 
   } else {
     if (c->grav.count > 0) {
-      gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count);
+      gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count, grav_props);
       const double dx =
           c->grav.multipole->CoM[0] > c->loc[0] + c->width[0] * 0.5
               ? c->grav.multipole->CoM[0] - c->loc[0]
@@ -2322,7 +2325,9 @@ void cell_check_foreign_multipole(const struct cell *c) {
  *
  * @param c Cell to act upon
  */
-void cell_check_multipole(struct cell *c) {
+void cell_check_multipole(struct cell *c,
+                          const struct gravity_props *const grav_props) {
+
 #ifdef SWIFT_DEBUG_CHECKS
   struct gravity_tensors ma;
   const double tolerance = 1e-3; /* Relative */
@@ -2330,11 +2335,12 @@ void cell_check_multipole(struct cell *c) {
   /* First recurse */
   if (c->split)
     for (int k = 0; k < 8; k++)
-      if (c->progeny[k] != NULL) cell_check_multipole(c->progeny[k]);
+      if (c->progeny[k] != NULL)
+        cell_check_multipole(c->progeny[k], grav_props);
 
   if (c->grav.count > 0) {
     /* Brute-force calculation */
-    gravity_P2M(&ma, c->grav.parts, c->grav.count);
+    gravity_P2M(&ma, c->grav.parts, c->grav.count, grav_props);
 
     /* Now  compare the multipole expansion */
     if (!gravity_multipole_equal(&ma, c->grav.multipole, tolerance)) {
diff --git a/src/cell.h b/src/cell.h
index 9c9e2e64f85305e37fe912e0436e5dbde333f6d8..c6d32c8219b31cadfd20a7110226aa7e15badcf9 100644
--- a/src/cell.h
+++ b/src/cell.h
@@ -852,8 +852,10 @@ int cell_link_foreign_gparts(struct cell *c, struct gpart *gparts);
 int cell_count_parts_for_tasks(const struct cell *c);
 int cell_count_gparts_for_tasks(const struct cell *c);
 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 cell_make_multipoles(struct cell *c, integertime_t ti_current,
+                          const struct gravity_props *const grav_props);
+void cell_check_multipole(struct cell *c,
+                          const struct gravity_props *const grav_props);
 void cell_check_foreign_multipole(const struct cell *c);
 void cell_clean(struct cell *c);
 void cell_check_part_drift_point(struct cell *c, void *data);
diff --git a/src/engine.c b/src/engine.c
index 8f14cfd0088cff9d47bee38662a5aeff357dd8e0..4afbeb9b2f891d339d1c4d96d072e0b2c5a525ec 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -4198,7 +4198,7 @@ void engine_do_reconstruct_multipoles_mapper(void *map_data, int num_elements,
     if (c != NULL && c->nodeID == e->nodeID) {
 
       /* Construct the multipoles in this cell hierarchy */
-      cell_make_multipoles(c, e->ti_current);
+      cell_make_multipoles(c, e->ti_current, e->gravity_properties);
     }
   }
 }
diff --git a/src/gravity/MultiSoftening/gravity.h b/src/gravity/MultiSoftening/gravity.h
index 6d1270c952100f3a25202fcdb22be09f9acaa8d9..aae8c9ee670019af3bf7f82cad0f75876810df30 100644
--- a/src/gravity/MultiSoftening/gravity.h
+++ b/src/gravity/MultiSoftening/gravity.h
@@ -48,7 +48,10 @@ __attribute__((always_inline)) INLINE static float gravity_get_mass(
 __attribute__((always_inline)) INLINE static float gravity_get_softening(
     const struct gpart* gp, const struct gravity_props* restrict grav_props) {
 
-  return grav_props->epsilon_cur;
+  if (gp->type == swift_type_dark_matter_background)
+    return grav_props->epsilon_background_fac * cbrtf(gp->mass);
+  else
+    return grav_props->epsilon_cur;
 }
 
 /**
diff --git a/src/gravity/MultiSoftening/gravity_io.h b/src/gravity/MultiSoftening/gravity_io.h
index 2e443e8fdc2479f3f2feff30281dccad9a7b6519..11c970aa2973996916060bc38ffcccd8a3fe2fcc 100644
--- a/src/gravity/MultiSoftening/gravity_io.h
+++ b/src/gravity/MultiSoftening/gravity_io.h
@@ -67,6 +67,11 @@ INLINE static void convert_gpart_vel(const struct engine* e,
   ret[2] *= cosmo->a_inv;
 }
 
+INLINE static void convert_gpart_soft(const struct engine* e,
+                                      const struct gpart* gp, float* ret) {
+  ret[0] = gravity_get_softening(gp, e->gravity_properties);
+}
+
 /**
  * @brief Specifies which g-particle fields to read from a dataset
  *
@@ -104,7 +109,7 @@ INLINE static void darkmatter_write_particles(const struct gpart* gparts,
                                               int* num_fields) {
 
   /* Say how much we want to write */
-  *num_fields = 5;
+  *num_fields = 6;
 
   /* List what we want to write */
   list[0] = io_make_output_field_convert_gpart(
@@ -117,6 +122,8 @@ INLINE static void darkmatter_write_particles(const struct gpart* gparts,
                                  UNIT_CONV_NO_UNITS, gparts, id_or_neg_offset);
   list[4] = io_make_output_field("GroupIDs", INT, 1, UNIT_CONV_NO_UNITS, gparts,
                                  group_id);
+  list[5] = io_make_output_field_convert_gpart(
+      "Softenings", FLOAT, 1, UNIT_CONV_LENGTH, gparts, convert_gpart_soft);
 }
 
 #endif /* SWIFT_DEFAULT_GRAVITY_IO_H */
diff --git a/src/gravity/MultiSoftening/gravity_part.h b/src/gravity/MultiSoftening/gravity_part.h
index 2c16a34a11d3a7674f5a6c122da780aeaff4a9dc..276c7f5176002b8a2e51768c47c6c91d8187fe51 100644
--- a/src/gravity/MultiSoftening/gravity_part.h
+++ b/src/gravity/MultiSoftening/gravity_part.h
@@ -44,8 +44,7 @@ struct gpart {
   /*! Type of the #gpart (DM, gas, star, ...) */
   enum part_type type;
 
-  /* Particle group ID and size in the FOF. */
-  size_t group_id, group_size;
+  unsigned char group_id, group_size;
 
 #ifdef SWIFT_DEBUG_CHECKS
 
diff --git a/src/gravity_properties.c b/src/gravity_properties.c
index 8d3dfe9c4683842b905959ab3c688cc1f23309e9..c1807630dda831e45b63bfdea73a3a66750bed2f 100644
--- a/src/gravity_properties.c
+++ b/src/gravity_properties.c
@@ -40,8 +40,10 @@
 
 void gravity_props_init(struct gravity_props *p, struct swift_params *params,
                         const struct phys_const *phys_const,
-                        const struct cosmology *cosmo, int with_cosmology,
-                        int periodic) {
+                        const struct cosmology *cosmo, 
+                        const double high_res_DM_mass, 
+                        const int with_cosmology,
+                        const int periodic) {
 
   /* Tree updates */
   p->rebuild_frequency =
@@ -89,10 +91,39 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params,
 
   /* Softening parameters */
   if (with_cosmology) {
-    p->epsilon_comoving =
-        parser_get_param_double(params, "Gravity:comoving_softening");
+
+    /* Check that a mass for the high res. particles was indeed read. */
+    if (high_res_DM_mass == -1.)
+      error("DM particle mass for type 1 has not been read from the ICs.");
+
+    const double ratio =
+        parser_get_param_double(params, "Gravity:softening_ratio");
+
+    /* Compute the comoving softening length as a fraction of the mean
+     * inter-particle density of the high-res. DM particles
+     * and assuming the mean density of the Universe is used in the simulation.
+     */
+    const double mean_matter_density =
+        cosmo->Omega_m * cosmo->critical_density_0;
+
+    p->epsilon_comoving = ratio * cbrt(high_res_DM_mass / mean_matter_density);
+
+    /* Maximal physical softening taken straight from the parameter file */
     p->epsilon_max_physical =
         parser_get_param_double(params, "Gravity:max_physical_softening");
+
+    /* Compute the comoving softening length for background particles.
+     * Since they have variable masses the mass factor will be multiplied
+     * in later on.
+     * Note that we already multiply in the conversion from Plummer -> real
+     * softening length */
+    const double ratio_background =
+        parser_get_param_double(params, "Gravity:softening_ratio_background");
+
+    p->epsilon_background_fac = kernel_gravity_softening_plummer_equivalent *
+                                ratio_background *
+                                cbrt(1. / mean_matter_density);
+
   } else {
     p->epsilon_max_physical =
         parser_get_param_double(params, "Gravity:max_physical_softening");
@@ -109,7 +140,7 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params,
 void gravity_props_update(struct gravity_props *p,
                           const struct cosmology *cosmo) {
 
-  /* Current softening lengths */
+  /* Current softening length for the high-resolution particles. */
   double softening;
   if (p->epsilon_comoving * cosmo->a > p->epsilon_max_physical)
     softening = p->epsilon_max_physical / cosmo->a;
@@ -121,11 +152,6 @@ void gravity_props_update(struct gravity_props *p,
 
   /* 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) {
@@ -143,14 +169,14 @@ void gravity_props_print(const struct gravity_props *p) {
           kernel_gravity_softening_name);
 
   message(
-      "Self-gravity comoving softening:    epsilon=%.4f (Plummer equivalent: "
-      "%.4f)",
+      "Self-gravity comoving softening: epsilon=%.6f (Plummer equivalent: "
+      "%.6f)",
       p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent,
       p->epsilon_comoving);
 
   message(
-      "Self-gravity maximal physical softening:    epsilon=%.4f (Plummer "
-      "equivalent: %.4f)",
+      "Self-gravity maximal physical softening:    epsilon=%.6f (Plummer "
+      "equivalent: %.6f)",
       p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent,
       p->epsilon_max_physical);
 
@@ -171,33 +197,38 @@ void gravity_props_print(const struct gravity_props *p) {
 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_s(h_grpgrav, "Softening style",
-                       kernel_gravity_softening_name);
-  io_write_attribute_f(
-      h_grpgrav, "Comoving softening length [internal units]",
-      p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent);
-  io_write_attribute_f(
-      h_grpgrav,
-      "Comoving Softening length (Plummer equivalent)  [internal units]",
-      p->epsilon_comoving);
-  io_write_attribute_f(
-      h_grpgrav, "Maximal physical softening length  [internal units]",
-      p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent);
-  io_write_attribute_f(h_grpgrav,
-                       "Maximal physical softening length (Plummer equivalent) "
-                       " [internal units]",
-                       p->epsilon_max_physical);
-  io_write_attribute_f(h_grpgrav, "Opening angle", p->theta_crit);
-  io_write_attribute_s(h_grpgrav, "Scheme", GRAVITY_IMPLEMENTATION);
-  io_write_attribute_i(h_grpgrav, "MM order", SELF_GRAVITY_MULTIPOLE_ORDER);
-  io_write_attribute_f(h_grpgrav, "Mesh a_smooth", p->a_smooth);
-  io_write_attribute_f(h_grpgrav, "Mesh r_cut_max ratio", p->r_cut_max_ratio);
-  io_write_attribute_f(h_grpgrav, "Mesh r_cut_min ratio", p->r_cut_min_ratio);
-  io_write_attribute_f(h_grpgrav, "Tree update frequency",
-                       p->rebuild_frequency);
-  io_write_attribute_s(h_grpgrav, "Mesh truncation function",
-                       kernel_long_gravity_truncation_name);
+  /* io_write_attribute_f(h_grpgrav, "Time integration eta", p->eta); */
+  /* io_write_attribute_s(h_grpgrav, "Softening style", */
+  /*                      kernel_gravity_softening_name); */
+  /* io_write_attribute_f( */
+  /*     h_grpgrav, "Comoving softening length [internal units]", */
+  /*     p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent); */
+  /* io_write_attribute_f( */
+  /*     h_grpgrav, */
+  /*     "Comoving Softening length (Plummer equivalent)  [internal units]", */
+  /*     p->epsilon_comoving); */
+  /* io_write_attribute_f( */
+  /*     h_grpgrav, "Maximal physical softening length  [internal units]", */
+  /*     p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent);
+   */
+  /* io_write_attribute_f(h_grpgrav, */
+  /*                      "Maximal physical softening length (Plummer
+   * equivalent) " */
+  /*                      " [internal units]", */
+  /*                      p->epsilon_max_physical); */
+  /* io_write_attribute_f(h_grpgrav, "Opening angle", p->theta_crit); */
+  /* io_write_attribute_s(h_grpgrav, "Scheme", GRAVITY_IMPLEMENTATION); */
+  /* io_write_attribute_i(h_grpgrav, "MM order", SELF_GRAVITY_MULTIPOLE_ORDER);
+   */
+  /* io_write_attribute_f(h_grpgrav, "Mesh a_smooth", p->a_smooth); */
+  /* io_write_attribute_f(h_grpgrav, "Mesh r_cut_max ratio",
+   * p->r_cut_max_ratio); */
+  /* io_write_attribute_f(h_grpgrav, "Mesh r_cut_min ratio",
+   * p->r_cut_min_ratio); */
+  /* io_write_attribute_f(h_grpgrav, "Tree update frequency", */
+  /*                      p->rebuild_frequency); */
+  /* io_write_attribute_s(h_grpgrav, "Mesh truncation function", */
+  /*                      kernel_long_gravity_truncation_name); */
 }
 #endif
 
diff --git a/src/gravity_properties.h b/src/gravity_properties.h
index 79d72765e767351e29ffa30b615c1f7f4f98022c..81ec91ee1e0813b8779caccd540f87088ada8258 100644
--- a/src/gravity_properties.h
+++ b/src/gravity_properties.h
@@ -40,25 +40,18 @@ struct swift_params;
  */
 struct gravity_props {
 
-  /*! Frequency of tree-rebuild in units of #gpart updates. */
-  float rebuild_frequency;
+  /* -------------- Softening for the regular DM and baryons ----------- */
 
-  /*! Periodic long-range mesh side-length */
-  int mesh_size;
+  /*! Softening length for high-res. particles at the current redshift.  */
+  float epsilon_cur;
 
-  /*! Mesh smoothing scale in units of top-level cell size */
-  float a_smooth;
+  /* -------------- Softening for the background DM -------------------- */
 
-  /*! Distance below which the truncated mesh force is Newtonian in units of
-   * a_smooth */
-  float r_cut_min_ratio;
+  /*! Conversion factor from cbrt of particle mass to softening assuming
+   * a constant fraction of the mean inter-particle separation at that mass. */
+  float epsilon_background_fac;
 
-  /*! Distance above which the truncated mesh force is negligible in units of
-   * a_smooth */
-  float r_cut_max_ratio;
-
-  /*! Time integration dimensionless multiplier */
-  float eta;
+  /* -------------- Properties of the FFM gravity ---------------------- */
 
   /*! Tree opening angle (Multipole acceptance criterion) */
   double theta_crit;
@@ -69,23 +62,44 @@ struct gravity_props {
   /*! Inverse of opening angle */
   double theta_crit_inv;
 
-  /*! Comoving softening */
-  double epsilon_comoving;
+  /* ------------- Properties of the softened gravity ------------------ */
 
-  /*! Maxium physical softening */
-  double epsilon_max_physical;
+  /*! Fraction of the mean inter particle separation corresponding to the
+   * co-moving softening length of the low-res. particles (DM + baryons) */
+  float mean_inter_particle_fraction_high_res;
 
-  /*! Current softening length */
-  float epsilon_cur;
+  /*! Co-moving softening length for for high-res. particles (DM + baryons)
+   * assuming a constant fraction of the mean inter-particle separation
+   * and a constant particle mass */
+  float epsilon_comoving;
 
-  /*! Square of current softening length */
-  float epsilon_cur2;
+  /*! Maximal softening length in physical coordinates for the high-res.
+   * particles (DM + baryons) */
+  float epsilon_max_physical;
 
-  /*! Inverse of current softening length */
-  float epsilon_cur_inv;
+  /* ------------- Properties of the time integration  ----------------- */
 
-  /*! Cube of the inverse of current oftening length */
-  float epsilon_cur_inv3;
+  /*! Frequency of tree-rebuild in units of #gpart updates. */
+  float rebuild_frequency;
+
+  /*! Time integration dimensionless multiplier */
+  float eta;
+
+  /* ------------- Properties of the mesh-based gravity ---------------- */
+
+  /*! Periodic long-range mesh side-length */
+  int mesh_size;
+
+  /*! Mesh smoothing scale in units of top-level cell size */
+  float a_smooth;
+
+  /*! Distance below which the truncated mesh force is Newtonian in units of
+   * a_smooth */
+  float r_cut_min_ratio;
+
+  /*! Distance above which the truncated mesh force is negligible in units of
+   * a_smooth */
+  float r_cut_max_ratio;
 
   /*! Gravitational constant (in internal units, copied from the physical
    * constants) */
@@ -94,9 +108,10 @@ struct gravity_props {
 
 void gravity_props_print(const struct gravity_props *p);
 void gravity_props_init(struct gravity_props *p, struct swift_params *params,
-                        const struct phys_const *phys_const,
-                        const struct cosmology *cosmo, int with_cosmology,
-                        int periodic);
+const struct phys_const *phys_const,
+                        const struct cosmology *cosmo,
+                        const double high_res_DM_mass, const int with_cosmology,
+                        const int periodic);
 void gravity_props_update(struct gravity_props *p,
                           const struct cosmology *cosmo);
 
diff --git a/src/hydro_properties.c b/src/hydro_properties.c
index 0082546ce14030a37fa63d87ea88bc99153b8213..d823675579a5e13e5f80f2c5030a755d6e96267a 100644
--- a/src/hydro_properties.c
+++ b/src/hydro_properties.c
@@ -338,7 +338,8 @@ void hydro_props_update(struct hydro_props *p, const struct gravity_props *gp,
    * is a fixed fraction of the radius at which the softened forces
    * recover a Newtonian behaviour (i.e. 2.8 * Plummer equivalent softening
    * in the case of a cubic spline kernel). */
-  p->h_min = p->h_min_ratio * gp->epsilon_cur / kernel_gamma;
+  // MATTHIEU
+  p->h_min = p->h_min_ratio * 1. /*gp->epsilon_cur*/ / kernel_gamma;
 }
 
 /**
diff --git a/src/multipole.h b/src/multipole.h
index e867dfd4e2cc5c9fcd06d7d95dcf76a97689c2b3..fe17a624491ac88a8d9061cba99b47c69d48bc74 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -117,6 +117,9 @@ struct multipole {
   /*! Minimal velocity along each axis of all #gpart */
   float min_delta_vel[3];
 
+  /*! Maximal co-moving softening of all the #gpart in the mulipole */
+  float max_softening;
+
   /* 0th order term */
   float M_000;
 
@@ -459,6 +462,7 @@ INLINE static void gravity_multipole_init(struct multipole *m) {
  */
 INLINE static void gravity_multipole_print(const struct multipole *m) {
 
+  printf("eps_max = %12.5e\n", m->max_softening);
   printf("Vel= [%12.5e %12.5e %12.5e]\n", m->vel[0], m->vel[1], m->vel[2]);
   printf("-------------------------\n");
   printf("M_000= %12.5e\n", m->M_000);
@@ -512,6 +516,9 @@ INLINE static void gravity_multipole_print(const struct multipole *m) {
 INLINE static void gravity_multipole_add(struct multipole *restrict ma,
                                          const struct multipole *restrict mb) {
 
+  /* Maximum of both softenings */
+  ma->max_softening = max(ma->max_softening, mb->max_softening);
+
   /* Add 0th order term */
   ma->M_000 += mb->M_000;
 
@@ -630,6 +637,14 @@ INLINE static int gravity_multipole_equal(const struct gravity_tensors *ga,
   const double v2 = ma->vel[0] * ma->vel[0] + ma->vel[1] * ma->vel[1] +
                     ma->vel[2] * ma->vel[2];
 
+  /* Check maximal softening */
+  if (fabsf(ma->max_softening - mb->max_softening) /
+          fabsf(ma->max_softening + mb->max_softening) >
+      tolerance) {
+    message("max softening different!");
+    return 0;
+  }
+
   /* Check bulk velocity (if non-zero and component > 1% of norm)*/
   if (fabsf(ma->vel[0] + mb->vel[0]) > 1e-10 &&
       (ma->vel[0] * ma->vel[0]) > 0.0001 * v2 &&
@@ -1022,11 +1037,14 @@ INLINE static int gravity_multipole_equal(const struct gravity_tensors *ga,
  * @param multi The #multipole (content will  be overwritten).
  * @param gparts The #gpart.
  * @param gcount The number of particles.
+ * @param grav_props The properties of the gravity scheme.
  */
 INLINE static void gravity_P2M(struct gravity_tensors *multi,
-                               const struct gpart *gparts, int gcount) {
+                               const struct gpart *gparts, const int gcount,
+                               const struct gravity_props *const grav_props) {
 
   /* Temporary variables */
+  float epsilon_max = 0.f;
   double mass = 0.0;
   double com[3] = {0.0, 0.0, 0.0};
   double vel[3] = {0.f, 0.f, 0.f};
@@ -1034,12 +1052,14 @@ INLINE static void gravity_P2M(struct gravity_tensors *multi,
   /* Collect the particle data for CoM. */
   for (int k = 0; k < gcount; k++) {
     const double m = gparts[k].mass;
+    const float epsilon = gravity_get_softening(&gparts[k], grav_props);
 
 #ifdef SWIFT_DEBUG_CHECKS
     if (gparts[k].time_bin == time_bin_inhibited)
       error("Inhibited particle in P2M. Should have been removed earlier.");
 #endif
 
+    epsilon_max = max(epsilon_max, epsilon);
     mass += m;
     com[0] += gparts[k].x[0] * m;
     com[1] += gparts[k].x[1] * m;
@@ -1203,6 +1223,7 @@ INLINE static void gravity_P2M(struct gravity_tensors *multi,
 #endif
 
   /* Store the data on the multipole. */
+  multi->m_pole.max_softening = epsilon_max;
   multi->m_pole.M_000 = mass;
   multi->r_max = sqrt(r_max2);
   multi->CoM[0] = com[0];
@@ -1316,6 +1337,9 @@ INLINE static void gravity_M2M(struct multipole *restrict m_a,
                                const struct multipole *restrict m_b,
                                const double pos_a[3], const double pos_b[3]) {
 
+  /* "shift" the softening */
+  m_a->max_softening = m_b->max_softening;
+
   /* Shift 0th order term */
   m_a->M_000 = m_b->M_000;
 
@@ -1964,8 +1988,8 @@ INLINE static void gravity_M2L_nonsym(
     const int periodic, const double dim[3], const float rs_inv) {
 
   /* Recover some constants */
-  const float eps = props->epsilon_cur;
-  const float eps_inv = props->epsilon_cur_inv;
+  const float eps = m_a->max_softening;
+  const float eps_inv = 1.f / eps;
 
   /* Compute distance vector */
   float dx = (float)(pos_b[0] - pos_a[0]);
@@ -2015,8 +2039,8 @@ INLINE static void gravity_M2L_symmetric(
     const float rs_inv) {
 
   /* Recover some constants */
-  const float eps = props->epsilon_cur;
-  const float eps_inv = props->epsilon_cur_inv;
+  const float eps = m_a->max_softening;
+  const float eps_inv = 1.f / eps;
 
   /* Compute distance vector */
   float dx = (float)(pos_b[0] - pos_a[0]);
diff --git a/src/serial_io.c b/src/serial_io.c
index 3b3872762f237c4922bbc30fd866599547b23557..05a1839572cfcea8a81559cbdb197dbed26e605d 100644
--- a/src/serial_io.c
+++ b/src/serial_io.c
@@ -493,11 +493,11 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
                     double dim[3], struct part** parts, struct gpart** gparts,
                     struct spart** sparts, struct bpart** bparts, size_t* Ngas,
                     size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars,
-                    size_t* Nblackholes, int* flag_entropy, int with_hydro,
-                    int with_gravity, int with_stars, int with_black_holes,
-                    int cleanup_h, int cleanup_sqrt_a, double h, double a,
-                    int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                    int n_threads, int dry_run) {
+                    size_t* Nblackholes, int* flag_entropy, float* gpart_mass,
+                    int with_hydro, int with_gravity, int with_stars,
+                    int with_black_holes, int cleanup_h, int cleanup_sqrt_a,
+                    double h, double a, 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) */
@@ -801,6 +801,14 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
     /* Prepare the DM particles */
     io_prepare_dm_gparts(&tp, *gparts, Ndm);
 
+    /* Record the mass of the DM particles */
+    const float local_gpart_mass = (*gparts)[0].mass;
+    float global_gpart_mass;
+    MPI_Allreduce(&local_gpart_mass, &global_gpart_mass, 1, MPI_FLOAT, MPI_MAX,
+                  comm);
+    /* Record the mass of the DM particles */
+    *gpart_mass = global_gpart_mass;
+
     /* Prepare the DM background particles */
     io_prepare_dm_background_gparts(&tp, *gparts + Ndm, Ndm_background);
 
diff --git a/src/serial_io.h b/src/serial_io.h
index 6badf076b8373ce2b6d5b2cd3d91a5b2f57ed8ae..e038d578a8d8c1acfd582515263ef9b086f9edbe 100644
--- a/src/serial_io.h
+++ b/src/serial_io.h
@@ -39,11 +39,11 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units,
                     double dim[3], struct part** parts, struct gpart** gparts,
                     struct spart** sparts, struct bpart** bparts, size_t* Ngas,
                     size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars,
-                    size_t* Nblackholes, int* flag_entropy, int with_hydro,
-                    int with_gravity, int with_stars, int with_black_holes,
-                    int cleanup_h, int cleanup_sqrt_a, double h, double a,
-                    int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info,
-                    int n_threads, int dry_run);
+                    size_t* Nblackholes, int* flag_entropy, float* gpart_mass,
+                    int with_hydro, int with_gravity, int with_stars,
+                    int with_black_holes, int cleanup_h, int cleanup_sqrt_a,
+                    double h, double a, int mpi_rank, int mpi_size,
+                    MPI_Comm comm, MPI_Info info, int n_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 6f1f4a0d8bbcb1c66c35e6efe6f2a5a13a9f5104..ae42fd9a213e05ad9688e4642f0f2fb989302964 100644
--- a/src/single_io.c
+++ b/src/single_io.c
@@ -405,10 +405,10 @@ void read_ic_single(const char* fileName,
                     struct part** parts, struct gpart** gparts,
                     struct spart** sparts, struct bpart** bparts, size_t* Ngas,
                     size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars,
-                    size_t* Nblackholes, int* flag_entropy, int with_hydro,
-                    int with_gravity, int with_stars, int with_black_holes,
-                    int cleanup_h, int cleanup_sqrt_a, double h, double a,
-                    int n_threads, int dry_run) {
+                    size_t* Nblackholes, int* flag_entropy, float* gpart_mass,
+                    int with_hydro, int with_gravity, int with_stars,
+                    int with_black_holes, int cleanup_h, int cleanup_sqrt_a,
+                    double h, double a, int n_threads, int dry_run) {
 
   hid_t h_file = 0, h_grp = 0;
   /* GADGET has only cubic boxes (in cosmological mode) */
@@ -665,6 +665,9 @@ void read_ic_single(const char* fileName,
     /* Prepare the DM particles */
     io_prepare_dm_gparts(&tp, *gparts, Ndm);
 
+    /* Record the mass of the DM particles */
+    *gpart_mass = (*gparts)[0].mass;
+
     /* Prepare the DM background particles */
     io_prepare_dm_background_gparts(&tp, *gparts + Ndm, Ndm_background);
 
diff --git a/src/single_io.h b/src/single_io.h
index 47b575272c2fbe5b170eb4370743cd6830b99ae0..6044d903efffe587d32d66e4e6785503ed6b10d2 100644
--- a/src/single_io.h
+++ b/src/single_io.h
@@ -35,10 +35,10 @@ void read_ic_single(const char* fileName,
                     struct part** parts, struct gpart** gparts,
                     struct spart** sparts, struct bpart** bparts, size_t* Ngas,
                     size_t* Ndm, size_t* Ndm_background, size_t* Nstars,
-                    size_t* Nblackholes, int* flag_entropy, int with_hydro,
-                    int with_gravity, int with_stars, int with_black_holes,
-                    int cleanup_h, int cleanup_sqrt_a, double h, double a,
-                    int nr_threads, int dry_run);
+                    size_t* Nblackholes, int* flag_entropy, float* gpart_mass,
+                    int with_hydro, int with_gravity, int with_stars,
+                    int with_black_holes, int cleanup_h, int cleanup_sqrt_a,
+                    double h, double a, int nr_threads, int dry_run);
 
 void write_output_single(struct engine* e, const char* baseName,
                          const struct unit_system* internal_units,
diff --git a/src/space.c b/src/space.c
index 61ecf3fd81f4a57d274ad911e0471337625f944b..cea579d09f438ff07611eb4c674decd7a3547de8 100644
--- a/src/space.c
+++ b/src/space.c
@@ -1928,7 +1928,7 @@ void space_rebuild(struct space *s, int repartitioned, int verbose) {
   /* Check that the multipole construction went OK */
   if (s->with_self_gravity)
     for (int k = 0; k < s->nr_cells; k++)
-      cell_check_multipole(&s->cells_top[k]);
+      cell_check_multipole(&s->cells_top[k], s->e->gravity_properties);
 #endif
 
   /* Clean up any stray sort indices in the cell buffer. */
@@ -3603,7 +3603,8 @@ void space_split_recursive(struct space *s, struct cell *c,
     if (s->with_self_gravity) {
       if (gcount > 0) {
 
-        gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count);
+        gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count,
+                    e->gravity_properties);
 
       } else {