From 7da1281703d43f0c5d83d8a7ec98a9ebb155f840 Mon Sep 17 00:00:00 2001
From: Matthieu Schaller <schaller@strw.leidenuniv.nl>
Date: Tue, 13 Aug 2019 23:13:32 +0200
Subject: [PATCH] Backported the new interface to the chemistry from the
 COLIBRE fork.

---
 src/chemistry/EAGLE/chemistry.h           | 105 +++++++++++++++++++++-
 src/cooling/EAGLE/cooling.c               |  16 ++--
 src/cooling/EAGLE/cooling_rates.h         |  70 +++++++--------
 src/cooling/EAGLE/newton_cooling.c        |   5 +-
 src/feedback/EAGLE/feedback.c             |  24 ++---
 src/star_formation/EAGLE/star_formation.h |  12 ++-
 6 files changed, 169 insertions(+), 63 deletions(-)

diff --git a/src/chemistry/EAGLE/chemistry.h b/src/chemistry/EAGLE/chemistry.h
index a04d7f94e7..c06b29f441 100644
--- a/src/chemistry/EAGLE/chemistry.h
+++ b/src/chemistry/EAGLE/chemistry.h
@@ -170,9 +170,10 @@ __attribute__((always_inline)) INLINE static void chemistry_first_init_part(
     p->chemistry_data.metal_mass_fraction_total =
         data->initial_metal_mass_fraction_total;
 
-    for (int elem = 0; elem < chemistry_element_count; ++elem)
+    for (int elem = 0; elem < chemistry_element_count; ++elem) {
       p->chemistry_data.metal_mass_fraction[elem] =
           data->initial_metal_mass_fraction[elem];
+    }
   }
   chemistry_init_part(p, data);
 }
@@ -241,4 +242,106 @@ static INLINE void chemistry_print_backend(
           chemistry_element_count);
 }
 
+/**
+ * @brief Updates the metal mass fractions after diffusion at the end of the
+ * force loop.
+ *
+ * @param p The particle to act upon.
+ * @param cosmo The current cosmological model.
+ */
+__attribute__((always_inline)) INLINE static void chemistry_end_force(
+    struct part* restrict p, const struct cosmology* cosmo) {}
+
+/**
+ * @brief Computes the chemistry-related time-step constraint.
+ *
+ * @param phys_const The physical constants in internal units.
+ * @param cosmo The current cosmological model.
+ * @param us The internal system of units.
+ * @param hydro_props The properties of the hydro scheme.
+ * @param p Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float chemistry_timestep(
+    const struct phys_const* restrict phys_const,
+    const struct cosmology* restrict cosmo,
+    const struct unit_system* restrict us,
+    const struct hydro_props* hydro_props,
+    const struct chemistry_global_data* cd, const struct part* restrict p) {
+  return FLT_MAX;
+}
+
+/**
+ * @brief Returns the total metallicity (metal mass fraction) of the
+ * star particle to be used in feedback/enrichment related routines.
+ *
+ * EAGLE uses smooth abundances for everything.
+ *
+ * @param sp Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float
+chemistry_get_total_metal_mass_fraction_for_feedback(
+    const struct spart* restrict sp) {
+
+  return sp->chemistry_data.smoothed_metal_mass_fraction_total;
+}
+
+/**
+ * @brief Returns the total metallicity (metal mass fraction) of the
+ * gas particle to be used in cooling related routines.
+ *
+ * EAGLE uses smooth abundances for everything.
+ *
+ * @param p Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float
+chemistry_get_total_metal_mass_fraction_for_cooling(
+    const struct part* restrict p) {
+
+  return p->chemistry_data.smoothed_metal_mass_fraction_total;
+}
+
+/**
+ * @brief Returns the abundance array (metal mass fractions) of the
+ * gas particle to be used in cooling related routines.
+ *
+ * EAGLE uses smooth abundances for everything.
+ *
+ * @param p Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float const*
+chemistry_get_metal_mass_fraction_for_cooling(const struct part* restrict p) {
+
+  return p->chemistry_data.smoothed_metal_mass_fraction;
+}
+
+/**
+ * @brief Returns the total metallicity (metal mass fraction) of the
+ * gas particle to be used in star formation related routines.
+ *
+ * EAGLE uses smooth abundances for everything.
+ *
+ * @param p Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float
+chemistry_get_total_metal_mass_fraction_for_star_formation(
+    const struct part* restrict p) {
+
+  return p->chemistry_data.smoothed_metal_mass_fraction_total;
+}
+
+/**
+ * @brief Returns the abundance array (metal mass fractions) of the
+ * gas particle to be used in star formation related routines.
+ *
+ * EAGLE uses smooth abundances for everything.
+ *
+ * @param p Pointer to the particle data.
+ */
+__attribute__((always_inline)) INLINE static float const*
+chemistry_get_metal_mass_fraction_for_star_formation(
+    const struct part* restrict p) {
+
+  return p->chemistry_data.smoothed_metal_mass_fraction;
+}
+
 #endif /* SWIFT_CHEMISTRY_EAGLE_H */
diff --git a/src/cooling/EAGLE/cooling.c b/src/cooling/EAGLE/cooling.c
index 674631ae52..c5595ef514 100644
--- a/src/cooling/EAGLE/cooling.c
+++ b/src/cooling/EAGLE/cooling.c
@@ -423,10 +423,10 @@ void cooling_cool_part(const struct phys_const *phys_const,
   abundance_ratio_to_solar(p, cooling, abundance_ratio);
 
   /* Get the Hydrogen and Helium mass fractions */
-  const float XH =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_H];
-  const float XHe =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_He];
+  const float *const metal_fraction =
+      chemistry_get_metal_mass_fraction_for_cooling(p);
+  const float XH = metal_fraction[chemistry_element_H];
+  const float XHe = metal_fraction[chemistry_element_He];
 
   /* Get the Helium mass fraction. Note that this is He / (H + He), i.e. a
    * metal-free Helium mass fraction as per the Wiersma+08 definition */
@@ -600,10 +600,10 @@ float cooling_get_temperature(
   const double u_cgs = u * cooling->internal_energy_to_cgs;
 
   /* Get the Hydrogen and Helium mass fractions */
-  const float XH =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_H];
-  const float XHe =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_He];
+  const float *const metal_fraction =
+      chemistry_get_metal_mass_fraction_for_cooling(p);
+  const float XH = metal_fraction[chemistry_element_H];
+  const float XHe = metal_fraction[chemistry_element_He];
 
   /* Get the Helium mass fraction. Note that this is He / (H + He), i.e. a
    * metal-free Helium mass fraction as per the Wiersma+08 definition */
diff --git a/src/cooling/EAGLE/cooling_rates.h b/src/cooling/EAGLE/cooling_rates.h
index bf908c3a7c..39978c9bfa 100644
--- a/src/cooling/EAGLE/cooling_rates.h
+++ b/src/cooling/EAGLE/cooling_rates.h
@@ -43,61 +43,57 @@
  * We also re-order the elements such that they match the order of the
  * tables. This is [H, He, C, N, O, Ne, Mg, Si, S, Ca, Fe].
  *
+ * The solar abundances table (from the cooling struct) is arranged as
+ * [H, He, C, N, O, Ne, Mg, Si, S, Ca, Fe].
+ *
  * @param p Pointer to #part struct.
  * @param cooling #cooling_function_data struct.
  * @param ratio_solar (return) Array of ratios to solar abundances.
  */
-__attribute__((always_inline)) INLINE void abundance_ratio_to_solar(
+__attribute__((always_inline)) INLINE static void abundance_ratio_to_solar(
     const struct part *p, const struct cooling_function_data *cooling,
     float ratio_solar[eagle_cooling_N_abundances]) {
 
-  ratio_solar[0] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_H] *
-      cooling->SolarAbundances_inv[0 /* H */];
+  /* Get the individual metal mass fractions from the particle */
+  const float *const metal_fraction =
+      chemistry_get_metal_mass_fraction_for_cooling(p);
+
+  ratio_solar[0] = metal_fraction[chemistry_element_H] *
+                   cooling->SolarAbundances_inv[0 /* H */];
 
-  ratio_solar[1] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_He] *
-      cooling->SolarAbundances_inv[1 /* He */];
+  ratio_solar[1] = metal_fraction[chemistry_element_He] *
+                   cooling->SolarAbundances_inv[1 /* He */];
 
-  ratio_solar[2] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_C] *
-      cooling->SolarAbundances_inv[2 /* C */];
+  ratio_solar[2] = metal_fraction[chemistry_element_C] *
+                   cooling->SolarAbundances_inv[2 /* C */];
 
-  ratio_solar[3] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_N] *
-      cooling->SolarAbundances_inv[3 /* N */];
+  ratio_solar[3] = metal_fraction[chemistry_element_N] *
+                   cooling->SolarAbundances_inv[3 /* N */];
 
-  ratio_solar[4] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_O] *
-      cooling->SolarAbundances_inv[4 /* O */];
+  ratio_solar[4] = metal_fraction[chemistry_element_O] *
+                   cooling->SolarAbundances_inv[4 /* O */];
 
-  ratio_solar[5] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Ne] *
-      cooling->SolarAbundances_inv[5 /* Ne */];
+  ratio_solar[5] = metal_fraction[chemistry_element_Ne] *
+                   cooling->SolarAbundances_inv[5 /* Ne */];
 
-  ratio_solar[6] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Mg] *
-      cooling->SolarAbundances_inv[6 /* Mg */];
+  ratio_solar[6] = metal_fraction[chemistry_element_Mg] *
+                   cooling->SolarAbundances_inv[6 /* Mg */];
 
-  ratio_solar[7] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Si] *
-      cooling->SolarAbundances_inv[7 /* Si */];
+  ratio_solar[7] = metal_fraction[chemistry_element_Si] *
+                   cooling->SolarAbundances_inv[7 /* Si */];
 
   /* For S, we use the same ratio as Si */
-  ratio_solar[8] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Si] *
-      cooling->SolarAbundances_inv[7 /* Si */] *
-      cooling->S_over_Si_ratio_in_solar;
+  ratio_solar[8] = metal_fraction[chemistry_element_Si] *
+                   cooling->SolarAbundances_inv[7 /* Si */] *
+                   cooling->S_over_Si_ratio_in_solar;
 
   /* For Ca, we use the same ratio as Si */
-  ratio_solar[9] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Si] *
-      cooling->SolarAbundances_inv[7 /* Si */] *
-      cooling->Ca_over_Si_ratio_in_solar;
-
-  ratio_solar[10] =
-      p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_Fe] *
-      cooling->SolarAbundances_inv[10 /* Fe */];
+  ratio_solar[9] = metal_fraction[chemistry_element_Si] *
+                   cooling->SolarAbundances_inv[7 /* Si */] *
+                   cooling->Ca_over_Si_ratio_in_solar;
+
+  ratio_solar[10] = metal_fraction[chemistry_element_Fe] *
+                    cooling->SolarAbundances_inv[10 /* Fe */];
 }
 
 /**
diff --git a/src/cooling/EAGLE/newton_cooling.c b/src/cooling/EAGLE/newton_cooling.c
index e86ebb7a2f..50af3294c3 100644
--- a/src/cooling/EAGLE/newton_cooling.c
+++ b/src/cooling/EAGLE/newton_cooling.c
@@ -621,8 +621,9 @@ INLINE static double eagle_metal_cooling_rate(
     const float log_table_bound_low = (cooling->Therm[0] + 0.05) / M_LOG10E;
 
     /* convert Hydrogen mass fraction in Hydrogen number density */
-    const float XH =
-        p->chemistry_data.smoothed_metal_mass_fraction[chemistry_element_H];
+    float const *metal_fraction =
+        chemistry_get_metal_mass_fraction_for_cooling(p);
+    const float XH = metal_fraction[chemistry_element_H];
     const double n_H = hydro_get_physical_density(p, cosmo) * XH /
                        phys_const->const_proton_mass;
     const double n_H_cgs = n_H * cooling->number_density_to_cgs;
diff --git a/src/feedback/EAGLE/feedback.c b/src/feedback/EAGLE/feedback.c
index cf6848760f..69f92fe992 100644
--- a/src/feedback/EAGLE/feedback.c
+++ b/src/feedback/EAGLE/feedback.c
@@ -105,15 +105,15 @@ double eagle_feedback_energy_fraction(const struct spart* sp,
 
   /* Star properties */
 
-  /* Smoothed metallicity (metal mass fraction) at birth time of the star */
-  const double Z_smooth = sp->chemistry_data.smoothed_metal_mass_fraction_total;
+  /* Metallicity (metal mass fraction) at birth time of the star */
+  const double Z = chemistry_get_total_metal_mass_fraction_for_feedback(sp);
 
   /* Physical density of the gas at the star's birth time */
   const double rho_birth = sp->birth_density;
   const double n_birth = rho_birth * props->rho_to_n_cgs;
 
   /* Calculate f_E */
-  const double Z_term = pow(max(Z_smooth, 1e-6) / Z_0, n_Z);
+  const double Z_term = pow(max(Z, 1e-6) / Z_0, n_Z);
   const double n_term = pow(n_birth / n_0, -n_n);
   const double denonimator = 1. + Z_term * n_term;
 
@@ -333,7 +333,7 @@ INLINE static void evolve_SNIa(const float log10_min_mass,
    * and use updated values for the star's age and timestep in this function */
   if (log10_max_mass > props->log10_SNIa_max_mass_msun) {
 
-    const float Z = sp->chemistry_data.metal_mass_fraction_total;
+    const float Z = chemistry_get_total_metal_mass_fraction_for_feedback(sp);
     const float max_mass = exp10f(props->log10_SNIa_max_mass_msun);
     const float lifetime_Gyr = lifetime_in_Gyr(max_mass, Z, props);
 
@@ -401,6 +401,9 @@ INLINE static void evolve_SNII(float log10_min_mass, float log10_max_mass,
 
   int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index;
 
+  /* Metallicity (metal mass fraction) at birth time of the star */
+  const double Z = chemistry_get_total_metal_mass_fraction_for_feedback(sp);
+
   /* If mass at beginning of step is less than tabulated lower bound for IMF,
    * limit it.*/
   if (log10_min_mass < props->log10_SNII_min_mass_msun)
@@ -423,9 +426,7 @@ INLINE static void evolve_SNII(float log10_min_mass, float log10_max_mass,
   int iz_low = 0, iz_high = 0, low_index_3d, high_index_3d, low_index_2d,
       high_index_2d;
   float dz = 0.;
-  determine_bin_yield_SNII(&iz_low, &iz_high, &dz,
-                           log10(sp->chemistry_data.metal_mass_fraction_total),
-                           props);
+  determine_bin_yield_SNII(&iz_low, &iz_high, &dz, log10(Z), props);
 
   /* compute metals produced */
   float metal_mass_released[chemistry_element_count], metal_mass_released_total;
@@ -557,6 +558,9 @@ INLINE static void evolve_AGB(const float log10_min_mass, float log10_max_mass,
 
   int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index;
 
+  /* Metallicity (metal mass fraction) at birth time of the star */
+  const double Z = chemistry_get_total_metal_mass_fraction_for_feedback(sp);
+
   /* If mass at end of step is greater than tabulated lower bound for IMF, limit
    * it.*/
   if (log10_max_mass > props->log10_SNII_min_mass_msun)
@@ -574,9 +578,7 @@ INLINE static void evolve_AGB(const float log10_min_mass, float log10_max_mass,
   int iz_low = 0, iz_high = 0, low_index_3d, high_index_3d, low_index_2d,
       high_index_2d;
   float dz = 0.f;
-  determine_bin_yield_AGB(&iz_low, &iz_high, &dz,
-                          log10(sp->chemistry_data.metal_mass_fraction_total),
-                          props);
+  determine_bin_yield_AGB(&iz_low, &iz_high, &dz, log10(Z), props);
 
   /* compute metals produced */
   float metal_mass_released[chemistry_element_count], metal_mass_released_total;
@@ -718,7 +720,7 @@ void compute_stellar_evolution(const struct feedback_props* feedback_props,
   const double star_age_Gyr = age * conversion_factor;
 
   /* Get the metallicity */
-  const float Z = sp->chemistry_data.metal_mass_fraction_total;
+  const float Z = chemistry_get_total_metal_mass_fraction_for_feedback(sp);
 
   /* Properties collected in the stellar density loop. */
   const float ngb_gas_mass = sp->feedback_data.to_collect.ngb_mass;
diff --git a/src/star_formation/EAGLE/star_formation.h b/src/star_formation/EAGLE/star_formation.h
index f2c77e0368..3533abcae6 100644
--- a/src/star_formation/EAGLE/star_formation.h
+++ b/src/star_formation/EAGLE/star_formation.h
@@ -232,8 +232,11 @@ INLINE static int star_formation_is_star_forming(
    * because we also need to check if the physical density exceeded
    * the appropriate limit */
 
-  const double Z = p->chemistry_data.smoothed_metal_mass_fraction_total;
-  const double X_H = p->chemistry_data.smoothed_metal_mass_fraction[0];
+  const double Z =
+      chemistry_get_total_metal_mass_fraction_for_star_formation(p);
+  const float* const metal_fraction =
+      chemistry_get_metal_mass_fraction_for_star_formation(p);
+  const double X_H = metal_fraction[chemistry_element_H];
   const double n_H = physical_density * X_H;
 
   /* Get the density threshold */
@@ -278,8 +281,9 @@ INLINE static void star_formation_compute_SFR(
   }
 
   /* Hydrogen number density of this particle */
-  const double physical_density = hydro_get_physical_density(p, cosmo);
-  const double X_H = p->chemistry_data.smoothed_metal_mass_fraction[0];
+  const float* const metal_fraction =
+      chemistry_get_metal_mass_fraction_for_star_formation(p);
+  const double X_H = metal_fraction[chemistry_element_H];
   const double n_H = physical_density * X_H / phys_const->const_proton_mass;
 
   /* Are we above the threshold for automatic star formation? */
-- 
GitLab