From c5a703a297c6eb8fed2625be818d8c5296e96da6 Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <matthieu.schaller@durham.ac.uk>
Date: Sat, 9 Jun 2018 13:53:45 +0200
Subject: [PATCH] Full expression for the Gadget2 truncation function and its
 derivatives.

---
 src/kernel_long_gravity.h          | 37 +++++++++++++++++++++++++++++-
 theory/Multipoles/mesh_summary.tex |  2 +-
 2 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/kernel_long_gravity.h b/src/kernel_long_gravity.h
index f818d67d9f..0adfcb303d 100644
--- a/src/kernel_long_gravity.h
+++ b/src/kernel_long_gravity.h
@@ -31,7 +31,7 @@
 #include <float.h>
 #include <math.h>
 
-//#define GADGET2_LONG_RANGE_CORRECTION
+#define GADGET2_LONG_RANGE_CORRECTION
 
 struct truncated_derivatives {
 
@@ -47,6 +47,40 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_derivatives(
     const float r, const float rs_inv,
     struct truncated_derivatives *const derivs) {
 
+#ifdef GADGET2_LONG_RANGE_CORRECTION
+
+  /* Powers of u=r/2r_s */
+  const float u = 0.5f * r * rs_inv;
+  const float u2 = u * u;
+  const float u3 = u2 * u;
+  const float u4 = u3 * u;
+
+  /* Powers of (1/r_s) */
+  const float rs_inv2 = rs_inv * rs_inv;
+  const float rs_inv3 = rs_inv2 * rs_inv;
+  const float rs_inv4 = rs_inv3 * rs_inv;
+  const float rs_inv5 = rs_inv4 * rs_inv;
+
+  /* Derivatives of \chi */
+  derivs->chi_0 = erfcf(u);
+  derivs->chi_1 = -rs_inv;
+  derivs->chi_2 = rs_inv2 * u;
+  derivs->chi_3 = -rs_inv3 * (u2 - 0.5f);
+  derivs->chi_4 = rs_inv4 * (u3 - 1.5f * u);
+  derivs->chi_5 = -rs_inv5 * (u4 - u2 + 0.75f);
+
+  const float one_over_sqrt_pi = ((float)(M_2_SQRTPI * 0.5));
+  const float common_factor = one_over_sqrt_pi * expf(-u2);
+
+  /* Multiply in the common factors */
+  derivs->chi_1 *= common_factor;
+  derivs->chi_2 *= common_factor;
+  derivs->chi_3 *= common_factor;
+  derivs->chi_4 *= common_factor;
+  derivs->chi_5 *= common_factor;
+
+#else
+
   /* Powers of 2/r_s */
   const float c0 = 1.f;
   const float c1 = 2.f * rs_inv;
@@ -80,6 +114,7 @@ __attribute__((always_inline)) INLINE static void kernel_long_grav_derivatives(
   derivs->chi_4 = -2.f * exp_x * c4 * (24.f * a5 - 36.f * a4 + 14.f * a3 - a2);
   derivs->chi_5 = -2.f * exp_x * c5 *
                   (120.f * a6 - 240.f * a5 + 150.f * a4 - 30.f * a3 + a2);
+#endif
 }
 
 /**
diff --git a/theory/Multipoles/mesh_summary.tex b/theory/Multipoles/mesh_summary.tex
index afab390bfe..1b952f0dba 100644
--- a/theory/Multipoles/mesh_summary.tex
+++ b/theory/Multipoles/mesh_summary.tex
@@ -24,7 +24,7 @@ This function alongside the trunctation function used in
   $\chi(r, r_s) = \mathrm{erfc}(\frac{1}{2}\frac{r}{r_s})$.} is shown
 on Fig.~\ref{fig:fmm:potential_short}. This choice of $\sigma(w)$ can
 seem rather cumbersome at first but writing
-$\alpha(w) \equiv (1+e^w)^{-1}$, one can expressed all derivatives of
+$\alpha(w) \equiv (1+e^w)^{-1}$, one can express all derivatives of
 $\sigma(w)$ as simple polynomials in $\alpha(w)$ (with an identical
 $e^w$ pre-factor), which are easy and cheap to evaluate (see Appendix
 \ref{sec:pot_derivatives}). For instance, in the case of the direct
-- 
GitLab