From 3922dc4ff43b2b9ab38fcdec81e8ee9430064ccf Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <matthieu.schaller@durham.ac.uk>
Date: Wed, 13 Jul 2016 15:19:37 +0100
Subject: [PATCH] Faster implementation of pow(x, 5/3) and more generic version
 for various implementations

---
 src/Makefile.am           |   2 +-
 src/const.h               |   8 +--
 src/gamma.h               | 107 ++++++++++++++++++++++++++++++++++++++
 src/hydro/Gadget2/hydro.h |  23 ++++----
 src/units.c               |   9 ++--
 5 files changed, 130 insertions(+), 19 deletions(-)
 create mode 100644 src/gamma.h

diff --git a/src/Makefile.am b/src/Makefile.am
index bc263d6fb0..3b78a428f6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,7 +58,7 @@ nobase_noinst_HEADERS = approx_math.h atomic.h cycle.h error.h inline.h kernel_h
 		 gravity.h gravity_io.h \
 		 gravity/Default/gravity.h gravity/Default/gravity_iact.h gravity/Default/gravity_io.h \
 		 gravity/Default/gravity_debug.h gravity/Default/gravity_part.h  \
-	 	 hydro.h hydro_io.h \
+	 	 hydro.h hydro_io.h gamma.h \
 		 hydro/Minimal/hydro.h hydro/Minimal/hydro_iact.h hydro/Minimal/hydro_io.h \
                  hydro/Minimal/hydro_debug.h hydro/Minimal/hydro_part.h \
 		 hydro/Default/hydro.h hydro/Default/hydro_iact.h hydro/Default/hydro_io.h \
diff --git a/src/const.h b/src/const.h
index 673aa3bf00..65404d6a3e 100644
--- a/src/const.h
+++ b/src/const.h
@@ -20,9 +20,6 @@
 #ifndef SWIFT_CONST_H
 #define SWIFT_CONST_H
 
-/* Hydrodynamical constants. */
-#define const_hydro_gamma (5.0f / 3.0f)
-
 /* SPH Viscosity constants. */
 #define const_viscosity_alpha 0.8f
 #define const_viscosity_alpha_min \
@@ -44,6 +41,11 @@
 #define const_G 6.672e-8f     /* Gravitational constant. */
 #define const_epsilon 0.0014f /* Gravity blending distance. */
 
+/* Hydrodynamical adiabatic index. */
+#define HYDRO_GAMMA_5_3
+//#define HYDRO_GAMMA_4_3
+//#define HYDRO_GAMMA_2_1
+
 /* Kernel function to use */
 #define CUBIC_SPLINE_KERNEL
 //#define QUARTIC_SPLINE_KERNEL
diff --git a/src/gamma.h b/src/gamma.h
new file mode 100644
index 0000000000..f51f16b5c0
--- /dev/null
+++ b/src/gamma.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016   Matthieu Schaller (matthieu.schaller@durham.ac.uk).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ******************************************************************************/
+#ifndef SWIFT_GAMMA_H
+#define SWIFT_GAMMA_H
+
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <math.h>
+
+/* Local headers. */
+#include "const.h"
+#include "debug.h"
+#include "inline.h"
+
+/* First define some constants */
+#if defined(HYDRO_GAMMA_5_3)
+
+#define hydro_gamma 1.66666666666666667f
+#define hydro_gamma_minus_one 0.66666666666666667f
+
+#elif defined(HYDRO_GAMMA_4_3)
+
+#define hydro_gamma 1.33333333333333333f
+#define hydro_gamma_minus_one 0.33333333333333333f
+
+#elif defined(HYDRO_GAMMA_2_1)
+
+#define hydro_gamma 2.f
+#define hydro_gamma_minus_one 1.f
+
+#endif
+
+/**
+ * @brief Returns the argument to the power given by the adiabatic index
+ *
+ * Computes $x^\gamma$.
+ */
+__attribute__((always_inline)) INLINE static float pow_gamma(float x) {
+
+#if defined(HYDRO_GAMMA_5_3)
+
+  const float x2 = x * x;
+  const float x5 = x2 * x2 * x;
+  return cbrtf(x5);
+
+#elif defined(HYDRO_GAMMA_4_3)
+
+  const float x2 = x * x;
+  const float x4 = x2 * x2;
+  return cbrtf(x4);
+
+#elif defined(HYDRO_GAMMA_2_1)
+
+  return x * x;
+
+#else
+  error("The adiabatic index is not defined !");
+  return 0.f;
+#endif
+}
+
+/**
+ * @brief Returns one over the argument to the power given by the adiabatic
+ * index minus one
+ *
+ * Computes $x^{-(\gamma - 1)}$.
+ */
+__attribute__((always_inline)) INLINE static float pow_minus_gamma_minus_one(
+    float x) {
+
+#if defined(HYDRO_GAMMA_5_3)
+
+  return 1.f / cbrtf(x * x);
+
+#elif defined(HYDRO_GAMMA_4_3)
+
+  return 1.f / cbrtf(x);
+
+#elif defined(HYDRO_GAMMA_2_1)
+
+  return 1.f / x;
+
+#else
+  error("The adiabatic index is not defined !");
+  return 0.f;
+#endif
+}
+
+#endif /* SWIFT_GAMMA_H */
diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h
index 0973acb0fb..4081679d49 100644
--- a/src/hydro/Gadget2/hydro.h
+++ b/src/hydro/Gadget2/hydro.h
@@ -17,6 +17,8 @@
  *
  ******************************************************************************/
 
+#include "gamma.h"
+
 /**
  * @brief Computes the hydro time-step of a given particle
  *
@@ -132,11 +134,10 @@ __attribute__((always_inline)) INLINE static void hydro_prepare_force(
 
   /* Compute the pressure */
   const float dt = (ti_current - (p->ti_begin + p->ti_end) / 2) * timeBase;
-  p->force.pressure =
-      (p->entropy + p->entropy_dt * dt) * powf(p->rho, const_hydro_gamma);
+  p->force.pressure = (p->entropy + p->entropy_dt * dt) * pow_gamma(p->rho);
 
   /* Compute the sound speed */
-  p->force.soundspeed = sqrtf(const_hydro_gamma * p->force.pressure / p->rho);
+  p->force.soundspeed = sqrtf(hydro_gamma * p->force.pressure / p->rho);
 }
 
 /**
@@ -179,10 +180,10 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
   /* Drift the pressure */
   const float dt_entr = (t1 - (p->ti_begin + p->ti_end) / 2) * timeBase;
   p->force.pressure =
-      (p->entropy + p->entropy_dt * dt_entr) * powf(p->rho, const_hydro_gamma);
+      (p->entropy + p->entropy_dt * dt_entr) * pow_gamma(p->rho);
 
   /* Compute the new sound speed */
-  p->force.soundspeed = sqrtf(const_hydro_gamma * p->force.pressure / p->rho);
+  p->force.soundspeed = sqrtf(hydro_gamma * p->force.pressure / p->rho);
 }
 
 /**
@@ -195,8 +196,7 @@ __attribute__((always_inline)) INLINE static void hydro_predict_extra(
 __attribute__((always_inline)) INLINE static void hydro_end_force(
     struct part* p) {
 
-  p->entropy_dt *=
-      (const_hydro_gamma - 1.f) * powf(p->rho, -(const_hydro_gamma - 1.f));
+  p->entropy_dt *= hydro_gamma_minus_one * pow_minus_gamma_minus_one(p->rho);
 }
 
 /**
@@ -232,8 +232,8 @@ __attribute__((always_inline)) INLINE static void hydro_kick_extra(
 __attribute__((always_inline)) INLINE static void hydro_convert_quantities(
     struct part* p) {
 
-  p->entropy = (const_hydro_gamma - 1.f) * p->entropy *
-               powf(p->rho, -(const_hydro_gamma - 1.f));
+  p->entropy =
+      hydro_gamma_minus_one * p->entropy * pow_minus_gamma_minus_one(p->rho);
 }
 
 /**
@@ -247,6 +247,7 @@ __attribute__((always_inline)) INLINE static float hydro_get_internal_energy(
 
   const float entropy = p->entropy + p->entropy_dt * dt;
 
-  return entropy * powf(p->rho, const_hydro_gamma - 1.f) *
-         (1.f / (const_hydro_gamma - 1.f));
+  return entropy * powf(p->rho, hydro_gamma - 1.f) *
+         (1.f / (hydro_gamma - 1.f));
+  return 1;
 }
diff --git a/src/units.c b/src/units.c
index 8e0ff08f1d..ca75fc7ee6 100644
--- a/src/units.c
+++ b/src/units.c
@@ -39,6 +39,7 @@
 /* Includes. */
 #include "const.h"
 #include "error.h"
+#include "gamma.h"
 
 /**
  * @brief Initialises the UnitSystem structure with the constants given in
@@ -188,14 +189,14 @@ void units_get_base_unit_exponants_array(float baseUnitsExp[5],
       break;
 
     case UNIT_CONV_ENTROPY:
-      baseUnitsExp[UNIT_MASS] = 1.f - const_hydro_gamma;
-      baseUnitsExp[UNIT_LENGTH] = 3.f * const_hydro_gamma - 1.f;
+      baseUnitsExp[UNIT_MASS] = 1.f - hydro_gamma;
+      baseUnitsExp[UNIT_LENGTH] = 3.f * hydro_gamma - 1.f;
       baseUnitsExp[UNIT_TIME] = -2.f;
       break;
 
     case UNIT_CONV_ENTROPY_PER_UNIT_MASS:
-      baseUnitsExp[UNIT_MASS] = -const_hydro_gamma;
-      baseUnitsExp[UNIT_LENGTH] = 3.f * const_hydro_gamma - 1.f;
+      baseUnitsExp[UNIT_MASS] = -hydro_gamma;
+      baseUnitsExp[UNIT_LENGTH] = 3.f * hydro_gamma - 1.f;
       baseUnitsExp[UNIT_TIME] = -2.f;
       break;
 
-- 
GitLab