From 13bd7b92f2a02c9e42a474be0a65b7cdd2bf38fd Mon Sep 17 00:00:00 2001
From: lhausamm <loic_hausammann@hotmail.com>
Date: Mon, 26 Mar 2018 09:29:53 +0200
Subject: [PATCH] Remove Omega in grackle and add metallicity to gear chemistry

---
 examples/parameter_example.yml   |   1 -
 src/chemistry/gear/chemistry.h   |  14 +++
 src/cooling/grackle/cooling.h    | 155 ++++++++++++++-----------------
 src/cooling/grackle/cooling_io.h |   2 -
 4 files changed, 86 insertions(+), 86 deletions(-)

diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml
index b9d7faeab0..8a42ef773d 100644
--- a/examples/parameter_example.yml
+++ b/examples/parameter_example.yml
@@ -191,7 +191,6 @@ GrackleCooling:
   OutputMode: 0 # (optional) Write in output corresponding primordial chemistry mode
   MaxSteps: 10000 # (optional) Max number of step when computing the initial composition
   ConvergenceLimit: 1e-2 # (optional) Convergence threshold (relative) for initial composition
-  Omega: 0.8 # (optional) Over relaxation coefficient for initial composition (< 1 avoid oscillation, > 1 speedup convergence)
 
 # Parameters related to chemistry models  -----------------------------------------------
 
diff --git a/src/chemistry/gear/chemistry.h b/src/chemistry/gear/chemistry.h
index 8ccb29fa5e..a73125e0a1 100644
--- a/src/chemistry/gear/chemistry.h
+++ b/src/chemistry/gear/chemistry.h
@@ -51,6 +51,18 @@ chemistry_get_element_name(enum chemistry_element elem) {
   return chemistry_element_names[elem];
 }
 
+/**
+ * @brief Compute the metal mass fraction
+ *
+ * @param p Pointer to the particle data.
+ * @param xp Pointer to the extended particle data.
+ * @param data The global chemistry information.
+ */
+__attribute__((always_inline)) INLINE static float chemistry_metal_mass_fraction(
+    const struct part* restrict p, const struct xpart* restrict xp) {
+  return p->chemistry_data.Z;  
+}
+
 /**
  * @brief Initialises the chemistry properties.
  *
@@ -145,6 +157,8 @@ __attribute__((always_inline)) INLINE static void chemistry_end_density(
 __attribute__((always_inline)) INLINE static void chemistry_first_init_part(
     struct part* restrict p, struct xpart* restrict xp,
     const struct chemistry_global_data* data) {
+
+  p->chemistry_data.Z = data->initial_metallicity;
   chemistry_init_part(p, data);
 }
 
diff --git a/src/cooling/grackle/cooling.h b/src/cooling/grackle/cooling.h
index 8a337c60e3..6fb7c41cc1 100644
--- a/src/cooling/grackle/cooling.h
+++ b/src/cooling/grackle/cooling.h
@@ -31,6 +31,7 @@
 
 /* Local includes. */
 #include "../config.h"
+#include "chemistry.h"
 #include "cooling_io.h"
 #include "error.h"
 #include "hydro.h"
@@ -61,7 +62,7 @@ static double cooling_rate(
  * @param xp The #xpart to print
  */
 __attribute__((always_inline)) INLINE static void cooling_print_fractions(
-    struct xpart* restrict xp) {
+    const struct xpart* restrict xp) {
 
   const struct cooling_xpart_data tmp = xp->cooling_data;
 #if COOLING_GRACKLE_MODE > 0
@@ -82,100 +83,80 @@ __attribute__((always_inline)) INLINE static void cooling_print_fractions(
   message("Metal: %g", tmp.metal_frac);
 }
 
+#define cooling_check(old, new, limit, print, step, field, field_name)	\
+  ({									\
+    float err = fabsf((old->field - new->field) / new->field);		\
+    if (err > limit)							\
+      {									\
+	if (print == 1)							\
+	  {								\
+	    char *msg = "Step: %5i, Element %5s need to converge: %e";	\
+	    printf(msg, step, field_name, err);				\
+	  }								\
+	else if (print == 2)						\
+	  {								\
+	    char *msg = "\rStep: %5i, Element %5s need to converge: %e"; \
+	    printf(msg, step, field_name, err);				\
+	  }								\
+	return 0;							\
+      }									\
+  })
+  
 /**
  * @brief Check if the equilibrium as been reached
  *
  * @param old Previous step particle
  * @param xp Current step particle
+ * @param limit Convergence limit
+ * @param print Print message
+ * @param step Current step
  *
  * @return Value of the test
  */
 __attribute__((always_inline)) INLINE static int cooling_check_convergence(
     const struct xpart* restrict old, const struct xpart* restrict xp,
-    const float limit) {
+    const float limit, const int print, const int step) {
+
 
 #if COOLING_GRACKLE_MODE > 0
   const struct cooling_xpart_data *old_data = &old->cooling_data;
   const struct cooling_xpart_data *new_data = &xp->cooling_data;
 
-  if (fabsf((old_data->HI_frac - new_data->HI_frac) / new_data->HI_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HI_frac, "HI");
 
-  if (fabsf((old_data->HII_frac - new_data->HII_frac) / new_data->HII_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HII_frac, "HII");
   
-  if (fabsf((old_data->HeI_frac - new_data->HeI_frac) / new_data->HeI_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HeI_frac, "HeI");
 
-  if (fabsf((old_data->HeII_frac - new_data->HeII_frac) / new_data->HeII_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HeII_frac, "HeII");
 
-  if (fabsf((old_data->HeIII_frac - new_data->HeIII_frac) / new_data->HeIII_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HeIII_frac, "HeIII");
 
-  if (fabsf((old_data->e_frac - new_data->e_frac) / new_data->e_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, e_frac, "e");
 
 #endif // COOLING_GRACKLE_MODE > 0
   
 #if COOLING_GRACKLE_MODE > 1
 
-  if (fabsf((old_data->HM_frac - new_data->HM_frac) / new_data->HM_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, HM_frac, "HM");
 
-  if (fabsf((old_data->H2I_frac - new_data->H2I_frac) / new_data->H2I_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, H2I_frac, "H2I");
 
-  if (fabsf((old_data->H2II_frac - new_data->H2II_frac) / new_data->H2II_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, H2II_frac, "H2II");
 
 #endif // COOLING_GRACKLE_MODE > 1
   
 #if COOLING_GRACKLE_MODE > 2
 
-  if (fabsf((old_data->DI_frac - new_data->DI_frac) / new_data->DI_frac) > limit)
-    return 0;
-  if (fabsf((old_data->DII_frac - new_data->DII_frac) / new_data->DII_frac) > limit)
-    return 0;
-  if (fabsf((old_data->HDI_frac - new_data->HDI_frac) / new_data->HDI_frac) > limit)
-    return 0;
+  cooling_check(old_data, new_data, limit, print, step, DI_frac, "DI");
 
-#endif // COOLING_GRACKLE_MODE > 2
+  cooling_check(old_data, new_data, limit, print, step, DII_frac, "DII");
 
-  return 1;
-}
+  cooling_check(old_data, new_data, limit, print, step, HDI_frac, "HDI");
 
-__attribute__((always_inline)) INLINE static void cooling_over_relaxation(
-    struct xpart* restrict xp, const struct xpart* restrict xp_1, const float coeff) {
-
-#if COOLING_GRACKLE_MODE > 0
-  struct cooling_xpart_data data = xp->cooling_data;
-  const struct cooling_xpart_data data_1 = xp_1->cooling_data;
-
-  data.HI_frac    = data.HI_frac    * coeff + data_1.HI_frac    * (1. - coeff);
-  data.HII_frac   = data.HII_frac   * coeff + data_1.HII_frac   * (1. - coeff);
-  data.HeI_frac   = data.HeI_frac   * coeff + data_1.HeI_frac   * (1. - coeff);
-  data.HeII_frac  = data.HeII_frac  * coeff + data_1.HeII_frac  * (1. - coeff);
-  data.HeIII_frac = data.HeIII_frac * coeff + data_1.HeIII_frac * (1. - coeff);
-  data.e_frac     = data.e_frac     * coeff + data_1.e_frac     * (1. - coeff);
-
-#endif // COOLING_GRACKLE_MODE > 0
-
-#if COOLING_GRACKLE_MODE > 1
-
-  data.HM_frac    = data.HM_frac  * coeff + data_1.HM_frac   * (1. - coeff);
-  data.H2I_frac   = data.H2I_frac * coeff + data_1.H2I_frac  * (1. - coeff);
-  data.H2II_frac = data.H2II_frac * coeff + data_1.H2II_frac * (1. - coeff);
-
-#endif
-
-#if COOLING_GRACKLE_MODE > 2
-
-  data.DI_frac  = data.DI_frac  * coeff + data_1.DI_frac  * (1. - coeff);
-  data.DII_frac = data.DII_frac * coeff + data_1.DII_frac * (1. - coeff);
-  data.HDI_frac = data.HDI_frac * coeff + data_1.HDI_frac * (1. - coeff);
+#endif // COOLING_GRACKLE_MODE > 2
 
-#endif
+  return 1;
 }
 
 /**
@@ -187,46 +168,56 @@ __attribute__((always_inline)) INLINE static void cooling_over_relaxation(
  */
 __attribute__((always_inline)) INLINE static void cooling_compute_equilibrium_fractions(
     const struct cooling_function_data* restrict cooling,
-    const struct part* restrict p, struct xpart* restrict xp) {
+    const struct part* restrict p, struct xpart* restrict xp,
+    const int restart) {
 
   struct cooling_function_data tmp_cooling = *cooling;
+  /* disable energy updates */
+  tmp_cooling.chemistry.with_radiative_cooling = 0;
 
 #if COOLING_GRACKLE_MODE == 0
   error("This function should not be called in primordial chemistry = 0");
 #endif
 
+  /* a few constants */
+  const float limit = tmp_cooling.convergence_limit;
+  double dt = 0.1 * fabs(cooling_time(&tmp_cooling, p, xp));
+
   /* define a few variables */
   struct xpart xp_1 = *xp;
   int step = 0;
+  int print = 0;
 
-  /* a few constants */
-  const float limit = tmp_cooling.convergence_limit;
-  const double dt = 0.01 * fabs(cooling_time(&tmp_cooling, p, xp));
   
-  /* disable energy updates */
-  tmp_cooling.chemistry.with_radiative_cooling = 0;
-
+ 
   /* compute equilibrium fractions */
   do {
     /* update data */
     step += 1;
     xp_1 = *xp;
 
+#ifdef SWIFT_DEBUG_CHECKS
+    /* update type printing */
+    if (step > 0)
+      print = 2; // clear line 
+    else if (step > 1)
+      print = 1; // end line
+#endif
+
     /* compute cooling rate */
     cooling_rate(NULL, NULL, &tmp_cooling, p, xp, dt);
 
-    cooling_over_relaxation(xp, &xp_1, cooling->omega);
-
-  } while(!cooling_check_convergence(&xp_1, xp, limit) &&
-	  step < tmp_cooling.max_step);
+  } while(!cooling_check_convergence(&xp_1, xp, limit, print, step) &&
+      step < tmp_cooling.max_step);
 
+  if (print > 0)
+    printf("\n");
   /* check if converged */
   if (step >= cooling->max_step) {
-    error("A particle failed to reach equilibrium. "
-  	  "You can change GrackleCooling:MaxStep or "
-  	  "GrackleCooling:ConvergenceLimit to avoid this problem");
+    message("WARNING: A particle failed to reach equilibrium. "
+	    "You can change GrackleCooling:MaxStep or "
+	    "GrackleCooling:ConvergenceLimit to avoid this problem");
   }
-
 }
 
 /**
@@ -243,9 +234,6 @@ __attribute__((always_inline)) INLINE static void cooling_first_init_part(
 
   xp->cooling_data.radiated_energy = 0.f;
 
-  /* metal cooling = 1 */
-  xp->cooling_data.metal_frac = cooling->chemistry.SolarMetalFractionByMass;
-
 #if COOLING_GRACKLE_MODE >= 1
   gr_float zero = 1.e-20;
 
@@ -275,10 +263,9 @@ __attribute__((always_inline)) INLINE static void cooling_first_init_part(
   xp->cooling_data.HDI_frac = zero;
 #endif  // MODE >= 3
 
-
 #if COOLING_GRACKLE_MODE > 0
   /* compute equilibrium */
-  cooling_compute_equilibrium_fractions(cooling, p, xp);
+  cooling_compute_equilibrium_fractions(cooling, p, xp, 0);
 #endif
 
 }
@@ -417,7 +404,8 @@ __attribute__((always_inline)) INLINE static void cooling_free_data(
  * @param xp the #xpart
  */
 __attribute__((always_inline)) INLINE static void cooling_copy_to_data(
-    grackle_field_data* data, const struct xpart* xp, const gr_float rho) {
+    grackle_field_data* data, const struct part* p,
+    const struct xpart* xp, const gr_float rho) {
 
 #if COOLING_GRACKLE_MODE >= 1
   /* primordial chemistry >= 1 */
@@ -444,7 +432,8 @@ __attribute__((always_inline)) INLINE static void cooling_copy_to_data(
 #endif  // MODE >= 3
 
   /* metal cooling = 1 */
-  data->metal_density[0] = xp->cooling_data.metal_frac * rho;
+  const float Z = chemistry_metal_mass_fraction(p, xp);
+  data->metal_density[0] = Z * rho;
 
   /* volumetric heating rate */
   data->volumetric_heating_rate = NULL;
@@ -556,7 +545,7 @@ __attribute__((always_inline)) INLINE static double cooling_rate(
   cooling_malloc_data(&data);
 
   /* copy data from particle to grackle data */
-  cooling_copy_to_data(&data, xp, density);
+  cooling_copy_to_data(&data, p, xp, density);
 
   /* solve chemistry with table */
   if (solve_chemistry(&units, &data, dt) == 0) {
@@ -627,7 +616,7 @@ __attribute__((always_inline)) INLINE static gr_float cooling_time(
   cooling_malloc_data(&data);
 
   /* copy data from particle to grackle data */
-  cooling_copy_to_data(&data, xp, density);
+  cooling_copy_to_data(&data, p, xp, density);
 
   /* Compute cooling time */
   gr_float cooling_time;
diff --git a/src/cooling/grackle/cooling_io.h b/src/cooling/grackle/cooling_io.h
index 3bdf0cfd79..44e2c19213 100644
--- a/src/cooling/grackle/cooling_io.h
+++ b/src/cooling/grackle/cooling_io.h
@@ -156,8 +156,6 @@ __attribute__((always_inline)) INLINE static void cooling_read_parameters(
   cooling->convergence_limit =
     parser_get_opt_param_double(parameter_file, "GrackleCooling:ConvergenceLimit", 1e-2);
 
-  cooling->omega =
-    parser_get_opt_param_double(parameter_file, "GrackleCooling:Omega", 0.8);
 }
 
 
-- 
GitLab