diff --git a/src/const.h b/src/const.h
index 928835c5ae0ac70d641243b0d183c2c0652cdc8a..cd6aecbe603719467ebb010515befbd383fce965 100644
--- a/src/const.h
+++ b/src/const.h
@@ -53,7 +53,10 @@
 /* This option disables particle movement */
 //#define GIZMO_FIX_PARTICLES
 /* Try to keep cells regular by adding a correction velocity. */
-#define GIZMO_STEER_MOTION
+//#define GIZMO_STEER_MOTION
+/* Use a meshless finite mass method. */
+#define GIZMO_MFM
+/* Use the total energy instead of the thermal energy as conserved variable. */
 //#define GIZMO_TOTAL_ENERGY
 
 /* Options to control handling of unphysical values (GIZMO_SPH only). */
diff --git a/src/riemann/riemann_exact.h b/src/riemann/riemann_exact.h
index 0c6c1c86273b42f521102e6e91d642d3dff30b27..caf2e923b76a0328c3faee05a661c8aa2afa292b 100644
--- a/src/riemann/riemann_exact.h
+++ b/src/riemann/riemann_exact.h
@@ -485,6 +485,88 @@ __attribute__((always_inline)) INLINE static void riemann_solver_solve(
   Whalf[3] += vhalf * n_unit[2];
 }
 
+/**
+ * @brief Solve the Riemann problem between the given left and right state and
+ * return the velocity and pressure in the middle state
+ *
+ * Based on chapter 4 in Toro
+ *
+ * @param WL Left state.
+ * @param vL Left state velocity.
+ * @param WR Right state.
+ * @param vR Right state velocity.
+ * @param vM Middle state velocity.
+ * @param PM Middle state pressure.
+ */
+__attribute__((always_inline)) INLINE static void
+riemann_solver_solve_middle_state(const float* WL, const float vL,
+                                  const float* WR, const float vR, float* vM,
+                                  float* PM) {
+
+  /* sound speeds */
+  float aL, aR;
+  /* variables used for finding pstar */
+  float p, pguess, fp, fpguess;
+
+  /* calculate sound speeds */
+  aL = sqrtf(hydro_gamma * WL[4] / WL[0]);
+  aR = sqrtf(hydro_gamma * WR[4] / WR[0]);
+
+  /* vacuum */
+  /* check vacuum (generation) condition */
+  if (riemann_is_vacuum(WL, WR, vL, vR, aL, aR)) {
+    *vM = 0.0f;
+    *PM = 0.0f;
+    return;
+  }
+
+  /* values are ok: let's find pstar (riemann_f(pstar) = 0)! */
+  /* We normally use a Newton-Raphson iteration to find the zeropoint
+     of riemann_f(p), but if pstar is close to 0, we risk negative p values.
+     Since riemann_f(p) is undefined for negative pressures, we don't
+     want this to happen.
+     We therefore use Brent's method if riemann_f(0) is larger than some
+     value. -5 makes the iteration fail safe while almost never invoking
+     the expensive Brent solver. */
+  p = 0.0f;
+  /* obtain a first guess for p */
+  pguess = riemann_guess_p(WL, WR, vL, vR, aL, aR);
+  fp = riemann_f(p, WL, WR, vL, vR, aL, aR);
+  fpguess = riemann_f(pguess, WL, WR, vL, vR, aL, aR);
+  /* ok, pstar is close to 0, better use Brent's method... */
+  /* we use Newton-Raphson until we find a suitable interval */
+  if (fp * fpguess >= 0.0f) {
+    /* Newton-Raphson until convergence or until suitable interval is found
+       to use Brent's method */
+    unsigned int counter = 0;
+    while (fabs(p - pguess) > 1.e-6f * 0.5f * (p + pguess) && fpguess < 0.0f) {
+      p = pguess;
+      pguess = pguess - fpguess / riemann_fprime(pguess, WL, WR, aL, aR);
+      fpguess = riemann_f(pguess, WL, WR, vL, vR, aL, aR);
+      counter++;
+      if (counter > 1000) {
+        error("Stuck in Newton-Raphson!\n");
+      }
+    }
+  }
+  /* As soon as there is a suitable interval: use Brent's method */
+  if (1.e6 * fabs(p - pguess) > 0.5f * (p + pguess) && fpguess > 0.0f) {
+    p = 0.0f;
+    fp = riemann_f(p, WL, WR, vL, vR, aL, aR);
+    /* use Brent's method to find the zeropoint */
+    p = riemann_solve_brent(p, pguess, fp, fpguess, 1.e-6, WL, WR, vL, vR, aL,
+                            aR);
+  } else {
+    p = pguess;
+  }
+
+  *PM = p;
+  /* calculate the velocity in the intermediate state */
+  *vM =
+      0.5f * (vL + vR) + 0.5f * (riemann_fb(p, WR, aR) - riemann_fb(p, WL, aL));
+}
+
+#ifndef GIZMO_MFM
 __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
     const float* Wi, const float* Wj, const float* n_unit, const float* vij,
     float* totflux) {
@@ -542,5 +624,44 @@ __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
   riemann_check_output(Wi, Wj, n_unit, vij, totflux);
 #endif
 }
+#else /* GIZMO_MFM */
+__attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
+    const float* Wi, const float* Wj, const float* n_unit, const float* vij,
+    float* totflux) {
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_input(Wi, Wj, n_unit, vij);
+#endif
+
+  /* vacuum? */
+  if (Wi[0] == 0.0f || Wj[0] == 0.0f) {
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
+    return;
+  }
+
+  const float vL = Wi[1] * n_unit[0] + Wi[2] * n_unit[1] + Wi[3] * n_unit[2];
+  const float vR = Wj[1] * n_unit[0] + Wj[2] * n_unit[1] + Wj[3] * n_unit[2];
+
+  float vM, PM;
+  riemann_solver_solve_middle_state(Wi, vL, Wj, vR, &vM, &PM);
+
+  const float vface =
+      vij[0] * n_unit[0] + vij[1] * n_unit[1] + vij[2] * n_unit[2];
+
+  totflux[0] = 0.0f;
+  totflux[1] = PM * n_unit[0];
+  totflux[2] = PM * n_unit[1];
+  totflux[3] = PM * n_unit[2];
+  totflux[4] = (vM + vface) * PM;
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_output(Wi, Wj, n_unit, vij, totflux);
+#endif
+}
+#endif /* GIZMO_MFM */
 
 #endif /* SWIFT_RIEMANN_EXACT_H */
diff --git a/src/riemann/riemann_hllc.h b/src/riemann/riemann_hllc.h
index 26fcd627fcf11769baf18955af53ed6e948ba513..e5dc3a9ae094c28c6fa1e612e349a3930c72a882 100644
--- a/src/riemann/riemann_hllc.h
+++ b/src/riemann/riemann_hllc.h
@@ -38,6 +38,7 @@
     "The HLLC Riemann solver currently only supports and ideal gas equation of state. Either select this equation of state, or try using another Riemann solver!"
 #endif
 
+#ifndef GIZMO_MFM
 __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
     const float *WL, const float *WR, const float *n, const float *vij,
     float *totflux) {
@@ -184,5 +185,78 @@ __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
   riemann_check_output(WL, WR, n, vij, totflux);
 #endif
 }
+#else /* GIZMO_MFM */
+__attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
+    const float *WL, const float *WR, const float *n, const float *vij,
+    float *totflux) {
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_input(WL, WR, n, vij);
+#endif
+
+  /* Handle pure vacuum */
+  if (!WL[0] && !WR[0]) {
+    totflux[0] = 0.f;
+    totflux[1] = 0.f;
+    totflux[2] = 0.f;
+    totflux[3] = 0.f;
+    totflux[4] = 0.f;
+    return;
+  }
+
+  /* STEP 0: obtain velocity in interface frame */
+  const float uL = WL[1] * n[0] + WL[2] * n[1] + WL[3] * n[2];
+  const float uR = WR[1] * n[0] + WR[2] * n[1] + WR[3] * n[2];
+  const float aL = sqrtf(hydro_gamma * WL[4] / WL[0]);
+  const float aR = sqrtf(hydro_gamma * WR[4] / WR[0]);
+
+  /* Handle vacuum: vacuum does not require iteration and is always exact */
+  if (riemann_is_vacuum(WL, WR, uL, uR, aL, aR)) {
+    totflux[0] = 0.f;
+    totflux[1] = 0.f;
+    totflux[2] = 0.f;
+    totflux[3] = 0.f;
+    totflux[4] = 0.f;
+    return;
+  }
+
+  /* STEP 1: pressure estimate */
+  const float rhobar = 0.5f * (WL[0] + WR[0]);
+  const float abar = 0.5f * (aL + aR);
+  const float pPVRS = 0.5f * (WL[4] + WR[4]) - 0.5f * (uR - uL) * rhobar * abar;
+  const float pstar = max(0.f, pPVRS);
+
+  /* STEP 2: wave speed estimates
+     all these speeds are along the interface normal, since uL and uR are */
+  float qL = 1.f;
+  if (pstar > WL[4] && WL[4] > 0.f) {
+    qL = sqrtf(1.f +
+               0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                   (pstar / WL[4] - 1.f));
+  }
+  float qR = 1.f;
+  if (pstar > WR[4] && WR[4] > 0.f) {
+    qR = sqrtf(1.f +
+               0.5f * hydro_gamma_plus_one * hydro_one_over_gamma *
+                   (pstar / WR[4] - 1.f));
+  }
+  const float SL = uL - aL * qL;
+  const float SR = uR + aR * qR;
+  const float Sstar =
+      (WR[4] - WL[4] + WL[0] * uL * (SL - uL) - WR[0] * uR * (SR - uR)) /
+      (WL[0] * (SL - uL) - WR[0] * (SR - uR));
+
+  totflux[0] = 0.0f;
+  totflux[1] = pstar * n[0];
+  totflux[2] = pstar * n[1];
+  totflux[3] = pstar * n[2];
+  const float vface = vij[0] * n[0] + vij[1] * n[1] + vij[2] * n[2];
+  totflux[4] = pstar * (Sstar + vface);
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_output(WL, WR, n, vij, totflux);
+#endif
+}
+#endif /* GIZMO_MFM */
 
 #endif /* SWIFT_RIEMANN_HLLC_H */
diff --git a/src/riemann/riemann_trrs.h b/src/riemann/riemann_trrs.h
index 597f6f8edd9690dbdd34a3c9885ae228c2af734c..5722b2efac3991970bb4e2ec347f9f89befa3762 100644
--- a/src/riemann/riemann_trrs.h
+++ b/src/riemann/riemann_trrs.h
@@ -161,6 +161,7 @@ __attribute__((always_inline)) INLINE static void riemann_solver_solve(
   Whalf[3] += vhalf * n_unit[2];
 }
 
+#ifndef GIZMO_MFM
 __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
     const float* Wi, const float* Wj, const float* n_unit, const float* vij,
     float* totflux) {
@@ -218,5 +219,65 @@ __attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
   riemann_check_output(Wi, Wj, n_unit, vij, totflux);
 #endif
 }
+#else /* GIZMO_MFM */
+__attribute__((always_inline)) INLINE static void riemann_solve_for_flux(
+    const float* Wi, const float* Wj, const float* n_unit, const float* vij,
+    float* totflux) {
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_input(Wi, Wj, n_unit, vij);
+#endif
+
+  if (Wi[0] == 0.0f || Wj[0] == 0.0f) {
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
+    return;
+  }
+
+  /* calculate the velocities along the interface normal */
+  const float vL = Wi[1] * n_unit[0] + Wi[2] * n_unit[1] + Wi[3] * n_unit[2];
+  const float vR = Wj[1] * n_unit[0] + Wj[2] * n_unit[1] + Wj[3] * n_unit[2];
+
+  /* calculate the sound speeds */
+  const float aL = sqrtf(hydro_gamma * Wi[4] / Wi[0]);
+  const float aR = sqrtf(hydro_gamma * Wj[4] / Wj[0]);
+
+  if (riemann_is_vacuum(Wi, Wj, vL, vR, aL, aR)) {
+    totflux[0] = 0.0f;
+    totflux[1] = 0.0f;
+    totflux[2] = 0.0f;
+    totflux[3] = 0.0f;
+    totflux[4] = 0.0f;
+    return;
+  }
+
+  /* calculate the velocity and pressure in the intermediate state */
+  const float PLR = pow_gamma_minus_one_over_two_gamma(Wi[4] / Wj[4]);
+  const float ustar = (PLR * vL / aL + vR / aR +
+                       hydro_two_over_gamma_minus_one * (PLR - 1.0f)) /
+                      (PLR / aL + 1.0f / aR);
+  const float pstar =
+      0.5f *
+      (Wi[4] * pow_two_gamma_over_gamma_minus_one(
+                   1.0f + hydro_gamma_minus_one_over_two / aL * (vL - ustar)) +
+       Wj[4] * pow_two_gamma_over_gamma_minus_one(
+                   1.0f + hydro_gamma_minus_one_over_two / aR * (ustar - vR)));
+
+  totflux[0] = 0.0f;
+  totflux[1] = pstar * n_unit[0];
+  totflux[2] = pstar * n_unit[1];
+  totflux[3] = pstar * n_unit[2];
+  const float vface =
+      vij[0] * n_unit[0] + vij[1] * n_unit[1] + vij[2] * n_unit[2];
+  totflux[4] = pstar * (ustar + vface);
+
+#ifdef SWIFT_DEBUG_CHECKS
+  riemann_check_output(Wi, Wj, n_unit, vij, totflux);
+#endif
+}
+#endif /* GIZMO_MFM */
 
 #endif /* SWIFT_RIEMANN_TRRS_H */