diff --git a/src/gravity_derivatives.h b/src/gravity_derivatives.h
index d698c66e418a120e5e7ebbe1cba0a5a9af8cd1f1..ea188f64a60627c776604618329bb205cad37f7c 100644
--- a/src/gravity_derivatives.h
+++ b/src/gravity_derivatives.h
@@ -33,6 +33,7 @@
 /* Local headers. */
 #include "inline.h"
 #include "kernel_gravity.h"
+#include "kernel_long_gravity.h"
 
 /**
  * @brief Structure containing all the derivatives of the potential field
@@ -40,7 +41,7 @@
  */
 struct potential_derivatives_M2L {
 
-  /* 0th order terms */
+  /* 0th order term */
   float D_000;
 
 #if SELF_GRAVITY_MULTIPOLE_ORDER > 0
@@ -124,11 +125,14 @@ struct potential_derivatives_M2P {
  * @param r_inv Inverse norm of distance vector
  * @param eps Softening length.
  * @param eps_inv Inverse of softening length.
+ * @param periodic Is the calculation periodic ?
+ * @param rs_inv
  * @param pot (return) The structure containing all the derivatives.
  */
 __attribute__((always_inline)) INLINE static void
 compute_potential_derivatives_M2L(float r_x, float r_y, float r_z, float r2,
                                   float r_inv, float eps, float eps_inv,
+                                  int periodic, float rs_inv,
                                   struct potential_derivatives_M2L *pot) {
 
   float Dt_1;
@@ -148,8 +152,8 @@ compute_potential_derivatives_M2L(float r_x, float r_y, float r_z, float r2,
   float Dt_11;
 #endif
 
-  /* Un-softened case */
-  if (r2 > eps * eps) {
+  /* Un-softened un-truncated case (Newtonian potential) */
+  if (!periodic && r2 > eps * eps) {
 
     Dt_1 = r_inv;
 #if SELF_GRAVITY_MULTIPOLE_ORDER > 0
@@ -171,6 +175,52 @@ compute_potential_derivatives_M2L(float r_x, float r_y, float r_z, float r2,
 #if SELF_GRAVITY_MULTIPOLE_ORDER > 5
 #error "Missing implementation for order >5"
 #endif
+    /* Un-softened truncated case */
+  } else if (periodic && r2 > eps * eps) {
+
+    /* Get the derivatives of the truncated potential */
+    const float r = r2 * r_inv;
+    struct truncated_derivatives derivs;
+    kernel_long_grav_derivatives(r, rs_inv, &derivs);
+
+    Dt_1 = derivs.chi_0 * r_inv;
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 0
+    const float r_inv2 = r_inv * r_inv;
+    const float r_inv3 = r_inv2 * r_inv;
+    Dt_3 = (r * derivs.chi_1 - derivs.chi_0) * r_inv3;
+#endif
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 1
+    const float r_inv5 = r_inv2 * r_inv3;
+    Dt_5 =
+        (r * r * derivs.chi_2 - 3.f * r * derivs.chi_1 + 3.f * derivs.chi_0) *
+        r_inv5;
+#endif
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 2
+    const float r_inv7 = r_inv2 * r_inv5;
+    Dt_7 = (r * r * r * derivs.chi_3 - 6.f * r * r * derivs.chi_2 +
+            15.f * r * derivs.chi_1 - 15.f * derivs.chi_0) *
+           r_inv7;
+#endif
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 3
+    const float r_inv9 = r_inv2 * r_inv7;
+    Dt_9 = (r * r * r * r * derivs.chi_4 - 10.f * r * r * r * derivs.chi_3 +
+            45.f * r * r * derivs.chi_2 - 105.f * r * derivs.chi_1 +
+            105.f * derivs.chi_0) *
+           r_inv9;
+#endif
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 4
+    const float r_inv11 = r_inv2 * r_inv9;
+    Dt_11 = (r * r * r * r * r * derivs.chi_5 -
+             15.f * r * r * r * r * derivs.chi_4 +
+             105.f * r * r * r * derivs.chi_3 - 420.f * r * r * derivs.chi_2 +
+             945.f * r * derivs.chi_1 - 945.f * derivs.chi_0) *
+            r_inv11;
+#endif
+#if SELF_GRAVITY_MULTIPOLE_ORDER > 5
+#error "Missing implementation for order >5"
+#endif
+
+    /* Softened case */
 
   } else {
     const float r = r2 * r_inv;
diff --git a/src/kernel_long_gravity.h b/src/kernel_long_gravity.h
index e2e3117c51523b9c2fa330e9591ce28805d3a42a..f0e239cb9bfcbdfbba17779dc262bf88e23d42fd 100644
--- a/src/kernel_long_gravity.h
+++ b/src/kernel_long_gravity.h
@@ -28,10 +28,55 @@
 #include "inline.h"
 
 /* Standard headers */
+#include <float.h>
 #include <math.h>
 
 //#define GADGET2_LONG_RANGE_CORRECTION
 
+struct truncated_derivatives {
+
+  float chi_0;
+  float chi_1;
+  float chi_2;
+  float chi_3;
+  float chi_4;
+  float chi_5;
+};
+
+__attribute__((always_inline)) INLINE static void kernel_long_grav_derivatives(
+    const float r, const float rs_inv,
+    struct truncated_derivatives *const derivs) {
+
+  const float constant1 = 2.f * rs_inv;
+  const float x = constant1 * r;
+
+  const float exp_x = expf(x);  // good_approx_expf(x);
+  const float alpha_inv = 1.f + exp_x;
+
+  const float alpha1 = 1.f / alpha_inv;
+  const float alpha2 = alpha1 * alpha1;
+  const float alpha3 = alpha2 * alpha1;
+  const float alpha4 = alpha3 * alpha1;
+  const float alpha5 = alpha4 * alpha1;
+  const float alpha6 = alpha5 * alpha1;
+
+  const float constant2 = constant1 * constant1;
+  const float constant3 = constant2 * constant1;
+  const float constant4 = constant3 * constant1;
+  const float constant5 = constant4 * constant1;
+
+  derivs->chi_0 = 2.f * (1.f - exp_x * alpha1);
+  derivs->chi_1 = constant1 * (2.f * alpha2 - 2.f * alpha1);
+  derivs->chi_2 = constant2 * (4.f * alpha3 - 6.f * alpha2 + 2.f * alpha1);
+  derivs->chi_3 = constant3 * (12.f * alpha4 - 24.f * alpha3 + 14.f * alpha2 -
+                               2.f * alpha1);
+  derivs->chi_4 = constant4 * (48.f * alpha5 - 120.f * alpha4 + 100.f * alpha3 -
+                               30.f * alpha2 + 2.f * alpha1);
+  derivs->chi_5 =
+      constant5 * (240.f * alpha6 - 720.f * alpha5 + 780.f * alpha4 -
+                   360.f * alpha3 + 62.f * alpha2 - 2.f * alpha1);
+}
+
 /**
  * @brief Computes the long-range correction term for the potential calculation
  * coming from FFT.
@@ -68,7 +113,7 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_pot_eval(
  * @param W (return) The value of the kernel function.
  */
 __attribute__((always_inline)) INLINE static void kernel_long_grav_force_eval(
-    float u, float *const W) {
+    const float u, float *const W) {
 
 #ifdef GADGET2_LONG_RANGE_CORRECTION
 
@@ -112,7 +157,7 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_force_eval(
  * @param W (return) The value of the kernel function.
  */
 __attribute__((always_inline)) INLINE static void fourier_kernel_long_grav_eval(
-    double u2, double *const W) {
+    const double u2, double *const W) {
 
 #ifdef GADGET2_LONG_RANGE_CORRECTION
   *W = exp(-u2);
diff --git a/src/multipole.h b/src/multipole.h
index d5756c3ac060fc03faa9e841653dab5c9768f352..26857c3b877ffec1c3070e707d938d682f5c0069 100644
--- a/src/multipole.h
+++ b/src/multipole.h
@@ -1521,9 +1521,7 @@ INLINE static void gravity_M2L(struct grav_tensor *l_b,
                                const struct multipole *m_a,
                                const double pos_b[3], const double pos_a[3],
                                const struct gravity_props *props, int periodic,
-                               const double dim[3]) {
-
-  error("ooo");
+                               const double dim[3], float rs_inv) {
 
   /* Recover some constants */
   const float eps = props->epsilon_cur;
@@ -1547,7 +1545,8 @@ INLINE static void gravity_M2L(struct grav_tensor *l_b,
 
   /* Compute all derivatives */
   struct potential_derivatives_M2L pot;
-  compute_potential_derivatives_M2L(dx, dy, dz, r2, r_inv, eps, eps_inv, &pot);
+  compute_potential_derivatives_M2L(dx, dy, dz, r2, r_inv, eps, eps_inv,
+                                    periodic, rs_inv, &pot);
 
 #ifdef SWIFT_DEBUG_CHECKS
   /* Count interactions */
@@ -2264,7 +2263,7 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb,
 #endif
 
   // MATTHIEU
-  return;
+  // return;
 
   /* Local accumulator */
   double a_grav[3] = {0., 0., 0.};
diff --git a/src/runner_doiact_grav.h b/src/runner_doiact_grav.h
index 0849a34b3f0647a5245306f3f08e741728444cfb..58b5b40cd50572c0cf399c2aab79c3b3e407f7e9 100644
--- a/src/runner_doiact_grav.h
+++ b/src/runner_doiact_grav.h
@@ -174,8 +174,8 @@ static INLINE void runner_dopair_grav_mm(struct runner *r,
   const int periodic = s->periodic;
   const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]};
   const struct gravity_props *props = e->gravity_properties;
-  // const float a_smooth = e->gravity_properties->a_smooth;
-  // const float rlr_inv = 1. / (a_smooth * ci->super->width[0]);
+  const float a_smooth = e->mesh->a_smooth;
+  const float rlr_inv = 1. / a_smooth;
 
   TIMER_TIC;
 
@@ -206,11 +206,8 @@ static INLINE void runner_dopair_grav_mm(struct runner *r,
         cj->ti_old_multipole, cj->nodeID, ci->nodeID, e->ti_current);
 
   /* Let's interact at this level */
-  if (0)
-    gravity_M2L(&ci->multipole->pot, multi_j, ci->multipole->CoM,
-                cj->multipole->CoM, props, periodic, dim);
-
-  runner_dopair_grav_pp(r, ci, cj, 0);
+  gravity_M2L(&ci->multipole->pot, multi_j, ci->multipole->CoM,
+              cj->multipole->CoM, props, periodic, dim, rlr_inv);
 
   TIMER_TOC(timer_dopair_grav_mm);
 }