diff --git a/configure.ac b/configure.ac index 2a15c2190d68dfda1d517a98d77057d0741a669f..6dc5ffd28ee1a17197e42dce7c1b8451256025b5 100644 --- a/configure.ac +++ b/configure.ac @@ -1329,7 +1329,7 @@ case "$with_subgrid" in with_subgrid_entropy_floor=none with_subgrid_stars=GEAR with_subgrid_star_formation=GEAR - with_subgrid_feedback=thermal + with_subgrid_feedback=none ;; EAGLE) with_subgrid_cooling=EAGLE @@ -1338,7 +1338,7 @@ case "$with_subgrid" in with_subgrid_entropy_floor=EAGLE with_subgrid_stars=EAGLE with_subgrid_star_formation=EAGLE - with_subgrid_feedback=none + with_subgrid_feedback=EAGLE ;; *) AC_MSG_ERROR([Unknown subgrid choice: $with_subgrid]) @@ -1727,11 +1727,8 @@ case "$with_stars" in GEAR) AC_DEFINE([STARS_GEAR], [1], [GEAR stellar model]) ;; - EAGLE) - AC_DEFINE([STARS_EAGLE], [1], [EAGLE stellar model]) - ;; none) - AC_DEFINE([STARS_NONE], [1], [None stellar model]) + AC_DEFINE([STARS_NONE], [1], [Basic stellar model]) ;; *) @@ -1742,7 +1739,7 @@ esac # Feedback model AC_ARG_WITH([feedback], [AS_HELP_STRING([--with-feedback=<model>], - [Feedback model to use @<:@none, thermal, debug default: none@:>@] + [Feedback model to use @<:@none, EAGLE, debug default: none@:>@] )], [with_feedback="$withval"], [with_feedback="none"] @@ -1757,10 +1754,11 @@ if test "$with_subgrid" != "none"; then fi case "$with_feedback" in - thermal) - AC_DEFINE([FEEDBACK_THERMAL], [1], [Thermal Blastwave]) + EAGLE) + AC_DEFINE([FEEDBACK_EAGLE], [1], [EAGLE stellar feedback and evolution model]) ;; none) + AC_DEFINE([FEEDBACK_NONE], [1], [No feedback]) ;; *) @@ -1889,6 +1887,9 @@ AM_CONDITIONAL([HAVE_DOXYGEN], [test "$ac_cv_path_ac_pt_DX_DOXYGEN" != ""]) # Check if using EAGLE cooling AM_CONDITIONAL([HAVEEAGLECOOLING], [test $with_cooling = "EAGLE"]) +# Check if using EAGLE feedback +AM_CONDITIONAL([HAVEEAGLEFEEDBACK], [test $with_feedback = "EAGLE"]) + # Handle .in files. AC_CONFIG_FILES([Makefile src/Makefile examples/Makefile examples/Cooling/CoolingRates/Makefile doc/Makefile doc/Doxyfile tests/Makefile]) AC_CONFIG_FILES([argparse/Makefile tools/Makefile]) diff --git a/src/Makefile.am b/src/Makefile.am index d7e4249a7ff67132505e3a7df8a134d4cd8b266c..8509880970f9ccbef67ef141d63785590d7f51c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -59,6 +59,12 @@ if HAVEEAGLECOOLING EAGLE_COOLING_SOURCES += cooling/EAGLE/cooling.c cooling/EAGLE/cooling_tables.c endif +# source files for EAGLE feedback +EAGLE_FEEDBACK_SOURCES = +if HAVEEAGLEFEEDBACK +EAGLE_FEEDBACK_SOURCES += feedback/EAGLE/feedback.c +endif + # Common source files AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c engine_maketasks.c \ engine_marktasks.c engine_drift.c serial_io.c timers.c debug.c scheduler.c \ @@ -71,7 +77,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c engine_maketasks.c collectgroup.c hydro_space.c equation_of_state.c \ chemistry.c cosmology.c restart.c mesh_gravity.c velociraptor_interface.c \ outputlist.c velociraptor_dummy.c logger_io.c memuse.c \ - $(EAGLE_COOLING_SOURCES) + $(EAGLE_COOLING_SOURCES) $(EAGLE_FEEDBACK_SOURCES) # Include files for distribution, not installation. nobase_noinst_HEADERS = align.h approx_math.h atomic.h barrier.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \ diff --git a/src/feedback.h b/src/feedback.h new file mode 100644 index 0000000000000000000000000000000000000000..e4987f916822fd90affd27372a51b6f11cf73287 --- /dev/null +++ b/src/feedback.h @@ -0,0 +1,36 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Coypright (c) 2018 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_FEEDBACK_H +#define SWIFT_FEEDBACK_H + +/* Config parameters. */ +#include "../config.h" + +/* Select the correct feedback model */ +#if defined(FEEDBACK_NONE) +#include "./feedback/Default/feedback.h" +#include "./deedback/Default/feedback_iact.h" +#elif defined(FEEDBACK_EAGLE) +#include "./feedback/EAGLE/feedback.h" +#include "./feedback/EAGLE/feedback_iact.h" +#else +#error "Invalid choice of feedback model" +#endif + +#endif diff --git a/src/feedback/EAGLE/feedback.c b/src/feedback/EAGLE/feedback.c new file mode 100644 index 0000000000000000000000000000000000000000..0b4f99ed5b690cbda8fc0b84922716506b1fe6ba --- /dev/null +++ b/src/feedback/EAGLE/feedback.c @@ -0,0 +1,742 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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/>. + * + ******************************************************************************/ + + +#include "feedback.h" + +#include "hydro_properties.h" +#include "imf.h" +#include "interpolate.h" +#include "yield_tables.h" + +/** + * @brief determine which metallicity bin star belongs to for AGB, compute bin + * indices and offsets + * + * @param iz_low Pointer to index of metallicity bin to which the star belongs + * (to be calculated in this function) + * @param iz_high Pointer to index of metallicity bin to above the star's + * metallicity (to be calculated in this function) + * @param dz metallicity bin offset + * @param log10_metallicity log10 of star metallicity + * @param star_properties stars_props data structure + */ +inline static void determine_bin_yield_AGB( + int* iz_low, int* iz_high, float* dz, float log10_metallicity, + const struct feedback_props* feedback_props) { + + // MATTHIEU + + /* if (log10_metallicity > log10_min_metallicity) { */ + /* /\* Find metallicity bin which contains the star's metallicity *\/ */ + /* int j; */ + /* for (j = 0; j < star_properties->feedback.AGB_n_z - 1 && */ + /* log10_metallicity > */ + /* star_properties->feedback.yield_AGB.metallicity[j + 1]; */ + /* j++) */ + /* ; */ + /* *iz_low = j; */ + /* *iz_high = *iz_low + 1; */ + + /* /\* Compute offset *\/ */ + /* if (log10_metallicity >= */ + /* star_properties->feedback.yield_AGB.metallicity[0] && */ + /* log10_metallicity <= */ + /* star_properties->feedback.yield_AGB */ + /* .metallicity[star_properties->feedback.AGB_n_z - 1]) */ + /* *dz = log10_metallicity - */ + /* star_properties->feedback.yield_AGB.metallicity[*iz_low]; */ + /* else */ + /* *dz = 0; */ + + /* /\* Normalize offset *\/ */ + /* float deltaz = star_properties->feedback.yield_AGB.metallicity[*iz_high] - */ + /* star_properties->feedback.yield_AGB.metallicity[*iz_low]; */ + + /* if (deltaz > 0) */ + /* *dz /= deltaz; */ + /* else */ + /* dz = 0; */ + /* } else { */ + /* *iz_low = 0; */ + /* *iz_high = 0; */ + /* *dz = 0; */ + /* } */ +} + +/** + * @brief determine which metallicity bin star belongs to for SNII, compute bin + * indices and offsets + * + * @param iz_low Pointer to index of metallicity bin to which the star belongs + * (to be calculated in this function) + * @param iz_high Pointer to index of metallicity bin to above the star's + * metallicity (to be calculated in this function) + * @param dz metallicity bin offset + * @param log10_metallicity log10 of star metallicity + * @param star_properties stars_props data structure + */ +inline static void determine_bin_yield_SNII( + int* iz_low, int* iz_high, float* dz, float log10_metallicity, + const struct feedback_props* feedback_props) { + + // MATTHIEU + + /* if (log10_metallicity > log10_min_metallicity) { */ + /* /\* Find metallicity bin which contains the star's metallicity *\/ */ + /* int j; */ + /* for (j = 0; j < star_properties->feedback.SNII_n_z - 1 && */ + /* log10_metallicity > */ + /* star_properties->feedback.yield_SNII.metallicity[j + 1]; */ + /* j++) */ + /* ; */ + /* *iz_low = j; */ + /* *iz_high = *iz_low + 1; */ + + /* /\* Compute offset *\/ */ + /* if (log10_metallicity >= */ + /* star_properties->feedback.yield_SNII.metallicity[0] && */ + /* log10_metallicity <= */ + /* star_properties->feedback.yield_SNII */ + /* .metallicity[star_properties->feedback.SNII_n_z - 1]) */ + /* *dz = log10_metallicity - */ + /* star_properties->feedback.yield_SNII.metallicity[*iz_low]; */ + /* else */ + /* *dz = 0; */ + + /* /\* Normalize offset *\/ */ + /* float deltaz = star_properties->feedback.yield_SNII.metallicity[*iz_high] - */ + /* star_properties->feedback.yield_SNII.metallicity[*iz_low]; */ + + /* if (deltaz > 0) */ + /* *dz = *dz / deltaz; */ + /* else */ + /* dz = 0; */ + /* } else { */ + /* *iz_low = 0; */ + /* *iz_high = 0; */ + /* *dz = 0; */ + /* } */ +} + + +/** + * @brief compute enrichment and feedback due to SNIa. To do this compute the + * number of SNIa that occur during the timestep, multiply by constants read + * from tables. + * + * @param log10_min_mass log10 mass at the end of step + * @param log10_max_mass log10 mass at the beginning of step + * @param stars star properties data structure + * @param sp spart we are computing feedback from + * @param star_age_Gyr age of star in Gyr + * @param dt_Gyr timestep dt in Gyr + */ +inline static void evolve_SNIa(float log10_min_mass, float log10_max_mass, + const struct feedback_props* feedback_props, + struct spart* restrict sp, float star_age_Gyr, + float dt_Gyr) { + + /* Check if we're outside the mass range for SNIa */ + if (log10_min_mass >= feedback_props->log10_SNIa_max_mass_msun) return; + + /* If the max mass is outside the mass range update it to be the maximum and + * use updated values for the star's age and timestep in this function */ + if (log10_max_mass > feedback_props->log10_SNIa_max_mass_msun) { + log10_max_mass = feedback_props->log10_SNIa_max_mass_msun; + float lifetime_Gyr = + lifetime_in_Gyr(exp(M_LN10 * feedback_props->log10_SNIa_max_mass_msun), + sp->chemistry_data.metal_mass_fraction_total, feedback_props); + dt_Gyr = star_age_Gyr + dt_Gyr - lifetime_Gyr; + star_age_Gyr = lifetime_Gyr; + } + + /* compute the number of SNIa */ + /* Efolding (Forster 2006) */ + float num_SNIa_per_msun = + feedback_props->SNIa_efficiency * + (exp(-star_age_Gyr / feedback_props->SNIa_timescale_Gyr) - + exp(-(star_age_Gyr + dt_Gyr) / feedback_props->SNIa_timescale_Gyr)) * + sp->mass_init; + + sp->feedback_data.to_distribute.num_SNIa = + num_SNIa_per_msun / feedback_props->const_solar_mass; + + /* compute mass fractions of each metal */ + for (int i = 0; i < chemistry_element_count; i++) { + sp->feedback_data.to_distribute.metal_mass[i] += + num_SNIa_per_msun * feedback_props->yield_SNIa_IMF_resampled[i]; + } + + /* Update the metallicity of the material released */ + sp->feedback_data.to_distribute.metal_mass_from_SNIa += + num_SNIa_per_msun * feedback_props->yield_SNIa_total_metals_IMF_resampled; + + /* Update the metal mass produced */ + sp->feedback_data.to_distribute.total_metal_mass += + num_SNIa_per_msun * feedback_props->yield_SNIa_total_metals_IMF_resampled; + + /* Compute the mass produced by SNIa */ + sp->feedback_data.to_distribute.mass_from_SNIa += + num_SNIa_per_msun * feedback_props->yield_SNIa_total_metals_IMF_resampled; + + /* Compute the iron mass produced */ + sp->feedback_data.to_distribute.Fe_mass_from_SNIa += + num_SNIa_per_msun * + feedback_props->yield_SNIa_IMF_resampled[chemistry_element_Fe]; +} + +/** + * @brief compute enrichment and feedback due to SNII. To do this, integrate the + * IMF weighted by the yields read from tables for each of the quantities of + * interest. + * + * @param log10_min_mass log10 mass at the end of step + * @param log10_max_mass log10 mass at the beginning of step + * @param stellar_yields array to store calculated yields for passing to + * integrate_imf + * @param stars star properties data structure + * @param sp spart we are computing feedback from + */ +inline static void evolve_SNII(float log10_min_mass, float log10_max_mass, + float* stellar_yields, + const struct feedback_props* restrict feedback_props, + struct spart* restrict sp) { + int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index; + + /* If mass at beginning of step is less than tabulated lower bound for IMF, + * limit it.*/ + if (log10_min_mass < feedback_props->log10_SNII_min_mass_msun) + log10_min_mass = feedback_props->log10_SNII_min_mass_msun; + + /* If mass at end of step is greater than tabulated upper bound for IMF, limit + * it.*/ + if (log10_max_mass > feedback_props->log10_SNII_max_mass_msun) + log10_max_mass = feedback_props->log10_SNII_max_mass_msun; + + /* Don't do anything if the stellar mass hasn't decreased by the end of the + * step */ + if (log10_min_mass >= log10_max_mass) return; + + /* determine which IMF mass bins contribute to the integral */ + determine_imf_bins(log10_min_mass, log10_max_mass, &low_imf_mass_bin_index, + &high_imf_mass_bin_index, feedback_props); + + /* Integrate IMF to determine number of SNII */ + sp->feedback_data.to_distribute.num_SNII = + integrate_imf(log10_min_mass, log10_max_mass, 0, stellar_yields, feedback_props); + + /* determine which metallicity bin and offset this star belongs to */ + 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), + feedback_props); + + /* compute metals produced */ + float metal_mass_released[chemistry_element_count], metal_mass_released_total; + for (int elem = 0; elem < chemistry_element_count; elem++) { + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_3d = feedback_row_major_index_3d( + iz_low, elem, mass_bin_index, feedback_props->SNII_n_z, + chemistry_element_count, feedback_props->n_imf_mass_bins); + high_index_3d = feedback_row_major_index_3d( + iz_high, elem, mass_bin_index, feedback_props->SNII_n_z, + chemistry_element_count, feedback_props->n_imf_mass_bins); + low_index_2d = feedback_row_major_index_2d( + iz_low, mass_bin_index, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * + (feedback_props->yield_SNII.yield_IMF_resampled[low_index_3d] + + sp->chemistry_data.metal_mass_fraction[elem] * + feedback_props->yield_SNII + .ejecta_IMF_resampled[low_index_2d]) + + dz * (feedback_props->yield_SNII.yield_IMF_resampled[high_index_3d] + + sp->chemistry_data.metal_mass_fraction[elem] * + feedback_props->yield_SNII + .ejecta_IMF_resampled[high_index_2d]); + } + + metal_mass_released[elem] = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + } + + /* Compute mass produced */ + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, + feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * (feedback_props->yield_SNII + .total_metals_IMF_resampled[low_index_2d] + + sp->chemistry_data.metal_mass_fraction_total * + feedback_props->yield_SNII + .ejecta_IMF_resampled[low_index_2d]) + + dz * (feedback_props->yield_SNII + .total_metals_IMF_resampled[high_index_2d] + + sp->chemistry_data.metal_mass_fraction_total * + feedback_props->yield_SNII + .ejecta_IMF_resampled[high_index_2d]); + } + + metal_mass_released_total = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + + /* yield normalization */ + float mass_ejected, mass_released; + + /* zero all negative values */ + for (int i = 0; i < chemistry_element_count; i++) + metal_mass_released[i] = max(metal_mass_released[i], 0.f); + + metal_mass_released_total = max(metal_mass_released_total, 0.f); + + /* compute the total metal mass ejected from the star*/ + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, + feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * + feedback_props->yield_SNII.ejecta_IMF_resampled[low_index_2d] + + dz * feedback_props->yield_SNII.ejecta_IMF_resampled[high_index_2d]; + } + + mass_ejected = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + + /* compute the total mass released */ + mass_released = metal_mass_released_total + + metal_mass_released[chemistry_element_H] + + metal_mass_released[chemistry_element_He]; + + /* normalize the yields */ + if (mass_released > 0) { + /* Set normalisation factor. Note additional multiplication by the star + * initial mass as tables are per initial mass */ + const float norm_factor = sp->mass_init * mass_ejected / mass_released; + + for (int i = 0; i < chemistry_element_count; i++) { + sp->feedback_data.to_distribute.metal_mass[i] += metal_mass_released[i] * norm_factor; + } + for (int i = 0; i < chemistry_element_count; i++) { + sp->feedback_data.to_distribute.mass_from_SNII += sp->feedback_data.to_distribute.metal_mass[i]; + } + sp->feedback_data.to_distribute.total_metal_mass += + metal_mass_released_total * norm_factor; + sp->feedback_data.to_distribute.metal_mass_from_SNII += + metal_mass_released_total * norm_factor; + } else { + error("wrong normalization!!!! mass_released = %e\n", mass_released); + } +} + +/** + * @brief compute enrichment and feedback due to AGB. To do this, integrate the + * IMF weighted by the yields read from tables for each of the quantities of + * interest. + * + * @param log10_min_mass log10 mass at the end of step + * @param log10_max_mass log10 mass at the beginning of step + * @param stellar_yields array to store calculated yields for passing to + * integrate_imf + * @param feedback_props star properties data structure + * @param sp spart we are computing feedback from + */ +inline static void evolve_AGB(float log10_min_mass, float log10_max_mass, + float* stellar_yields, + const struct feedback_props* restrict feedback_props, + struct spart* restrict sp) { + int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index; + + /* If mass at end of step is greater than tabulated lower bound for IMF, limit + * it.*/ + if (log10_max_mass > feedback_props->log10_SNII_min_mass_msun) + log10_max_mass = feedback_props->log10_SNII_min_mass_msun; + + /* Don't do anything if the stellar mass hasn't decreased by the end of the + * step */ + if (log10_min_mass >= log10_max_mass) return; + + /* determine which IMF mass bins contribute to the integral */ + determine_imf_bins(log10_min_mass, log10_max_mass, &low_imf_mass_bin_index, + &high_imf_mass_bin_index, feedback_props); + + /* determine which metallicity bin and offset this star belongs to */ + 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), + feedback_props); + + /* compute metals produced */ + float metal_mass_released[chemistry_element_count], metal_mass_released_total; + for (int elem = 0; elem < chemistry_element_count; elem++) { + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_3d = feedback_row_major_index_3d( + iz_low, elem, mass_bin_index, feedback_props->AGB_n_z, + chemistry_element_count, feedback_props->n_imf_mass_bins); + high_index_3d = feedback_row_major_index_3d( + iz_high, elem, mass_bin_index, feedback_props->AGB_n_z, + chemistry_element_count, feedback_props->n_imf_mass_bins); + low_index_2d = feedback_row_major_index_2d( + iz_low, mass_bin_index, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * + (feedback_props->yield_AGB.yield_IMF_resampled[low_index_3d] + + sp->chemistry_data.metal_mass_fraction[elem] * + feedback_props->yield_AGB + .ejecta_IMF_resampled[low_index_2d]) + + dz * (feedback_props->yield_AGB.yield_IMF_resampled[high_index_3d] + + sp->chemistry_data.metal_mass_fraction[elem] * + feedback_props->yield_AGB + .ejecta_IMF_resampled[high_index_2d]); + } + + metal_mass_released[elem] = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + } + + /* Compute mass produced */ + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, + feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * + (feedback_props->yield_AGB + .total_metals_IMF_resampled[low_index_2d] + + sp->chemistry_data.metal_mass_fraction_total * + feedback_props->yield_AGB.ejecta_IMF_resampled[low_index_2d]) + + dz * + (feedback_props->yield_AGB + .total_metals_IMF_resampled[high_index_2d] + + sp->chemistry_data.metal_mass_fraction_total * + feedback_props->yield_AGB.ejecta_IMF_resampled[high_index_2d]); + } + + metal_mass_released_total = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + + /* yield normalization */ + float mass_ejected, mass_released; + + /* zero all negative values */ + for (int i = 0; i < chemistry_element_count; i++) + metal_mass_released[i] = max(metal_mass_released[i], 0.f); + + metal_mass_released_total = max(metal_mass_released_total, 0.f); + + /* compute the total metal mass ejected from the star */ + for (mass_bin_index = low_imf_mass_bin_index; + mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { + low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, + feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + high_index_2d = feedback_row_major_index_2d( + iz_high, mass_bin_index, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + stellar_yields[mass_bin_index] = + (1 - dz) * + feedback_props->yield_AGB.ejecta_IMF_resampled[low_index_2d] + + dz * feedback_props->yield_AGB.ejecta_IMF_resampled[high_index_2d]; + } + + mass_ejected = + integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, feedback_props); + + /* compute the total mass released */ + mass_released = metal_mass_released_total + + metal_mass_released[chemistry_element_H] + + metal_mass_released[chemistry_element_He]; + + /* normalize the yields */ + if (mass_released > 0) { + /* Set normalisation factor. Note additional multiplication by the stellar + * initial mass as tables are per initial mass */ + const float norm_factor = sp->mass_init * mass_ejected / mass_released; + + for (int i = 0; i < chemistry_element_count; i++) { + sp->feedback_data.to_distribute.metal_mass[i] += metal_mass_released[i] * norm_factor; + sp->feedback_data.to_distribute.mass_from_AGB += metal_mass_released[i] * norm_factor; + } + sp->feedback_data.to_distribute.total_metal_mass += + metal_mass_released_total * norm_factor; + sp->feedback_data.to_distribute.metal_mass_from_AGB += + metal_mass_released_total * norm_factor; + } else { + error("wrong normalization!!!! mass_released = %e\n", mass_released); + } +} + +/** + * @brief calculates stellar mass in spart that died over the timestep, calls + * functions to calculate feedback due to SNIa, SNII and AGB + * + * @param star_properties feedback_props_props data structure + * @param sp spart that we're evolving + * @param us unit_system data structure + * @param age age of spart at beginning of step + * @param dt length of current timestep + */ +void compute_stellar_evolution( + const struct feedback_props* feedback_props, + struct spart* sp, const struct unit_system* us, float age, + double dt) { + + /* Allocate temporary array for calculating imf weights */ + float* stellar_yields; + stellar_yields = + malloc(feedback_props->n_imf_mass_bins * sizeof(float)); + + /* Convert dt and stellar age from internal units to Gyr. */ + const double Gyr_in_cgs = 3.154e16; + double dt_Gyr = + dt * units_cgs_conversion_factor(us, UNIT_CONV_TIME) / Gyr_in_cgs; + double star_age_Gyr = + age * units_cgs_conversion_factor(us, UNIT_CONV_TIME) / Gyr_in_cgs; + + /* calculate mass of stars that has died from the star's birth up to the + * beginning and end of timestep */ + double log10_max_dying_mass_msun = log10(dying_mass_msun( + star_age_Gyr, sp->chemistry_data.metal_mass_fraction_total, + feedback_props)); + double log10_min_dying_mass_msun = log10(dying_mass_msun( + star_age_Gyr + dt_Gyr, sp->chemistry_data.metal_mass_fraction_total, + feedback_props)); + + /* Sanity check. Worth investigating if necessary as functions for evaluating + * mass of stars dying might be strictly decreasing. */ + if (log10_min_dying_mass_msun > log10_max_dying_mass_msun) + error("min dying mass is greater than max dying mass"); + + /* Integration interval is zero - this can happen if minimum and maximum + * dying masses are above imf_max_mass_msun. Return without doing any + * feedback. */ + if (log10_min_dying_mass_msun == log10_max_dying_mass_msun) return; + + /* Evolve SNIa, SNII, AGB */ + evolve_SNIa(log10_min_dying_mass_msun, log10_max_dying_mass_msun, + feedback_props, sp, star_age_Gyr, dt_Gyr); + evolve_SNII(log10_min_dying_mass_msun, log10_max_dying_mass_msun, + stellar_yields, feedback_props, sp); + evolve_AGB(log10_min_dying_mass_msun, log10_max_dying_mass_msun, + stellar_yields, feedback_props, sp); + + /* Compute the mass to distribute */ + sp->feedback_data.to_distribute.mass = sp->feedback_data.to_distribute.total_metal_mass + + sp->feedback_data.to_distribute.metal_mass[chemistry_element_H] + + sp->feedback_data.to_distribute.metal_mass[chemistry_element_He]; + + /* Clean up */ + free(stellar_yields); +} + +/** + * @brief Compute number of SN that should go off given the age of the spart + * + * @param sp spart we're evolving + * @param stars_properties stars_props data structure + * @param age age of star at the beginning of the step + * @param dt length of step + */ +float compute_SNe(struct spart* sp, + const struct feedback_props* feedback_props, + float age, double dt) { + + if (age <= feedback_props->SNII_wind_delay && + age + dt > feedback_props->SNII_wind_delay) { + + return feedback_props->num_SNII_per_msun * sp->mass_init / + feedback_props->const_solar_mass; + } else { + return 0; + } +} + + +/** + * @brief Initializes constants related to stellar evolution, initializes imf, + * reads and processes yield tables + * + * @param params swift_params parameters structure + * @param stars stars_props data structure + */ +inline static void stars_evolve_init(struct swift_params* params, + struct feedback_props* feedback_props) { + + /* Set number of elements found in yield tables */ + feedback_props->SNIa_n_elements = 42; + feedback_props->SNII_n_mass = 11; + feedback_props->SNII_n_elements = 11; + feedback_props->SNII_n_z = 5; + feedback_props->AGB_n_mass = 23; + feedback_props->AGB_n_elements = 11; + feedback_props->AGB_n_z = 3; + feedback_props->lifetimes.n_mass = 30; + feedback_props->lifetimes.n_z = 6; + feedback_props->element_name_length = 15; + + /* Set bounds for imf */ + feedback_props->log10_SNII_min_mass_msun = 0.77815125f; // log10(6). + feedback_props->log10_SNII_max_mass_msun = 2.f; // log10(100). + feedback_props->log10_SNIa_max_mass_msun = 0.90308999f; // log10(8). + + /* Yield table filepath */ + parser_get_param_string(params, "EAGLEFeedback:filename", + feedback_props->yield_table_path); + parser_get_param_string(params, "EAGLEFeedback:imf_model", + feedback_props->IMF_Model); + + /* Initialise IMF */ + init_imf(feedback_props); + + /* Allocate yield tables */ + allocate_yield_tables(feedback_props); + + /* Set factors for each element adjusting SNII yield */ + feedback_props->typeII_factor[0] = 1.f; + feedback_props->typeII_factor[1] = 1.f; + feedback_props->typeII_factor[2] = 0.5f; + feedback_props->typeII_factor[3] = 1.f; + feedback_props->typeII_factor[4] = 1.f; + feedback_props->typeII_factor[5] = 1.f; + feedback_props->typeII_factor[6] = 2.f; + feedback_props->typeII_factor[7] = 1.f; + feedback_props->typeII_factor[8] = 0.5f; + + /* Read the tables */ + read_yield_tables(feedback_props); + + /* Set yield_mass_bins array */ + const float imf_log10_mass_bin_size = + (feedback_props->log10_imf_max_mass_msun - + feedback_props->log10_imf_min_mass_msun) / + (feedback_props->n_imf_mass_bins - 1); + for (int i = 0; i < feedback_props->n_imf_mass_bins; i++) + feedback_props->yield_mass_bins[i] = + imf_log10_mass_bin_size * i + feedback_props->log10_imf_min_mass_msun; + + /* Resample yields from mass bins used in tables to mass bins used in IMF */ + compute_yields(feedback_props); + + /* Resample ejecta contribution to enrichment from mass bins used in tables to + * mass bins used in IMF */ + compute_ejecta(feedback_props); + + /* Calculate number of type II SN per solar mass + * Note: since we are integrating the IMF without weighting it by the yields + * pass NULL pointer for stellar_yields array */ + feedback_props->num_SNII_per_msun = + integrate_imf(feedback_props->log10_SNII_min_mass_msun, + feedback_props->log10_SNII_max_mass_msun, 0, + /*(stellar_yields=)*/ NULL, feedback_props); + + message("initialized stellar feedback"); +} + +/** + * @brief Initialize the global properties of the feedback scheme. + * + * By default, takes the values provided by the hydro. + * + * @param sp The #feedback_properties. + * @param phys_const The physical constants in the internal unit system. + * @param us The internal unit system. + * @param params The parsed parameters. + * @param p The already read-in properties of the hydro scheme. + */ +void feedbakc_props_init(struct feedback_props *fp, + const struct phys_const *phys_const, + const struct unit_system *us, + struct swift_params *params, + const struct hydro_props *p, + const struct cosmology *cosmo) { + + /* Read SNIa timscale */ + fp->SNIa_timescale_Gyr = + parser_get_param_float(params, "EAGLEFeedback:SNIa_timescale_Gyr"); + + /* Read the efficiency of producing SNIa */ + fp->SNIa_efficiency = + parser_get_param_float(params, "EAGLEFeedback:SNIa_efficiency"); + + /* Are we doing continuous heating? */ + fp->continuous_heating = + parser_get_param_int(params, "EAGLEFeedback:continuous_heating_switch"); + + /* Set the delay time before SNII occur */ + const float Gyr_in_cgs = 1e9 * 365 * 24 * 3600; + fp->SNII_wind_delay = + parser_get_param_float(params, "EAGLEFeedback:SNII_wind_delay_Gyr") * + Gyr_in_cgs / units_cgs_conversion_factor(us, UNIT_CONV_TIME); + + /* Read the temperature change to use in stochastic heating */ + fp->SNe_deltaT_desired = + parser_get_param_float(params, "EAGLEFeedback:SNe_heating_temperature_K"); + fp->SNe_deltaT_desired /= + units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE); + + /* Set ejecta thermal energy */ + const float ejecta_velocity = + 1.0e6 / units_cgs_conversion_factor( + us, UNIT_CONV_SPEED); // EAGLE parameter is 10 km/s + fp->ejecta_specific_thermal_energy = 0.5 * ejecta_velocity * ejecta_velocity; + + /* Energy released by supernova */ + fp->total_energy_SNe = + 1.0e51 / units_cgs_conversion_factor(us, UNIT_CONV_ENERGY); + + /* Calculate temperature to internal energy conversion factor */ + fp->temp_to_u_factor = + phys_const->const_boltzmann_k / + (p->mu_ionised * (hydro_gamma_minus_one)*phys_const->const_proton_mass); + + /* Read birth time to set all stars in ICs to (defaults to -1 to indicate star + * present in ICs) */ + fp->spart_first_init_birth_time = parser_get_opt_param_float( + params, "EAGLEFeedback:birth_time_override", -1); + + /* Copy over solar mass */ + fp->const_solar_mass = phys_const->const_solar_mass; +} + + diff --git a/src/feedback/EAGLE/feedback.h b/src/feedback/EAGLE/feedback.h index 6f669956027185a4218f23fd4baa67750dd0a941..d4ea9cb35d100588242343be6738bc87e61c7d9d 100644 --- a/src/feedback/EAGLE/feedback.h +++ b/src/feedback/EAGLE/feedback.h @@ -1,3 +1,39 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_FEEDBACK_EAGLE_H +#define SWIFT_FEEDBACK_EAGLE_H + +#include "cosmology.h" +#include "units.h" +#include "part.h" + +#include "feedback_properties.h" + + +void compute_stellar_evolution( + const struct feedback_props* feedback_props, + struct spart* sp, const struct unit_system* us, float age, + double dt); + +float compute_SNe(struct spart* sp, + const struct feedback_props* stars_properties, + float age, double dt); /** * @brief Prepares a s-particle for its feedback interactions @@ -7,8 +43,8 @@ __attribute__((always_inline)) INLINE static void feedback_init_spart( struct spart* sp) { - sp->density_weighted_frac_normalisation_inv = 0.f; - sp->ngb_mass = 0.f; + sp->feedback_data.density_weighted_frac_normalisation_inv = 0.f; + sp->feedback_data.ngb_mass = 0.f; } /** @@ -23,8 +59,8 @@ __attribute__((always_inline)) INLINE static void feedback_init_spart( __attribute__((always_inline)) INLINE static void feedback_first_init_spart( struct spart* sp, const struct feedback_props* feedback_props) { - sp->birth_density = -1.f; - sp->birth_time = feedback_props.spart_first_init_birth_time; + //sp->birth_density = -1.f; + //sp->birth_time = feedback_props.spart_first_init_birth_time; feedback_init_spart(sp); } @@ -41,566 +77,6 @@ __attribute__((always_inline)) INLINE static void feedback_first_init_spart( __attribute__((always_inline)) INLINE static void feedback_prepare_spart( struct spart* sp, const struct feedback_props* feedback_props) {} -/** - * @brief determine which metallicity bin star belongs to for AGB, compute bin - * indices and offsets - * - * @param iz_low Pointer to index of metallicity bin to which the star belongs - * (to be calculated in this function) - * @param iz_high Pointer to index of metallicity bin to above the star's - * metallicity (to be calculated in this function) - * @param dz metallicity bin offset - * @param log10_metallicity log10 of star metallicity - * @param star_properties stars_props data structure - */ -inline static void determine_bin_yield_AGB( - int* iz_low, int* iz_high, float* dz, float log10_metallicity, - const struct stars_props* restrict star_properties) { - - if (log10_metallicity > log10_min_metallicity) { - /* Find metallicity bin which contains the star's metallicity */ - int j; - for (j = 0; j < star_properties->feedback.AGB_n_z - 1 && - log10_metallicity > - star_properties->feedback.yield_AGB.metallicity[j + 1]; - j++) - ; - *iz_low = j; - *iz_high = *iz_low + 1; - - /* Compute offset */ - if (log10_metallicity >= - star_properties->feedback.yield_AGB.metallicity[0] && - log10_metallicity <= - star_properties->feedback.yield_AGB - .metallicity[star_properties->feedback.AGB_n_z - 1]) - *dz = log10_metallicity - - star_properties->feedback.yield_AGB.metallicity[*iz_low]; - else - *dz = 0; - - /* Normalize offset */ - float deltaz = star_properties->feedback.yield_AGB.metallicity[*iz_high] - - star_properties->feedback.yield_AGB.metallicity[*iz_low]; - - if (deltaz > 0) - *dz /= deltaz; - else - dz = 0; - } else { - *iz_low = 0; - *iz_high = 0; - *dz = 0; - } -} - -/** - * @brief determine which metallicity bin star belongs to for SNII, compute bin - * indices and offsets - * - * @param iz_low Pointer to index of metallicity bin to which the star belongs - * (to be calculated in this function) - * @param iz_high Pointer to index of metallicity bin to above the star's - * metallicity (to be calculated in this function) - * @param dz metallicity bin offset - * @param log10_metallicity log10 of star metallicity - * @param star_properties stars_props data structure - */ -inline static void determine_bin_yield_SNII( - int* iz_low, int* iz_high, float* dz, float log10_metallicity, - const struct stars_props* restrict star_properties) { - - if (log10_metallicity > log10_min_metallicity) { - /* Find metallicity bin which contains the star's metallicity */ - int j; - for (j = 0; j < star_properties->feedback.SNII_n_z - 1 && - log10_metallicity > - star_properties->feedback.yield_SNII.metallicity[j + 1]; - j++) - ; - *iz_low = j; - *iz_high = *iz_low + 1; - - /* Compute offset */ - if (log10_metallicity >= - star_properties->feedback.yield_SNII.metallicity[0] && - log10_metallicity <= - star_properties->feedback.yield_SNII - .metallicity[star_properties->feedback.SNII_n_z - 1]) - *dz = log10_metallicity - - star_properties->feedback.yield_SNII.metallicity[*iz_low]; - else - *dz = 0; - - /* Normalize offset */ - float deltaz = star_properties->feedback.yield_SNII.metallicity[*iz_high] - - star_properties->feedback.yield_SNII.metallicity[*iz_low]; - - if (deltaz > 0) - *dz = *dz / deltaz; - else - dz = 0; - } else { - *iz_low = 0; - *iz_high = 0; - *dz = 0; - } -} - -/** - * @brief compute enrichment and feedback due to SNIa. To do this compute the - * number of SNIa that occur during the timestep, multiply by constants read - * from tables. - * - * @param log10_min_mass log10 mass at the end of step - * @param log10_max_mass log10 mass at the beginning of step - * @param stars star properties data structure - * @param sp spart we are computing feedback from - * @param star_age_Gyr age of star in Gyr - * @param dt_Gyr timestep dt in Gyr - */ -inline static void evolve_SNIa(float log10_min_mass, float log10_max_mass, - const struct stars_props* restrict stars, - struct spart* restrict sp, float star_age_Gyr, - float dt_Gyr) { - - /* Check if we're outside the mass range for SNIa */ - if (log10_min_mass >= stars->feedback.log10_SNIa_max_mass_msun) return; - - /* If the max mass is outside the mass range update it to be the maximum and - * use updated values for the star's age and timestep in this function */ - if (log10_max_mass > stars->feedback.log10_SNIa_max_mass_msun) { - log10_max_mass = stars->feedback.log10_SNIa_max_mass_msun; - float lifetime_Gyr = - lifetime_in_Gyr(exp(M_LN10 * stars->feedback.log10_SNIa_max_mass_msun), - sp->chemistry_data.metal_mass_fraction_total, stars); - dt_Gyr = star_age_Gyr + dt_Gyr - lifetime_Gyr; - star_age_Gyr = lifetime_Gyr; - } - - /* compute the number of SNIa */ - /* Efolding (Forster 2006) */ - float num_SNIa_per_msun = - stars->feedback.SNIa_efficiency * - (exp(-star_age_Gyr / stars->feedback.SNIa_timescale_Gyr) - - exp(-(star_age_Gyr + dt_Gyr) / stars->feedback.SNIa_timescale_Gyr)) * - sp->mass_init; - - sp->to_distribute.num_SNIa = - num_SNIa_per_msun / stars->feedback.const_solar_mass; - - /* compute mass fractions of each metal */ - for (int i = 0; i < chemistry_element_count; i++) { - sp->to_distribute.metal_mass[i] += - num_SNIa_per_msun * stars->feedback.yield_SNIa_IMF_resampled[i]; - } - - /* Update the metallicity of the material released */ - sp->to_distribute.metal_mass_from_SNIa += - num_SNIa_per_msun * stars->feedback.yield_SNIa_total_metals_IMF_resampled; - - /* Update the metal mass produced */ - sp->to_distribute.total_metal_mass += - num_SNIa_per_msun * stars->feedback.yield_SNIa_total_metals_IMF_resampled; - - /* Compute the mass produced by SNIa */ - sp->to_distribute.mass_from_SNIa += - num_SNIa_per_msun * stars->feedback.yield_SNIa_total_metals_IMF_resampled; - - /* Compute the iron mass produced */ - sp->to_distribute.Fe_mass_from_SNIa += - num_SNIa_per_msun * - stars->feedback.yield_SNIa_IMF_resampled[chemistry_element_Fe]; -} - -/** - * @brief compute enrichment and feedback due to SNII. To do this, integrate the - * IMF weighted by the yields read from tables for each of the quantities of - * interest. - * - * @param log10_min_mass log10 mass at the end of step - * @param log10_max_mass log10 mass at the beginning of step - * @param stellar_yields array to store calculated yields for passing to - * integrate_imf - * @param stars star properties data structure - * @param sp spart we are computing feedback from - */ -inline static void evolve_SNII(float log10_min_mass, float log10_max_mass, - float* stellar_yields, - const struct stars_props* restrict stars, - struct spart* restrict sp) { - int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index; - - /* If mass at beginning of step is less than tabulated lower bound for IMF, - * limit it.*/ - if (log10_min_mass < stars->feedback.log10_SNII_min_mass_msun) - log10_min_mass = stars->feedback.log10_SNII_min_mass_msun; - - /* If mass at end of step is greater than tabulated upper bound for IMF, limit - * it.*/ - if (log10_max_mass > stars->feedback.log10_SNII_max_mass_msun) - log10_max_mass = stars->feedback.log10_SNII_max_mass_msun; - - /* Don't do anything if the stellar mass hasn't decreased by the end of the - * step */ - if (log10_min_mass >= log10_max_mass) return; - - /* determine which IMF mass bins contribute to the integral */ - determine_imf_bins(log10_min_mass, log10_max_mass, &low_imf_mass_bin_index, - &high_imf_mass_bin_index, stars); - - /* Integrate IMF to determine number of SNII */ - sp->to_distribute.num_SNII = - integrate_imf(log10_min_mass, log10_max_mass, 0, stellar_yields, stars); - - /* determine which metallicity bin and offset this star belongs to */ - int iz_low, iz_high, low_index_3d, high_index_3d, low_index_2d, high_index_2d; - float dz; - determine_bin_yield_SNII(&iz_low, &iz_high, &dz, - log10(sp->chemistry_data.metal_mass_fraction_total), - stars); - - /* compute metals produced */ - float metal_mass_released[chemistry_element_count], metal_mass_released_total; - for (int elem = 0; elem < chemistry_element_count; elem++) { - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_3d = feedback_row_major_index_3d( - iz_low, elem, mass_bin_index, stars->feedback.SNII_n_z, - chemistry_element_count, stars->feedback.n_imf_mass_bins); - high_index_3d = feedback_row_major_index_3d( - iz_high, elem, mass_bin_index, stars->feedback.SNII_n_z, - chemistry_element_count, stars->feedback.n_imf_mass_bins); - low_index_2d = feedback_row_major_index_2d( - iz_low, mass_bin_index, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * - (stars->feedback.yield_SNII.yield_IMF_resampled[low_index_3d] + - sp->chemistry_data.metal_mass_fraction[elem] * - stars->feedback.yield_SNII - .ejecta_IMF_resampled[low_index_2d]) + - dz * (stars->feedback.yield_SNII.yield_IMF_resampled[high_index_3d] + - sp->chemistry_data.metal_mass_fraction[elem] * - stars->feedback.yield_SNII - .ejecta_IMF_resampled[high_index_2d]); - } - - metal_mass_released[elem] = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - } - - /* Compute mass produced */ - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, - stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * (stars->feedback.yield_SNII - .total_metals_IMF_resampled[low_index_2d] + - sp->chemistry_data.metal_mass_fraction_total * - stars->feedback.yield_SNII - .ejecta_IMF_resampled[low_index_2d]) + - dz * (stars->feedback.yield_SNII - .total_metals_IMF_resampled[high_index_2d] + - sp->chemistry_data.metal_mass_fraction_total * - stars->feedback.yield_SNII - .ejecta_IMF_resampled[high_index_2d]); - } - - metal_mass_released_total = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - - /* yield normalization */ - float mass_ejected, mass_released; - - /* zero all negative values */ - for (int i = 0; i < chemistry_element_count; i++) - metal_mass_released[i] = max(metal_mass_released[i], 0.f); - - metal_mass_released_total = max(metal_mass_released_total, 0.f); - - /* compute the total metal mass ejected from the star*/ - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, - stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * - stars->feedback.yield_SNII.ejecta_IMF_resampled[low_index_2d] + - dz * stars->feedback.yield_SNII.ejecta_IMF_resampled[high_index_2d]; - } - - mass_ejected = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - - /* compute the total mass released */ - mass_released = metal_mass_released_total + - metal_mass_released[chemistry_element_H] + - metal_mass_released[chemistry_element_He]; - - /* normalize the yields */ - if (mass_released > 0) { - /* Set normalisation factor. Note additional multiplication by the star - * initial mass as tables are per initial mass */ - const float norm_factor = sp->mass_init * mass_ejected / mass_released; - - for (int i = 0; i < chemistry_element_count; i++) { - sp->to_distribute.metal_mass[i] += metal_mass_released[i] * norm_factor; - } - for (int i = 0; i < chemistry_element_count; i++) { - sp->to_distribute.mass_from_SNII += sp->to_distribute.metal_mass[i]; - } - sp->to_distribute.total_metal_mass += - metal_mass_released_total * norm_factor; - sp->to_distribute.metal_mass_from_SNII += - metal_mass_released_total * norm_factor; - } else { - error("wrong normalization!!!! mass_released = %e\n", mass_released); - } -} - -/** - * @brief compute enrichment and feedback due to AGB. To do this, integrate the - * IMF weighted by the yields read from tables for each of the quantities of - * interest. - * - * @param log10_min_mass log10 mass at the end of step - * @param log10_max_mass log10 mass at the beginning of step - * @param stellar_yields array to store calculated yields for passing to - * integrate_imf - * @param stars star properties data structure - * @param sp spart we are computing feedback from - */ -inline static void evolve_AGB(float log10_min_mass, float log10_max_mass, - float* stellar_yields, - const struct stars_props* restrict stars, - struct spart* restrict sp) { - int low_imf_mass_bin_index, high_imf_mass_bin_index, mass_bin_index; - - /* If mass at end of step is greater than tabulated lower bound for IMF, limit - * it.*/ - if (log10_max_mass > stars->feedback.log10_SNII_min_mass_msun) - log10_max_mass = stars->feedback.log10_SNII_min_mass_msun; - - /* Don't do anything if the stellar mass hasn't decreased by the end of the - * step */ - if (log10_min_mass >= log10_max_mass) return; - - /* determine which IMF mass bins contribute to the integral */ - determine_imf_bins(log10_min_mass, log10_max_mass, &low_imf_mass_bin_index, - &high_imf_mass_bin_index, stars); - - /* determine which metallicity bin and offset this star belongs to */ - int iz_low, iz_high, low_index_3d, high_index_3d, low_index_2d, high_index_2d; - float dz; - determine_bin_yield_AGB(&iz_low, &iz_high, &dz, - log10(sp->chemistry_data.metal_mass_fraction_total), - stars); - - /* compute metals produced */ - float metal_mass_released[chemistry_element_count], metal_mass_released_total; - for (int elem = 0; elem < chemistry_element_count; elem++) { - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_3d = feedback_row_major_index_3d( - iz_low, elem, mass_bin_index, stars->feedback.AGB_n_z, - chemistry_element_count, stars->feedback.n_imf_mass_bins); - high_index_3d = feedback_row_major_index_3d( - iz_high, elem, mass_bin_index, stars->feedback.AGB_n_z, - chemistry_element_count, stars->feedback.n_imf_mass_bins); - low_index_2d = feedback_row_major_index_2d( - iz_low, mass_bin_index, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * - (stars->feedback.yield_AGB.yield_IMF_resampled[low_index_3d] + - sp->chemistry_data.metal_mass_fraction[elem] * - stars->feedback.yield_AGB - .ejecta_IMF_resampled[low_index_2d]) + - dz * (stars->feedback.yield_AGB.yield_IMF_resampled[high_index_3d] + - sp->chemistry_data.metal_mass_fraction[elem] * - stars->feedback.yield_AGB - .ejecta_IMF_resampled[high_index_2d]); - } - - metal_mass_released[elem] = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - } - - /* Compute mass produced */ - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, - stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * - (stars->feedback.yield_AGB - .total_metals_IMF_resampled[low_index_2d] + - sp->chemistry_data.metal_mass_fraction_total * - stars->feedback.yield_AGB.ejecta_IMF_resampled[low_index_2d]) + - dz * - (stars->feedback.yield_AGB - .total_metals_IMF_resampled[high_index_2d] + - sp->chemistry_data.metal_mass_fraction_total * - stars->feedback.yield_AGB.ejecta_IMF_resampled[high_index_2d]); - } - - metal_mass_released_total = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - - /* yield normalization */ - float mass_ejected, mass_released; - - /* zero all negative values */ - for (int i = 0; i < chemistry_element_count; i++) - metal_mass_released[i] = max(metal_mass_released[i], 0.f); - - metal_mass_released_total = max(metal_mass_released_total, 0.f); - - /* compute the total metal mass ejected from the star */ - for (mass_bin_index = low_imf_mass_bin_index; - mass_bin_index < high_imf_mass_bin_index + 1; mass_bin_index++) { - low_index_2d = feedback_row_major_index_2d(iz_low, mass_bin_index, - stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - high_index_2d = feedback_row_major_index_2d( - iz_high, mass_bin_index, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - stellar_yields[mass_bin_index] = - (1 - dz) * - stars->feedback.yield_AGB.ejecta_IMF_resampled[low_index_2d] + - dz * stars->feedback.yield_AGB.ejecta_IMF_resampled[high_index_2d]; - } - - mass_ejected = - integrate_imf(log10_min_mass, log10_max_mass, 2, stellar_yields, stars); - - /* compute the total mass released */ - mass_released = metal_mass_released_total + - metal_mass_released[chemistry_element_H] + - metal_mass_released[chemistry_element_He]; - - /* normalize the yields */ - if (mass_released > 0) { - /* Set normalisation factor. Note additional multiplication by the stellar - * initial mass as tables are per initial mass */ - const float norm_factor = sp->mass_init * mass_ejected / mass_released; - - for (int i = 0; i < chemistry_element_count; i++) { - sp->to_distribute.metal_mass[i] += metal_mass_released[i] * norm_factor; - sp->to_distribute.mass_from_AGB += metal_mass_released[i] * norm_factor; - } - sp->to_distribute.total_metal_mass += - metal_mass_released_total * norm_factor; - sp->to_distribute.metal_mass_from_AGB += - metal_mass_released_total * norm_factor; - } else { - error("wrong normalization!!!! mass_released = %e\n", mass_released); - } -} - -/** - * @brief calculates stellar mass in spart that died over the timestep, calls - * functions to calculate feedback due to SNIa, SNII and AGB - * - * @param star_properties stars_props data structure - * @param sp spart that we're evolving - * @param us unit_system data structure - * @param age age of spart at beginning of step - * @param dt length of current timestep - */ -inline static void compute_stellar_evolution( - const struct stars_props* restrict star_properties, - struct spart* restrict sp, const struct unit_system* us, float age, - double dt) { - - /* Allocate temporary array for calculating imf weights */ - float* stellar_yields; - stellar_yields = - malloc(star_properties->feedback.n_imf_mass_bins * sizeof(float)); - - /* Convert dt and stellar age from internal units to Gyr. */ - const double Gyr_in_cgs = 3.154e16; - double dt_Gyr = - dt * units_cgs_conversion_factor(us, UNIT_CONV_TIME) / Gyr_in_cgs; - double star_age_Gyr = - age * units_cgs_conversion_factor(us, UNIT_CONV_TIME) / Gyr_in_cgs; - - /* calculate mass of stars that has died from the star's birth up to the - * beginning and end of timestep */ - double log10_max_dying_mass_msun = log10(dying_mass_msun( - star_age_Gyr, sp->chemistry_data.metal_mass_fraction_total, - star_properties)); - double log10_min_dying_mass_msun = log10(dying_mass_msun( - star_age_Gyr + dt_Gyr, sp->chemistry_data.metal_mass_fraction_total, - star_properties)); - - /* Sanity check. Worth investigating if necessary as functions for evaluating - * mass of stars dying might be strictly decreasing. */ - if (log10_min_dying_mass_msun > log10_max_dying_mass_msun) - error("min dying mass is greater than max dying mass"); - - /* Integration interval is zero - this can happen if minimum and maximum - * dying masses are above imf_max_mass_msun. Return without doing any - * feedback. */ - if (log10_min_dying_mass_msun == log10_max_dying_mass_msun) return; - - /* Evolve SNIa, SNII, AGB */ - evolve_SNIa(log10_min_dying_mass_msun, log10_max_dying_mass_msun, - star_properties, sp, star_age_Gyr, dt_Gyr); - evolve_SNII(log10_min_dying_mass_msun, log10_max_dying_mass_msun, - stellar_yields, star_properties, sp); - evolve_AGB(log10_min_dying_mass_msun, log10_max_dying_mass_msun, - stellar_yields, star_properties, sp); - - /* Compute the mass to distribute */ - sp->to_distribute.mass = sp->to_distribute.total_metal_mass + - sp->to_distribute.metal_mass[chemistry_element_H] + - sp->to_distribute.metal_mass[chemistry_element_He]; - - /* Clean up */ - free(stellar_yields); -} - -/** - * @brief Compute number of SN that should go off given the age of the spart - * - * @param sp spart we're evolving - * @param stars_properties stars_props data structure - * @param age age of star at the beginning of the step - * @param dt length of step - */ -inline static float compute_SNe(struct spart* sp, - const struct stars_props* stars_properties, - float age, double dt) { - if (age <= stars_properties->feedback.SNII_wind_delay && - age + dt > stars_properties->feedback.SNII_wind_delay) { - return stars_properties->feedback.num_SNII_per_msun * sp->mass_init / - stars_properties->feedback.const_solar_mass; - } else { - return 0; - } -} - /** * @brief Evolve the stellar properties of a #spart. * @@ -612,129 +88,52 @@ inline static float compute_SNe(struct spart* sp, * @param stars_properties The #stars_props */ __attribute__((always_inline)) INLINE static void stars_evolve_spart( - struct spart* restrict sp, const struct stars_props* stars_properties, + struct spart* restrict sp, const struct feedback_props* feedback_props, const struct cosmology* cosmo, const struct unit_system* us, double star_age, double dt) { /* Zero the number of SN and amount of mass that is distributed */ - sp->to_distribute.num_SNIa = 0; - sp->to_distribute.num_SNII = 0; - sp->to_distribute.mass = 0; + sp->feedback_data.to_distribute.num_SNIa = 0; + sp->feedback_data.to_distribute.num_SNII = 0; + sp->feedback_data.to_distribute.mass = 0; /* Zero the enrichment quantities */ for (int i = 0; i < chemistry_element_count; i++) - sp->to_distribute.metal_mass[i] = 0; - sp->to_distribute.total_metal_mass = 0; - sp->to_distribute.mass_from_AGB = 0; - sp->to_distribute.metal_mass_from_AGB = 0; - sp->to_distribute.mass_from_SNII = 0; - sp->to_distribute.metal_mass_from_SNII = 0; - sp->to_distribute.mass_from_SNIa = 0; - sp->to_distribute.metal_mass_from_SNIa = 0; - sp->to_distribute.Fe_mass_from_SNIa = 0; + sp->feedback_data.to_distribute.metal_mass[i] = 0; + sp->feedback_data.to_distribute.total_metal_mass = 0; + sp->feedback_data.to_distribute.mass_from_AGB = 0; + sp->feedback_data.to_distribute.metal_mass_from_AGB = 0; + sp->feedback_data.to_distribute.mass_from_SNII = 0; + sp->feedback_data.to_distribute.metal_mass_from_SNII = 0; + sp->feedback_data.to_distribute.mass_from_SNIa = 0; + sp->feedback_data.to_distribute.metal_mass_from_SNIa = 0; + sp->feedback_data.to_distribute.Fe_mass_from_SNIa = 0; /* Compute amount of enrichment and feedback that needs to be done in this * step */ - compute_stellar_evolution(stars_properties, sp, us, star_age, dt); + compute_stellar_evolution(feedback_props, sp, us, star_age, dt); /* Decrease star mass by amount of mass distributed to gas neighbours */ - sp->mass -= sp->to_distribute.mass; + sp->mass -= sp->feedback_data.to_distribute.mass; /* Compute the number of type II SNe that went off */ - sp->to_distribute.num_SNe = compute_SNe(sp, stars_properties, star_age, dt); + sp->feedback_data.to_distribute.num_SNe = compute_SNe(sp, feedback_props, star_age, dt); /* Compute energy change due to thermal and kinetic energy of ejecta */ - sp->to_distribute.d_energy = - sp->to_distribute.mass * - (stars_properties->feedback.ejecta_specific_thermal_energy + + sp->feedback_data.to_distribute.d_energy = + sp->feedback_data.to_distribute.mass * + (feedback_props->ejecta_specific_thermal_energy + 0.5 * (sp->v[0] * sp->v[0] + sp->v[1] * sp->v[1] + sp->v[2] * sp->v[2]) * cosmo->a2_inv); /* Compute probability of heating neighbouring particles */ - if (dt > 0 && sp->ngb_mass > 0) - sp->to_distribute.heating_probability = - stars_properties->feedback.total_energy_SNe * - sp->to_distribute.num_SNe / - (stars_properties->feedback.temp_to_u_factor * - stars_properties->feedback.SNe_deltaT_desired * sp->ngb_mass); + if (dt > 0 && sp->feedback_data.ngb_mass > 0) + sp->feedback_data.to_distribute.heating_probability = + feedback_props->total_energy_SNe * + sp->feedback_data.to_distribute.num_SNe / + (feedback_props->temp_to_u_factor * + feedback_props->SNe_deltaT_desired * sp->feedback_data.ngb_mass); } -/** - * @brief Initializes constants related to stellar evolution, initializes imf, - * reads and processes yield tables - * - * @param params swift_params parameters structure - * @param stars stars_props data structure - */ -inline static void stars_evolve_init(struct swift_params* params, - struct stars_props* restrict stars) { - - /* Set number of elements found in yield tables */ - stars->feedback.SNIa_n_elements = 42; - stars->feedback.SNII_n_mass = 11; - stars->feedback.SNII_n_elements = 11; - stars->feedback.SNII_n_z = 5; - stars->feedback.AGB_n_mass = 23; - stars->feedback.AGB_n_elements = 11; - stars->feedback.AGB_n_z = 3; - stars->feedback.lifetimes.n_mass = 30; - stars->feedback.lifetimes.n_z = 6; - stars->feedback.element_name_length = 15; - - /* Set bounds for imf */ - stars->feedback.log10_SNII_min_mass_msun = 0.77815125f; // log10(6). - stars->feedback.log10_SNII_max_mass_msun = 2.f; // log10(100). - stars->feedback.log10_SNIa_max_mass_msun = 0.90308999f; // log10(8). - - /* Yield table filepath */ - parser_get_param_string(params, "EAGLEFeedback:filename", - stars->feedback.yield_table_path); - parser_get_param_string(params, "EAGLEFeedback:imf_model", - stars->feedback.IMF_Model); - - /* Initialise IMF */ - init_imf(stars); - - /* Allocate yield tables */ - allocate_yield_tables(stars); - /* Set factors for each element adjusting SNII yield */ - stars->feedback.typeII_factor[0] = 1.f; - stars->feedback.typeII_factor[1] = 1.f; - stars->feedback.typeII_factor[2] = 0.5f; - stars->feedback.typeII_factor[3] = 1.f; - stars->feedback.typeII_factor[4] = 1.f; - stars->feedback.typeII_factor[5] = 1.f; - stars->feedback.typeII_factor[6] = 2.f; - stars->feedback.typeII_factor[7] = 1.f; - stars->feedback.typeII_factor[8] = 0.5f; - - /* Read the tables */ - read_yield_tables(stars); - - /* Set yield_mass_bins array */ - const float imf_log10_mass_bin_size = - (stars->feedback.log10_imf_max_mass_msun - - stars->feedback.log10_imf_min_mass_msun) / - (stars->feedback.n_imf_mass_bins - 1); - for (int i = 0; i < stars->feedback.n_imf_mass_bins; i++) - stars->feedback.yield_mass_bins[i] = - imf_log10_mass_bin_size * i + stars->feedback.log10_imf_min_mass_msun; - - /* Resample yields from mass bins used in tables to mass bins used in IMF */ - compute_yields(stars); - - /* Resample ejecta contribution to enrichment from mass bins used in tables to - * mass bins used in IMF */ - compute_ejecta(stars); - - /* Calculate number of type II SN per solar mass - * Note: since we are integrating the IMF without weighting it by the yields - * pass NULL pointer for stellar_yields array */ - stars->feedback.num_SNII_per_msun = - integrate_imf(stars->feedback.log10_SNII_min_mass_msun, - stars->feedback.log10_SNII_max_mass_msun, 0, - /*(stellar_yields=)*/ NULL, stars); - - message("initialized stellar feedback"); -} +#endif /* SWIFT_FEEDBACK_EAGLE_H */ diff --git a/src/feedback/EAGLE/feedback_iact.h b/src/feedback/EAGLE/feedback_iact.h index 2122f418d4b95cb843a35b7ed8aeeb7c2c664350..8550ff93545220ee56cee1680a467cdbf20f8ea8 100644 --- a/src/feedback/EAGLE/feedback_iact.h +++ b/src/feedback/EAGLE/feedback_iact.h @@ -16,7 +16,7 @@ * @param ti_current Current integer time value */ __attribute__((always_inline)) INLINE static void -runner_iact_nonsym_stars_density( +runner_iact_nonsym_feedback_density( float r2, const float *dx, float hi, float hj, struct spart *restrict si, const struct part *restrict pj, const struct cosmology *restrict cosmo, const struct stars_props *restrict stars_properties, @@ -42,14 +42,14 @@ runner_iact_nonsym_stars_density( kernel_deval(uj, &wj, &wj_dx); /* Add mass of pj to neighbour mass of si */ - si->ngb_mass += hydro_get_mass(pj); + si->feedback_data.ngb_mass += hydro_get_mass(pj); /* Add contribution of pj to normalisation of density weighted fraction * which determines how much mass to distribute to neighbouring * gas particles */ const float rho = hydro_get_comoving_density(pj); - if (rho != 0) si->density_weighted_frac_normalisation_inv += wj / rho; + if (rho != 0) si->feedback_data.density_weighted_frac_normalisation_inv += wj / rho; /* Compute contribution to the density */ si->rho_gas += mj * wi; @@ -72,7 +72,7 @@ runner_iact_nonsym_stars_density( * generator */ __attribute__((always_inline)) INLINE static void -runner_iact_nonsym_stars_feedback( +runner_iact_nonsym_feedback_apply( float r2, const float *dx, float hi, float hj, const struct spart *restrict si, struct part *restrict pj, const struct cosmology *restrict cosmo, diff --git a/src/feedback/EAGLE/feedback_properties.h b/src/feedback/EAGLE/feedback_properties.h index 0ccb4c0b33e34c51d633c73d1d5806e821a75f16..0389edee86ec30994a3c81265f70a49a488222d0 100644 --- a/src/feedback/EAGLE/feedback_properties.h +++ b/src/feedback/EAGLE/feedback_properties.h @@ -46,7 +46,7 @@ struct lifetime_table { double **dyingtime; }; -struct feedback_properties { +struct feedback_props { /* Flag to switch between continuous and stochastic heating */ int continuous_heating; @@ -150,68 +150,3 @@ struct feedback_properties { float spart_first_init_birth_time; }; -/** - * @brief Initialize the global properties of the feedback scheme. - * - * By default, takes the values provided by the hydro. - * - * @param sp The #feedback_properties. - * @param phys_const The physical constants in the internal unit system. - * @param us The internal unit system. - * @param params The parsed parameters. - * @param p The already read-in properties of the hydro scheme. - */ -INLINE static void feedbakc_props_init(struct feedback_props *fp, - const struct phys_const *phys_const, - const struct unit_system *us, - struct swift_params *params, - const struct hydro_props *p, - const struct cosmology *cosmo) { - - /* Read SNIa timscale */ - fp->SNIa_timescale_Gyr = - parser_get_param_float(params, "EAGLEFeedback:SNIa_timescale_Gyr"); - - /* Read the efficiency of producing SNIa */ - fp->SNIa_efficiency = - parser_get_param_float(params, "EAGLEFeedback:SNIa_efficiency"); - - /* Are we doing continuous heating? */ - fp->continuous_heating = - parser_get_param_int(params, "EAGLEFeedback:continuous_heating_switch"); - - /* Set the delay time before SNII occur */ - const float Gyr_in_cgs = 1e9 * 365 * 24 * 3600; - fp->SNII_wind_delay = - parser_get_param_float(params, "EAGLEFeedback:SNII_wind_delay_Gyr") * - Gyr_in_cgs / units_cgs_conversion_factor(us, UNIT_CONV_TIME); - - /* Read the temperature change to use in stochastic heating */ - fp->SNe_deltaT_desired = - parser_get_param_float(params, "EAGLEFeedback:SNe_heating_temperature_K"); - fp->SNe_deltaT_desired /= - units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE); - - /* Set ejecta thermal energy */ - const float ejecta_velocity = - 1.0e6 / units_cgs_conversion_factor( - us, UNIT_CONV_SPEED); // EAGLE parameter is 10 km/s - fp->ejecta_specific_thermal_energy = 0.5 * ejecta_velocity * ejecta_velocity; - - /* Energy released by supernova */ - fp->total_energy_SNe = - 1.0e51 / units_cgs_conversion_factor(us, UNIT_CONV_ENERGY); - - /* Calculate temperature to internal energy conversion factor */ - fp->temp_to_u_factor = - phys_const->const_boltzmann_k / - (p->mu_ionised * (hydro_gamma_minus_one)*phys_const->const_proton_mass); - - /* Read birth time to set all stars in ICs to (defaults to -1 to indicate star - * present in ICs) */ - fp->spart_first_init_birth_time = parser_get_opt_param_float( - params, "EAGLEFeedback:birth_time_override", -1); - - /* Copy over solar mass */ - fp->const_solar_mass = phys_const->const_solar_mass; -} diff --git a/src/feedback/EAGLE/feedback_struct.h b/src/feedback/EAGLE/feedback_struct.h index 1e0c8e055fb901c7dd78382aca94bbf3a70c6f1d..093bbfc424f507ab4cb9d670954f7cfa37a816a4 100644 --- a/src/feedback/EAGLE/feedback_struct.h +++ b/src/feedback/EAGLE/feedback_struct.h @@ -1,7 +1,26 @@ - - - -struct feedback_struct_data { +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_FEEDBACK_STRUCT_EAGLE_H +#define SWIFT_FEEDBACK_STRUCT_EAGLE_H + + +struct feedback_part_data { struct { @@ -58,4 +77,8 @@ struct feedback_struct_data { /* total mass (unweighted) of neighbouring gas particles */ float ngb_mass; -} +}; + + +#endif /* SWIFT_FEEDBACK_STRUCT_EAGLE_H */ + diff --git a/src/feedback/EAGLE/imf.h b/src/feedback/EAGLE/imf.h index f84cec786c8c196f33688d582ee705ccae5a2ffb..9914adacae2495337ca1406275a9e906fcd98289 100644 --- a/src/feedback/EAGLE/imf.h +++ b/src/feedback/EAGLE/imf.h @@ -20,6 +20,9 @@ #define SWIFT_EAGLE_STARS_IMF_H #include "interpolate.h" +#include "minmax.h" + +#include <string.h> /** * @brief the different weightings allowed for the IMF integration @@ -42,15 +45,15 @@ enum eagle_imf_integration_type { */ inline static void determine_imf_bins( double log10_min_mass, double log10_max_mass, int *i_min, int *i_max, - const struct stars_props *star_properties) { + const struct feedback_props *feedback_props) { #ifdef SWIFT_DEBUG_CHECKS if (log10_min_mass > log10_max_mass) error("Lower bound higher than larger bound."); #endif - const int N_bins = star_properties->feedback.n_imf_mass_bins; - const float *imf_bins_log10 = star_properties->feedback.imf_mass_bin_log10; + const int N_bins = feedback_props->n_imf_mass_bins; + const float *imf_bins_log10 = feedback_props->imf_mass_bin_log10; /* Check whether lower mass is within the IMF mass bin range */ log10_min_mass = max(log10_min_mass, imf_bins_log10[0]); @@ -87,14 +90,14 @@ inline static float integrate_imf(const float log10_min_mass, const float log10_max_mass, const enum eagle_imf_integration_type mode, const float *stellar_yields, - const struct stars_props *star_properties) { + const struct feedback_props *feedback_props) { /* Pull out some common terms */ - const int N_bins = star_properties->feedback.n_imf_mass_bins; - const float *imf = star_properties->feedback.imf; - const float *imf_mass_bin = star_properties->feedback.imf_mass_bin; + const int N_bins = feedback_props->n_imf_mass_bins; + const float *imf = feedback_props->imf; + const float *imf_mass_bin = feedback_props->imf_mass_bin; const float *imf_mass_bin_log10 = - star_properties->feedback.imf_mass_bin_log10; + feedback_props->imf_mass_bin_log10; /* IMF mass bin spacing in log10 space. Assumes uniform spacing. */ const float imf_log10_mass_bin_size = @@ -103,7 +106,7 @@ inline static float integrate_imf(const float log10_min_mass, /* Determine bins to integrate over based on integration bounds */ int i_min, i_max; determine_imf_bins(log10_min_mass, log10_max_mass, &i_min, &i_max, - star_properties); + feedback_props); /* Array for the integrand */ float integrand[N_bins]; @@ -189,82 +192,82 @@ inline static float integrate_imf(const float log10_min_mass, * table. * * @param star_properties #stars_props data structure */ -inline static void init_imf(struct stars_props *restrict star_properties) { +inline static void init_imf(struct feedback_props *restrict feedback_props) { /* Define number of imf mass bins */ - star_properties->feedback.n_imf_mass_bins = 200; + feedback_props->n_imf_mass_bins = 200; /* Define max and min imf masses */ - star_properties->feedback.imf_max_mass_msun = 100.f; - star_properties->feedback.imf_min_mass_msun = 0.1; - star_properties->feedback.log10_imf_max_mass_msun = - log10(star_properties->feedback.imf_max_mass_msun); - star_properties->feedback.log10_imf_min_mass_msun = - log10(star_properties->feedback.imf_min_mass_msun); + feedback_props->imf_max_mass_msun = 100.f; + feedback_props->imf_min_mass_msun = 0.1; + feedback_props->log10_imf_max_mass_msun = + log10(feedback_props->imf_max_mass_msun); + feedback_props->log10_imf_min_mass_msun = + log10(feedback_props->imf_min_mass_msun); /* Compute size of mass bins in log10 space */ const float imf_log10_mass_bin_size = - (star_properties->feedback.log10_imf_max_mass_msun - - star_properties->feedback.log10_imf_min_mass_msun) / - (float)(star_properties->feedback.n_imf_mass_bins - 1); + (feedback_props->log10_imf_max_mass_msun - + feedback_props->log10_imf_min_mass_msun) / + (float)(feedback_props->n_imf_mass_bins - 1); /* Allocate IMF array */ if (swift_memalign( - "imf-tables", (void **)&star_properties->feedback.imf, + "imf-tables", (void **)&feedback_props->imf, SWIFT_STRUCT_ALIGNMENT, - star_properties->feedback.n_imf_mass_bins * sizeof(float)) != 0) + feedback_props->n_imf_mass_bins * sizeof(float)) != 0) error("Failed to allocate IMF bins table"); /* Allocate array to store IMF mass bins */ if (swift_memalign( - "imf-tables", (void **)&star_properties->feedback.imf_mass_bin, + "imf-tables", (void **)&feedback_props->imf_mass_bin, SWIFT_STRUCT_ALIGNMENT, - star_properties->feedback.n_imf_mass_bins * sizeof(float)) != 0) + feedback_props->n_imf_mass_bins * sizeof(float)) != 0) error("Failed to allocate IMF bins table"); /* Allocate array to store IMF mass bins in log10 space */ if (swift_memalign( - "imf-tables", (void **)&star_properties->feedback.imf_mass_bin_log10, + "imf-tables", (void **)&feedback_props->imf_mass_bin_log10, SWIFT_STRUCT_ALIGNMENT, - star_properties->feedback.n_imf_mass_bins * sizeof(float)) != 0) + feedback_props->n_imf_mass_bins * sizeof(float)) != 0) error("Failed to allocate IMF bins table"); /* Set IMF from Chabrier 2003 */ - if (strcmp(star_properties->feedback.IMF_Model, "Chabrier") == 0) { - for (int i = 0; i < star_properties->feedback.n_imf_mass_bins; i++) { + if (strcmp(feedback_props->IMF_Model, "Chabrier") == 0) { + for (int i = 0; i < feedback_props->n_imf_mass_bins; i++) { const float log10_mass_msun = - star_properties->feedback.log10_imf_min_mass_msun + + feedback_props->log10_imf_min_mass_msun + i * imf_log10_mass_bin_size; const float mass_msun = exp10f(log10_mass_msun); if (mass_msun > 1.0) - star_properties->feedback.imf[i] = 0.237912 * pow(mass_msun, -2.3); + feedback_props->imf[i] = 0.237912 * pow(mass_msun, -2.3); else - star_properties->feedback.imf[i] = + feedback_props->imf[i] = 0.852464 * exp((log10(mass_msun) - log10(0.079)) * (log10(mass_msun) - log10(0.079)) / (-2.0 * pow(0.69, 2))) / mass_msun; - star_properties->feedback.imf_mass_bin[i] = mass_msun; - star_properties->feedback.imf_mass_bin_log10[i] = log10_mass_msun; + feedback_props->imf_mass_bin[i] = mass_msun; + feedback_props->imf_mass_bin_log10[i] = log10_mass_msun; } } else { error("Invalid IMF model %s. Valid models are: 'Chabrier'\n", - star_properties->feedback.IMF_Model); + feedback_props->IMF_Model); } /* Normalize the IMF */ const float norm = - integrate_imf(star_properties->feedback.log10_imf_min_mass_msun, - star_properties->feedback.log10_imf_max_mass_msun, + integrate_imf(feedback_props->log10_imf_min_mass_msun, + feedback_props->log10_imf_max_mass_msun, eagle_imf_integration_mass_weight, - /*(stellar_yields=)*/ NULL, star_properties); + /*(stellar_yields=)*/ NULL, feedback_props); - for (int i = 0; i < star_properties->feedback.n_imf_mass_bins; i++) - star_properties->feedback.imf[i] /= norm; + for (int i = 0; i < feedback_props->n_imf_mass_bins; i++) + feedback_props->imf[i] /= norm; } /** @@ -279,7 +282,7 @@ inline static void init_imf(struct stars_props *restrict star_properties) { */ inline static double dying_mass_msun(const float age_Gyr, const float metallicity, - const struct stars_props *star_props) { + const struct feedback_props *star_props) { float metallicity_offset, time_offset_low_metallicity = 0, time_offset_high_metallicity = 0, @@ -289,104 +292,104 @@ inline static double dying_mass_msun(const float age_Gyr, time_index_high_metallicity = -1; if (age_Gyr <= 0) { - return star_props->feedback.imf_max_mass_msun; + return star_props->imf_max_mass_msun; } const float log10_age_yr = log10f(age_Gyr * 1.e9); - if (metallicity <= star_props->feedback.lifetimes.metallicity[0]) { + if (metallicity <= star_props->lifetimes.metallicity[0]) { metallicity_index = 0; metallicity_offset = 0.0; } else if (metallicity >= - star_props->feedback.lifetimes - .metallicity[star_props->feedback.lifetimes.n_z - 1]) { - metallicity_index = star_props->feedback.lifetimes.n_z - 2; + star_props->lifetimes + .metallicity[star_props->lifetimes.n_z - 1]) { + metallicity_index = star_props->lifetimes.n_z - 2; metallicity_offset = 1.0; } else { for (metallicity_index = 0; - metallicity_index < star_props->feedback.lifetimes.n_z - 1; + metallicity_index < star_props->lifetimes.n_z - 1; metallicity_index++) - if (star_props->feedback.lifetimes.metallicity[metallicity_index + 1] > + if (star_props->lifetimes.metallicity[metallicity_index + 1] > metallicity) break; metallicity_offset = (metallicity - - star_props->feedback.lifetimes.metallicity[metallicity_index]) / - (star_props->feedback.lifetimes.metallicity[metallicity_index + 1] - - star_props->feedback.lifetimes.metallicity[metallicity_index]); + star_props->lifetimes.metallicity[metallicity_index]) / + (star_props->lifetimes.metallicity[metallicity_index + 1] - + star_props->lifetimes.metallicity[metallicity_index]); } if (log10_age_yr >= - star_props->feedback.lifetimes.dyingtime[metallicity_index][0]) { + star_props->lifetimes.dyingtime[metallicity_index][0]) { time_index_low_metallicity = 0; time_offset_low_metallicity = 0.0; } else if (log10_age_yr <= - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index] - [star_props->feedback.lifetimes.n_mass - 1]) { - time_index_low_metallicity = star_props->feedback.lifetimes.n_mass - 2; + [star_props->lifetimes.n_mass - 1]) { + time_index_low_metallicity = star_props->lifetimes.n_mass - 2; time_offset_low_metallicity = 1.0; } if (log10_age_yr >= - star_props->feedback.lifetimes.dyingtime[metallicity_index + 1][0]) { + star_props->lifetimes.dyingtime[metallicity_index + 1][0]) { time_index_high_metallicity = 0; time_offset_high_metallicity = 0.0; } else if (log10_age_yr <= - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index + 1] - [star_props->feedback.lifetimes.n_mass - 1]) { - time_index_high_metallicity = star_props->feedback.lifetimes.n_mass - 2; + [star_props->lifetimes.n_mass - 1]) { + time_index_high_metallicity = star_props->lifetimes.n_mass - 2; time_offset_high_metallicity = 1.0; } - int i = star_props->feedback.lifetimes.n_mass; + int i = star_props->lifetimes.n_mass; while (i >= 0 && (time_index_low_metallicity == -1 || time_index_high_metallicity == -1)) { i--; - if (star_props->feedback.lifetimes.dyingtime[metallicity_index][i] >= + if (star_props->lifetimes.dyingtime[metallicity_index][i] >= log10_age_yr && time_index_low_metallicity == -1) { time_index_low_metallicity = i; time_offset_low_metallicity = (log10_age_yr - - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index][time_index_low_metallicity]) / - (star_props->feedback.lifetimes + (star_props->lifetimes .dyingtime[metallicity_index][time_index_low_metallicity + 1] - - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index][time_index_low_metallicity]); } - if (star_props->feedback.lifetimes.dyingtime[metallicity_index + 1][i] >= + if (star_props->lifetimes.dyingtime[metallicity_index + 1][i] >= log10_age_yr && time_index_high_metallicity == -1) { time_index_high_metallicity = i; time_offset_high_metallicity = (log10_age_yr - - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index + 1][time_index_high_metallicity]) / - (star_props->feedback.lifetimes + (star_props->lifetimes .dyingtime[metallicity_index + 1] [time_index_high_metallicity + 1] - - star_props->feedback.lifetimes + star_props->lifetimes .dyingtime[metallicity_index + 1][time_index_high_metallicity]); } } mass_low_metallicity = - interpolate_1d(star_props->feedback.lifetimes.mass, + interpolate_1d(star_props->lifetimes.mass, time_index_low_metallicity, time_offset_low_metallicity); mass_high_metallicity = - interpolate_1d(star_props->feedback.lifetimes.mass, + interpolate_1d(star_props->lifetimes.mass, time_index_high_metallicity, time_offset_high_metallicity); float mass = (1.0 - metallicity_offset) * mass_low_metallicity + metallicity_offset * mass_high_metallicity; /* Check that we haven't killed too many stars */ - if (mass > star_props->feedback.imf_max_mass_msun) - mass = star_props->feedback.imf_max_mass_msun; + if (mass > star_props->imf_max_mass_msun) + mass = star_props->imf_max_mass_msun; return mass; } @@ -400,61 +403,61 @@ inline static double dying_mass_msun(const float age_Gyr, * @param star_properties the #stars_props data struct */ inline static float lifetime_in_Gyr(float mass, float metallicity, - const struct stars_props *restrict - star_properties) { + const struct feedback_props *restrict + feedback_props) { double time_Gyr = 0, mass_offset, metallicity_offset; int mass_index, metallicity_index; - if (mass <= star_properties->feedback.lifetimes.mass[0]) { + if (mass <= feedback_props->lifetimes.mass[0]) { mass_index = 0; mass_offset = 0.0; } else if (mass >= - star_properties->feedback.lifetimes - .mass[star_properties->feedback.lifetimes.n_mass - 1]) { - mass_index = star_properties->feedback.lifetimes.n_mass - 2; + feedback_props->lifetimes + .mass[feedback_props->lifetimes.n_mass - 1]) { + mass_index = feedback_props->lifetimes.n_mass - 2; mass_offset = 1.0; } else { for (mass_index = 0; - mass_index < star_properties->feedback.lifetimes.n_mass - 1; + mass_index < feedback_props->lifetimes.n_mass - 1; mass_index++) - if (star_properties->feedback.lifetimes.mass[mass_index + 1] > mass) + if (feedback_props->lifetimes.mass[mass_index + 1] > mass) break; mass_offset = - (mass - star_properties->feedback.lifetimes.mass[mass_index]) / - (star_properties->feedback.lifetimes.mass[mass_index + 1] - - star_properties->feedback.lifetimes.mass[mass_index]); + (mass - feedback_props->lifetimes.mass[mass_index]) / + (feedback_props->lifetimes.mass[mass_index + 1] - + feedback_props->lifetimes.mass[mass_index]); } - if (metallicity <= star_properties->feedback.lifetimes.metallicity[0]) { + if (metallicity <= feedback_props->lifetimes.metallicity[0]) { metallicity_index = 0; metallicity_offset = 0.0; } else if (metallicity >= - star_properties->feedback.lifetimes - .metallicity[star_properties->feedback.lifetimes.n_z - 1]) { - metallicity_index = star_properties->feedback.lifetimes.n_z - 2; + feedback_props->lifetimes + .metallicity[feedback_props->lifetimes.n_z - 1]) { + metallicity_index = feedback_props->lifetimes.n_z - 2; metallicity_offset = 1.0; } else { for (metallicity_index = 0; - metallicity_index < star_properties->feedback.lifetimes.n_z - 1; + metallicity_index < feedback_props->lifetimes.n_z - 1; metallicity_index++) - if (star_properties->feedback.lifetimes + if (feedback_props->lifetimes .metallicity[metallicity_index + 1] > metallicity) break; metallicity_offset = (metallicity - - star_properties->feedback.lifetimes.metallicity[metallicity_index]) / - (star_properties->feedback.lifetimes + feedback_props->lifetimes.metallicity[metallicity_index]) / + (feedback_props->lifetimes .metallicity[metallicity_index + 1] - - star_properties->feedback.lifetimes.metallicity[metallicity_index]); + feedback_props->lifetimes.metallicity[metallicity_index]); } /* time in Gyr */ time_Gyr = - exp(M_LN10 * interpolate_2d(star_properties->feedback.lifetimes.dyingtime, + exp(M_LN10 * interpolate_2d(feedback_props->lifetimes.dyingtime, metallicity_index, mass_index, metallicity_offset, mass_offset)) / 1.0e9; diff --git a/src/feedback/EAGLE/interpolate.h b/src/feedback/EAGLE/interpolate.h index e544d8e2e7cafc2b9e655cd2e2497c720fce14bd..10cf65454c8e3ebed465be885fc721038f7e2379 100644 --- a/src/feedback/EAGLE/interpolate.h +++ b/src/feedback/EAGLE/interpolate.h @@ -16,8 +16,40 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * ******************************************************************************/ -#ifndef SWIFT_EAGLE_STARS_INTERPOLATE_H -#define SWIFT_EAGLE_STARS_INTERPOLATE_H +#ifndef SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H +#define SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H + +#include "error.h" + + +/** + * @brief Returns the 1d index of element with 2d indices i,j + * from a flattened 2d array in row major order + * + * ALEXEI: this function also appears in EAGLE cooling. Could this be done + * without duplication? + * + * @param i, j Indices of element of interest + * @param nx, ny Sizes of array dimensions + */ +__attribute__((always_inline)) INLINE int feedback_row_major_index_2d(int i, + int j, + int nx, + int ny) { + return i * ny + j; +} + +/** + * @brief Returns the 1d index of element with 3d indices i,j,k + * from a flattened 3d array in row major order + * + * @param i, j, k Indices of element of interest + * @param nx, ny, nz Sizes of array dimensions + */ +__attribute__((always_inline)) INLINE int feedback_row_major_index_3d( + int i, int j, int k, int nx, int ny, int nz) { + return i * ny * nz + j * nz + k; +} /** * @brief linear interpolation of 1d table at bin i with offset dx @@ -94,4 +126,4 @@ inline static double interpolate_1D_non_uniform(double* array_x, return result; } -#endif /* SWIFT_EAGLE_STARS_INTERPOLATE_H */ +#endif /* SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H */ diff --git a/src/feedback/EAGLE/yield_tables.h b/src/feedback/EAGLE/yield_tables.h index c82868572fd418a0d2e65ee2d71ed89a597d722b..5844949d8155887ecf1f534d9d71726816e07136 100644 --- a/src/feedback/EAGLE/yield_tables.h +++ b/src/feedback/EAGLE/yield_tables.h @@ -23,35 +23,6 @@ static const float log10_min_metallicity = -20; -/** - * @brief Returns the 1d index of element with 2d indices i,j - * from a flattened 2d array in row major order - * - * ALEXEI: this function also appears in EAGLE cooling. Could this be done - * without duplication? - * - * @param i, j Indices of element of interest - * @param nx, ny Sizes of array dimensions - */ -__attribute__((always_inline)) INLINE int feedback_row_major_index_2d(int i, - int j, - int nx, - int ny) { - return i * ny + j; -} - -/** - * @brief Returns the 1d index of element with 3d indices i,j,k - * from a flattened 3d array in row major order - * - * @param i, j, k Indices of element of interest - * @param nx, ny, nz Sizes of array dimensions - */ -__attribute__((always_inline)) INLINE int feedback_row_major_index_3d( - int i, int j, int k, int nx, int ny, int nz) { - return i * ny * nz + j * nz + k; -} - /** * @brief returns index of element_name within array of element names * (element_array) @@ -78,7 +49,8 @@ inline static int get_element_index(const char *element_name, * * @param stars the #stars_props data structure */ -inline static void read_yield_tables(struct stars_props *restrict stars) { +inline static void read_yield_tables(struct feedback_props *feedback_props) { + #ifdef HAVE_HDF5 int i, j, k, flat_index; @@ -90,7 +62,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { herr_t status; /* Open SNIa tables for reading */ - sprintf(fname, "%s/SNIa.hdf5", stars->feedback.yield_table_path); + sprintf(fname, "%s/SNIa.hdf5", feedback_props->yield_table_path); file_id = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) error("unable to open file %s\n", fname); @@ -99,7 +71,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { H5Tset_size(datatype, H5T_VARIABLE); dataset = H5Dopen(file_id, "Species_names", H5P_DEFAULT); status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.SNIa_element_names); + feedback_props->SNIa_element_names); if (status < 0) error("error reading SNIa element names"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -109,7 +81,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read SNIa yields */ dataset = H5Dopen(file_id, "Yield", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.yields_SNIa); + feedback_props->yields_SNIa); if (status < 0) error("error reading SNIa yields"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -117,7 +89,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read SNIa total metals released */ dataset = H5Dopen(file_id, "Total_Metals", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - &stars->feedback.yield_SNIa_total_metals_IMF_resampled); + &feedback_props->yield_SNIa_total_metals_IMF_resampled); if (status < 0) error("error reading SNIa total metal"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -126,7 +98,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing SNIa file"); /* Open SNII tables for reading */ - sprintf(fname, "%s/SNII.hdf5", stars->feedback.yield_table_path); + sprintf(fname, "%s/SNII.hdf5", feedback_props->yield_table_path); file_id = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) error("unable to open file %s\n", fname); @@ -135,7 +107,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { H5Tset_size(datatype, H5T_VARIABLE); dataset = H5Dopen(file_id, "Species_names", H5P_DEFAULT); status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.SNII_element_names); + feedback_props->SNII_element_names); if (status < 0) error("error reading SNII element names"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -145,7 +117,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read array of masses */ dataset = H5Dopen(file_id, "Masses", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.yield_SNII.mass); + feedback_props->yield_SNII.mass); if (status < 0) error("error reading SNII masses"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -153,17 +125,17 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read array of metallicities */ dataset = H5Dopen(file_id, "Metallicities", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.yield_SNII.metallicity); + feedback_props->yield_SNII.metallicity); if (status < 0) error("error reading SNII metallicities"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); /* declare temporary arrays to read data from HDF5 files */ - double temp_yield_SNII[stars->feedback.SNII_n_elements] - [stars->feedback.SNII_n_mass]; - double temp_ejecta_SNII[stars->feedback.SNII_n_mass], - tempmet1[stars->feedback.SNII_n_mass]; - char *metallicity_yield_table_name_SNII[stars->feedback.SNII_n_z]; + double temp_yield_SNII[feedback_props->SNII_n_elements] + [feedback_props->SNII_n_mass]; + double temp_ejecta_SNII[feedback_props->SNII_n_mass], + tempmet1[feedback_props->SNII_n_mass]; + char *metallicity_yield_table_name_SNII[feedback_props->SNII_n_z]; /* read metallicity names */ datatype = H5Tcopy(H5T_C_S1); @@ -178,7 +150,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing datatype"); /* read SNII yield tables */ - for (i = 0; i < stars->feedback.SNII_n_z; i++) { + for (i = 0; i < feedback_props->SNII_n_z; i++) { /* read yields to temporary array */ sprintf(setname, "/Yields/%s/Yield", metallicity_yield_table_name_SNII[i]); dataset = H5Dopen(file_id, setname, H5P_DEFAULT); @@ -209,17 +181,17 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing dataset"); /* Flatten the temporary tables that were read, store in stars_props */ - for (k = 0; k < stars->feedback.SNII_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.SNII_n_z, - stars->feedback.SNII_n_mass); - stars->feedback.yield_SNII.ejecta[flat_index] = temp_ejecta_SNII[k]; - stars->feedback.yield_SNII.total_metals[flat_index] = tempmet1[k]; + for (k = 0; k < feedback_props->SNII_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->SNII_n_z, + feedback_props->SNII_n_mass); + feedback_props->yield_SNII.ejecta[flat_index] = temp_ejecta_SNII[k]; + feedback_props->yield_SNII.total_metals[flat_index] = tempmet1[k]; - for (j = 0; j < stars->feedback.SNII_n_elements; j++) { + for (j = 0; j < feedback_props->SNII_n_elements; j++) { flat_index = feedback_row_major_index_3d( - i, j, k, stars->feedback.SNII_n_z, stars->feedback.SNII_n_elements, - stars->feedback.SNII_n_mass); - stars->feedback.yield_SNII.yield[flat_index] = temp_yield_SNII[j][k]; + i, j, k, feedback_props->SNII_n_z, feedback_props->SNII_n_elements, + feedback_props->SNII_n_mass); + feedback_props->yield_SNII.yield[flat_index] = temp_yield_SNII[j][k]; } } } @@ -228,7 +200,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing file"); /* Read AGB tables */ - sprintf(fname, "%s/AGB.hdf5", stars->feedback.yield_table_path); + sprintf(fname, "%s/AGB.hdf5", feedback_props->yield_table_path); file_id = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) error("unable to open file %s\n", fname); @@ -237,7 +209,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { H5Tset_size(datatype, H5T_VARIABLE); dataset = H5Dopen(file_id, "Species_names", H5P_DEFAULT); status = H5Dread(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.AGB_element_names); + feedback_props->AGB_element_names); if (status < 0) error("error reading AGB element names"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -247,7 +219,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read array of masses */ dataset = H5Dopen(file_id, "Masses", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.yield_AGB.mass); + feedback_props->yield_AGB.mass); if (status < 0) error("error reading AGB masses"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -255,17 +227,17 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read array of metallicities */ dataset = H5Dopen(file_id, "Metallicities", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.yield_AGB.metallicity); + feedback_props->yield_AGB.metallicity); if (status < 0) error("error reading AGB metallicities"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); /* declare temporary arrays to read data from HDF5 files */ - double temp_yield_AGB[stars->feedback.AGB_n_elements] - [stars->feedback.AGB_n_mass]; - double temp_ejecta_AGB[stars->feedback.AGB_n_mass], - tempmet2[stars->feedback.AGB_n_mass]; - char *metallicity_yield_table_name_AGB[stars->feedback.AGB_n_z]; + double temp_yield_AGB[feedback_props->AGB_n_elements] + [feedback_props->AGB_n_mass]; + double temp_ejecta_AGB[feedback_props->AGB_n_mass], + tempmet2[feedback_props->AGB_n_mass]; + char *metallicity_yield_table_name_AGB[feedback_props->AGB_n_z]; /* read metallicity names */ datatype = H5Tcopy(H5T_C_S1); @@ -280,7 +252,7 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing datatype"); /* read AGB yield tables */ - for (i = 0; i < stars->feedback.AGB_n_z; i++) { + for (i = 0; i < feedback_props->AGB_n_z; i++) { /* read yields to temporary array */ sprintf(setname, "/Yields/%s/Yield", metallicity_yield_table_name_AGB[i]); dataset = H5Dopen(file_id, setname, H5P_DEFAULT); @@ -311,17 +283,17 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing dataset"); /* Flatten the temporary tables that were read, store in stars_props */ - for (k = 0; k < stars->feedback.AGB_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.AGB_n_z, - stars->feedback.AGB_n_mass); - stars->feedback.yield_AGB.ejecta[flat_index] = temp_ejecta_AGB[k]; - stars->feedback.yield_AGB.total_metals[flat_index] = tempmet2[k]; + for (k = 0; k < feedback_props->AGB_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->AGB_n_z, + feedback_props->AGB_n_mass); + feedback_props->yield_AGB.ejecta[flat_index] = temp_ejecta_AGB[k]; + feedback_props->yield_AGB.total_metals[flat_index] = tempmet2[k]; - for (j = 0; j < stars->feedback.AGB_n_elements; j++) { + for (j = 0; j < feedback_props->AGB_n_elements; j++) { flat_index = feedback_row_major_index_3d( - i, j, k, stars->feedback.AGB_n_z, stars->feedback.AGB_n_elements, - stars->feedback.AGB_n_mass); - stars->feedback.yield_AGB.yield[flat_index] = temp_yield_AGB[j][k]; + i, j, k, feedback_props->AGB_n_z, feedback_props->AGB_n_elements, + feedback_props->AGB_n_mass); + feedback_props->yield_AGB.yield[flat_index] = temp_yield_AGB[j][k]; } } } @@ -330,14 +302,14 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { if (status < 0) error("error closing file"); /* open lifetimes table */ - sprintf(fname, "%s/Lifetimes.hdf5", stars->feedback.yield_table_path); + sprintf(fname, "%s/Lifetimes.hdf5", feedback_props->yield_table_path); file_id = H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT); if (file_id < 0) error("unable to open file %s\n", fname); /* read lifetimes mass bins */ dataset = H5Dopen(file_id, "Masses", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.lifetimes.mass); + feedback_props->lifetimes.mass); if (status < 0) error("error reading lifetime table masses"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); @@ -345,23 +317,23 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { /* read metallicity bins */ dataset = H5Dopen(file_id, "Metallicities", H5P_DEFAULT); status = H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, - stars->feedback.lifetimes.metallicity); + feedback_props->lifetimes.metallicity); if (status < 0) error("error reading lifetimes metallicities"); status = H5Dclose(dataset); if (status < 0) error("error closing dataset"); /* allocate temporary array to read lifetimes */ - double temp_lifetimes[stars->feedback.lifetimes.n_z] - [stars->feedback.lifetimes.n_mass]; + double temp_lifetimes[feedback_props->lifetimes.n_z] + [feedback_props->lifetimes.n_mass]; dataset = H5Dopen(file_id, "Lifetimes", H5P_DEFAULT); H5Dread(dataset, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, temp_lifetimes); H5Dclose(dataset); - for (i = 0; i < stars->feedback.lifetimes.n_z; i++) { - for (j = 0; j < stars->feedback.lifetimes.n_mass; j++) { - stars->feedback.lifetimes.dyingtime[i][j] = log10(temp_lifetimes[i][j]); + for (i = 0; i < feedback_props->lifetimes.n_z; i++) { + for (j = 0; j < feedback_props->lifetimes.n_mass; j++) { + feedback_props->lifetimes.dyingtime[i][j] = log10(temp_lifetimes[i][j]); } } @@ -375,80 +347,80 @@ inline static void read_yield_tables(struct stars_props *restrict stars) { * * @param stars the #stars_props data struct to store the tables in */ -inline static void allocate_yield_tables(struct stars_props *restrict stars) { +inline static void allocate_yield_tables(struct feedback_props *feedback_props) { /* Allocate array to store SNIa yield tables */ - if (swift_memalign("feedback-tables", (void **)&stars->feedback.yields_SNIa, + if (swift_memalign("feedback-tables", (void **)&feedback_props->yields_SNIa, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNIa_n_elements * sizeof(double)) != 0) { + feedback_props->SNIa_n_elements * sizeof(double)) != 0) { error("Failed to allocate SNIa yields array"); } /* Allocate array to store SNIa yield table resampled by IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNIa_IMF_resampled, + (void **)&feedback_props->yield_SNIa_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNIa_n_elements * sizeof(double)) != 0) { + feedback_props->SNIa_n_elements * sizeof(double)) != 0) { error("Failed to allocate SNIa IMF resampled yields array"); } /* Allocate array for AGB mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.mass, + (void **)&feedback_props->yield_AGB.mass, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_mass * sizeof(double)) != 0) { + feedback_props->AGB_n_mass * sizeof(double)) != 0) { error("Failed to allocate AGB mass array"); } /* Allocate array for AGB metallicity bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.metallicity, + (void **)&feedback_props->yield_AGB.metallicity, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * sizeof(double)) != 0) { + feedback_props->AGB_n_z * sizeof(double)) != 0) { error("Failed to allocate AGB metallicity array"); } /* Allocate array to store AGB yield tables */ if (swift_memalign( - "feedback-tables", (void **)&stars->feedback.yield_AGB.yield, + "feedback-tables", (void **)&feedback_props->yield_AGB.yield, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.AGB_n_mass * - stars->feedback.AGB_n_elements * sizeof(double)) != 0) { + feedback_props->AGB_n_z * feedback_props->AGB_n_mass * + feedback_props->AGB_n_elements * sizeof(double)) != 0) { error("Failed to allocate AGB yield array"); } /* Allocate array to store AGB yield table resampled by IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.yield_IMF_resampled, + (void **)&feedback_props->yield_AGB.yield_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.n_imf_mass_bins * + feedback_props->AGB_n_z * feedback_props->n_imf_mass_bins * chemistry_element_count * sizeof(double)) != 0) { error("Failed to allocate AGB IMF resampled array"); } /* Allocate array to store AGB ejecta tables */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.ejecta, + (void **)&feedback_props->yield_AGB.ejecta, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.AGB_n_mass * + feedback_props->AGB_n_z * feedback_props->AGB_n_mass * sizeof(double)) != 0) { error("Failed to allocate AGB ejecta array"); } /* Allocate array to store AGB ejecta table resampled by IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.ejecta_IMF_resampled, + (void **)&feedback_props->yield_AGB.ejecta_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.n_imf_mass_bins * + feedback_props->AGB_n_z * feedback_props->n_imf_mass_bins * sizeof(double)) != 0) { error("Failed to allocate AGB ejecta IMF resampled array"); } /* Allocate array to store table of total metals released by AGB */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_AGB.total_metals, + (void **)&feedback_props->yield_AGB.total_metals, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.AGB_n_mass * + feedback_props->AGB_n_z * feedback_props->AGB_n_mass * sizeof(double)) != 0) { error("Failed to allocate AGB total metals array"); } @@ -457,72 +429,72 @@ inline static void allocate_yield_tables(struct stars_props *restrict stars) { * IMF mass bins */ if (swift_memalign( "feedback-tables", - (void **)&stars->feedback.yield_AGB.total_metals_IMF_resampled, + (void **)&feedback_props->yield_AGB.total_metals_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.AGB_n_z * stars->feedback.n_imf_mass_bins * + feedback_props->AGB_n_z * feedback_props->n_imf_mass_bins * sizeof(double)) != 0) { error("Failed to allocate AGB total metals IMF resampled array"); } /* Allocate array for SNII mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.mass, + (void **)&feedback_props->yield_SNII.mass, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_mass * sizeof(double)) != 0) { + feedback_props->SNII_n_mass * sizeof(double)) != 0) { error("Failed to allocate SNII mass array"); } /* Allocate array for SNII metallicity bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.metallicity, + (void **)&feedback_props->yield_SNII.metallicity, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * sizeof(double)) != 0) { + feedback_props->SNII_n_z * sizeof(double)) != 0) { error("Failed to allocate SNII metallicity array"); } /* Allocate array to store SNII yield tables */ if (swift_memalign( - "feedback-tables", (void **)&stars->feedback.yield_SNII.yield, + "feedback-tables", (void **)&feedback_props->yield_SNII.yield, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * stars->feedback.SNII_n_mass * - stars->feedback.SNII_n_elements * sizeof(double)) != 0) { + feedback_props->SNII_n_z * feedback_props->SNII_n_mass * + feedback_props->SNII_n_elements * sizeof(double)) != 0) { error("Failed to allocate SNII yield array"); } /* Allocate array to store SNII yield table resampled by IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.yield_IMF_resampled, + (void **)&feedback_props->yield_SNII.yield_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * - stars->feedback.n_imf_mass_bins * + feedback_props->SNII_n_z * + feedback_props->n_imf_mass_bins * chemistry_element_count * sizeof(double)) != 0) { error("Failed to allocate SNII IMF resampled array"); } /* Allocate array to store SNII ejecta tables */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.ejecta, + (void **)&feedback_props->yield_SNII.ejecta, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * stars->feedback.SNII_n_mass * + feedback_props->SNII_n_z * feedback_props->SNII_n_mass * sizeof(double)) != 0) { error("Failed to allocate SNII ejecta array"); } /* Allocate array to store SNII ejecta table resampled by IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.ejecta_IMF_resampled, + (void **)&feedback_props->yield_SNII.ejecta_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * - stars->feedback.n_imf_mass_bins * sizeof(double)) != + feedback_props->SNII_n_z * + feedback_props->n_imf_mass_bins * sizeof(double)) != 0) { error("Failed to allocate SNII ejecta IMF resampled array"); } /* Allocate array to store table of total metals released by SNII */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_SNII.total_metals, + (void **)&feedback_props->yield_SNII.total_metals, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * stars->feedback.SNII_n_mass * + feedback_props->SNII_n_z * feedback_props->SNII_n_mass * sizeof(double)) != 0) { error("Failed to allocate SNII total metals array"); } @@ -531,69 +503,69 @@ inline static void allocate_yield_tables(struct stars_props *restrict stars) { * IMF mass bins */ if (swift_memalign( "feedback-tables", - (void **)&stars->feedback.yield_SNII.total_metals_IMF_resampled, + (void **)&feedback_props->yield_SNII.total_metals_IMF_resampled, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.SNII_n_z * stars->feedback.n_imf_mass_bins * + feedback_props->SNII_n_z * feedback_props->n_imf_mass_bins * sizeof(double)) != 0) { error("Failed to allocate SNII total metals IMF resampled array"); } /* Allocate array for lifetimes mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.lifetimes.mass, + (void **)&feedback_props->lifetimes.mass, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.lifetimes.n_mass * sizeof(double)) != 0) { + feedback_props->lifetimes.n_mass * sizeof(double)) != 0) { error("Failed to allocate lifetime mass array"); } /* Allocate array for lifetimes metallicity bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.lifetimes.metallicity, + (void **)&feedback_props->lifetimes.metallicity, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.lifetimes.n_z * sizeof(double)) != 0) { + feedback_props->lifetimes.n_z * sizeof(double)) != 0) { error("Failed to allocate lifetime metallicity array"); } /* Allocate lifetimes array */ - stars->feedback.lifetimes.dyingtime = - (double **)malloc(stars->feedback.lifetimes.n_z * sizeof(double *)); - for (int i = 0; i < stars->feedback.lifetimes.n_z; i++) { - stars->feedback.lifetimes.dyingtime[i] = - (double *)malloc(stars->feedback.lifetimes.n_mass * sizeof(double)); + feedback_props->lifetimes.dyingtime = + (double **)malloc(feedback_props->lifetimes.n_z * sizeof(double *)); + for (int i = 0; i < feedback_props->lifetimes.n_z; i++) { + feedback_props->lifetimes.dyingtime[i] = + (double *)malloc(feedback_props->lifetimes.n_mass * sizeof(double)); } /* Allocate SNII factor array */ - if (swift_memalign("feedback-tables", (void **)&stars->feedback.typeII_factor, + if (swift_memalign("feedback-tables", (void **)&feedback_props->typeII_factor, SWIFT_STRUCT_ALIGNMENT, chemistry_element_count * sizeof(double)) != 0) { error("Failed to allocate SNII factor array"); } /* Allocate arrays to store names of elements tracked for SNIa, SNII, AGB */ - stars->feedback.SNIa_element_names = - (char **)malloc(stars->feedback.SNIa_n_elements * sizeof(char *)); - for (int i = 0; i < stars->feedback.SNIa_n_elements; i++) { - stars->feedback.SNIa_element_names[i] = - (char *)malloc(stars->feedback.element_name_length * sizeof(char)); + feedback_props->SNIa_element_names = + (char **)malloc(feedback_props->SNIa_n_elements * sizeof(char *)); + for (int i = 0; i < feedback_props->SNIa_n_elements; i++) { + feedback_props->SNIa_element_names[i] = + (char *)malloc(feedback_props->element_name_length * sizeof(char)); } - stars->feedback.SNII_element_names = - (char **)malloc(stars->feedback.SNII_n_elements * sizeof(char *)); - for (int i = 0; i < stars->feedback.SNII_n_elements; i++) { - stars->feedback.SNII_element_names[i] = - (char *)malloc(stars->feedback.element_name_length * sizeof(char)); + feedback_props->SNII_element_names = + (char **)malloc(feedback_props->SNII_n_elements * sizeof(char *)); + for (int i = 0; i < feedback_props->SNII_n_elements; i++) { + feedback_props->SNII_element_names[i] = + (char *)malloc(feedback_props->element_name_length * sizeof(char)); } - stars->feedback.AGB_element_names = - (char **)malloc(stars->feedback.AGB_n_elements * sizeof(char *)); - for (int i = 0; i < stars->feedback.AGB_n_elements; i++) { - stars->feedback.AGB_element_names[i] = - (char *)malloc(stars->feedback.element_name_length * sizeof(char)); + feedback_props->AGB_element_names = + (char **)malloc(feedback_props->AGB_n_elements * sizeof(char *)); + for (int i = 0; i < feedback_props->AGB_n_elements; i++) { + feedback_props->AGB_element_names[i] = + (char *)malloc(feedback_props->element_name_length * sizeof(char)); } /* Allocate array of IMF mass bins */ if (swift_memalign("feedback-tables", - (void **)&stars->feedback.yield_mass_bins, + (void **)&feedback_props->yield_mass_bins, SWIFT_STRUCT_ALIGNMENT, - stars->feedback.n_imf_mass_bins * sizeof(double)) != 0) { + feedback_props->n_imf_mass_bins * sizeof(double)) != 0) { error("Failed to allocate imf mass bins array"); } } @@ -603,41 +575,41 @@ inline static void allocate_yield_tables(struct stars_props *restrict stars) { * * @param stars the #stars_props data structure */ -inline static void compute_yields(struct stars_props *restrict stars) { +inline static void compute_yields(struct feedback_props *feedback_props) { int flat_index_3d, flat_index_2d; /* convert SNII tables to log10 */ - for (int i = 0; i < stars->feedback.SNII_n_mass; i++) { - stars->feedback.yield_SNII.mass[i] = - log10(stars->feedback.yield_SNII.mass[i]); - } - for (int i = 0; i < stars->feedback.SNII_n_z; i++) { - if (stars->feedback.yield_SNII.metallicity[i] > 0) { - stars->feedback.yield_SNII.metallicity[i] = - log10(stars->feedback.yield_SNII.metallicity[i]); + for (int i = 0; i < feedback_props->SNII_n_mass; i++) { + feedback_props->yield_SNII.mass[i] = + log10(feedback_props->yield_SNII.mass[i]); + } + for (int i = 0; i < feedback_props->SNII_n_z; i++) { + if (feedback_props->yield_SNII.metallicity[i] > 0) { + feedback_props->yield_SNII.metallicity[i] = + log10(feedback_props->yield_SNII.metallicity[i]); } else { - stars->feedback.yield_SNII.metallicity[i] = log10_min_metallicity; + feedback_props->yield_SNII.metallicity[i] = log10_min_metallicity; } } /* convert AGB tables to log10 */ - for (int i = 0; i < stars->feedback.AGB_n_mass; i++) { - stars->feedback.yield_AGB.mass[i] = - log10(stars->feedback.yield_AGB.mass[i]); - } - for (int i = 0; i < stars->feedback.AGB_n_z; i++) { - if (stars->feedback.yield_AGB.metallicity[i] > 0) { - stars->feedback.yield_AGB.metallicity[i] = - log10(stars->feedback.yield_AGB.metallicity[i]); + for (int i = 0; i < feedback_props->AGB_n_mass; i++) { + feedback_props->yield_AGB.mass[i] = + log10(feedback_props->yield_AGB.mass[i]); + } + for (int i = 0; i < feedback_props->AGB_n_z; i++) { + if (feedback_props->yield_AGB.metallicity[i] > 0) { + feedback_props->yield_AGB.metallicity[i] = + log10(feedback_props->yield_AGB.metallicity[i]); } else { - stars->feedback.yield_AGB.metallicity[i] = log10_min_metallicity; + feedback_props->yield_AGB.metallicity[i] = log10_min_metallicity; } } /* Declare temporary tables to accumulate yields */ - double SNII_yield[stars->feedback.SNII_n_mass]; - double AGB_yield[stars->feedback.AGB_n_mass]; + double SNII_yield[feedback_props->SNII_n_mass]; + double AGB_yield[feedback_props->AGB_n_mass]; float result; /* Resample yields for each element tracked in EAGLE */ @@ -646,101 +618,101 @@ inline static void compute_yields(struct stars_props *restrict stars) { elem < chemistry_element_count; elem++) { /* SNIa */ element_index = get_element_index(chemistry_get_element_name(elem), - stars->feedback.SNIa_element_names, - stars->feedback.SNIa_n_elements); - stars->feedback.yield_SNIa_IMF_resampled[elem] = - stars->feedback.yields_SNIa[element_index]; + feedback_props->SNIa_element_names, + feedback_props->SNIa_n_elements); + feedback_props->yield_SNIa_IMF_resampled[elem] = + feedback_props->yields_SNIa[element_index]; /* SNII */ element_index = get_element_index(chemistry_get_element_name(elem), - stars->feedback.SNII_element_names, - stars->feedback.SNII_n_elements); - for (int i = 0; i < stars->feedback.SNII_n_z; i++) { - for (int j = 0; j < stars->feedback.SNII_n_mass; j++) { + feedback_props->SNII_element_names, + feedback_props->SNII_n_elements); + for (int i = 0; i < feedback_props->SNII_n_z; i++) { + for (int j = 0; j < feedback_props->SNII_n_mass; j++) { flat_index_3d = feedback_row_major_index_3d( - i, element_index, j, stars->feedback.SNII_n_z, - stars->feedback.SNII_n_elements, stars->feedback.SNII_n_mass); - SNII_yield[j] = stars->feedback.yield_SNII.yield[flat_index_3d] * - exp(M_LN10 * (-stars->feedback.yield_SNII.mass[j])); + i, element_index, j, feedback_props->SNII_n_z, + feedback_props->SNII_n_elements, feedback_props->SNII_n_mass); + SNII_yield[j] = feedback_props->yield_SNII.yield[flat_index_3d] * + exp(M_LN10 * (-feedback_props->yield_SNII.mass[j])); } - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { - if (stars->feedback.yield_mass_bins[k] < - stars->feedback.yield_SNII.mass[0]) + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { + if (feedback_props->yield_mass_bins[k] < + feedback_props->yield_SNII.mass[0]) result = SNII_yield[0]; - else if (stars->feedback.yield_mass_bins[k] > - stars->feedback.yield_SNII - .mass[stars->feedback.SNII_n_mass - 1]) - result = SNII_yield[stars->feedback.SNII_n_mass - 1]; + else if (feedback_props->yield_mass_bins[k] > + feedback_props->yield_SNII + .mass[feedback_props->SNII_n_mass - 1]) + result = SNII_yield[feedback_props->SNII_n_mass - 1]; else { result = interpolate_1D_non_uniform( - stars->feedback.yield_SNII.mass, SNII_yield, - stars->feedback.SNII_n_mass, stars->feedback.yield_mass_bins[k]); + feedback_props->yield_SNII.mass, SNII_yield, + feedback_props->SNII_n_mass, feedback_props->yield_mass_bins[k]); } flat_index_3d = feedback_row_major_index_3d( - i, elem, k, stars->feedback.SNII_n_z, chemistry_element_count, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_SNII.yield_IMF_resampled[flat_index_3d] = - exp(M_LN10 * stars->feedback.yield_mass_bins[k]) * result; + i, elem, k, feedback_props->SNII_n_z, chemistry_element_count, + feedback_props->n_imf_mass_bins); + feedback_props->yield_SNII.yield_IMF_resampled[flat_index_3d] = + exp(M_LN10 * feedback_props->yield_mass_bins[k]) * result; } } - for (int i = 0; i < stars->feedback.SNII_n_z; i++) { - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { + for (int i = 0; i < feedback_props->SNII_n_z; i++) { + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { flat_index_2d = feedback_row_major_index_2d( - i, k, stars->feedback.SNII_n_z, stars->feedback.n_imf_mass_bins); + i, k, feedback_props->SNII_n_z, feedback_props->n_imf_mass_bins); flat_index_3d = feedback_row_major_index_3d( - i, elem, k, stars->feedback.SNII_n_z, chemistry_element_count, - stars->feedback.n_imf_mass_bins); + i, elem, k, feedback_props->SNII_n_z, chemistry_element_count, + feedback_props->n_imf_mass_bins); if (strcmp(chemistry_get_element_name(elem), "Hydrogen") != 0 || strcmp(chemistry_get_element_name(elem), "Helium") != 0) { - stars->feedback.yield_SNII + feedback_props->yield_SNII .total_metals_IMF_resampled[flat_index_2d] += - (stars->feedback.typeII_factor[elem] - 1) * - stars->feedback.yield_SNII.yield_IMF_resampled[flat_index_3d]; + (feedback_props->typeII_factor[elem] - 1) * + feedback_props->yield_SNII.yield_IMF_resampled[flat_index_3d]; } - stars->feedback.yield_SNII.yield_IMF_resampled[flat_index_3d] *= - stars->feedback.typeII_factor[elem]; + feedback_props->yield_SNII.yield_IMF_resampled[flat_index_3d] *= + feedback_props->typeII_factor[elem]; } } /* AGB */ element_index = get_element_index(chemistry_get_element_name(elem), - stars->feedback.AGB_element_names, - stars->feedback.AGB_n_elements); + feedback_props->AGB_element_names, + feedback_props->AGB_n_elements); if (element_index < 0) { error("element not tracked for AGB"); } else { - for (int i = 0; i < stars->feedback.AGB_n_z; i++) { - for (int j = 0; j < stars->feedback.AGB_n_mass; j++) { + for (int i = 0; i < feedback_props->AGB_n_z; i++) { + for (int j = 0; j < feedback_props->AGB_n_mass; j++) { flat_index_3d = feedback_row_major_index_3d( - i, element_index, j, stars->feedback.AGB_n_z, - stars->feedback.AGB_n_elements, stars->feedback.AGB_n_mass); - AGB_yield[j] = stars->feedback.yield_AGB.yield[flat_index_3d] * - exp(M_LN10 * (-stars->feedback.yield_AGB.mass[j])); + i, element_index, j, feedback_props->AGB_n_z, + feedback_props->AGB_n_elements, feedback_props->AGB_n_mass); + AGB_yield[j] = feedback_props->yield_AGB.yield[flat_index_3d] * + exp(M_LN10 * (-feedback_props->yield_AGB.mass[j])); } - for (int j = 0; j < stars->feedback.n_imf_mass_bins; j++) { - if (stars->feedback.yield_mass_bins[j] < - stars->feedback.yield_AGB.mass[0]) + for (int j = 0; j < feedback_props->n_imf_mass_bins; j++) { + if (feedback_props->yield_mass_bins[j] < + feedback_props->yield_AGB.mass[0]) result = AGB_yield[0]; - else if (stars->feedback.yield_mass_bins[j] > - stars->feedback.yield_AGB - .mass[stars->feedback.AGB_n_mass - 1]) - result = AGB_yield[stars->feedback.AGB_n_mass - 1]; + else if (feedback_props->yield_mass_bins[j] > + feedback_props->yield_AGB + .mass[feedback_props->AGB_n_mass - 1]) + result = AGB_yield[feedback_props->AGB_n_mass - 1]; else result = interpolate_1D_non_uniform( - stars->feedback.yield_AGB.mass, AGB_yield, - stars->feedback.AGB_n_mass, stars->feedback.yield_mass_bins[j]); + feedback_props->yield_AGB.mass, AGB_yield, + feedback_props->AGB_n_mass, feedback_props->yield_mass_bins[j]); flat_index_3d = feedback_row_major_index_3d( - i, elem, j, stars->feedback.AGB_n_z, chemistry_element_count, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_AGB.yield_IMF_resampled[flat_index_3d] = - exp(M_LN10 * stars->feedback.yield_mass_bins[j]) * result; + i, elem, j, feedback_props->AGB_n_z, chemistry_element_count, + feedback_props->n_imf_mass_bins); + feedback_props->yield_AGB.yield_IMF_resampled[flat_index_3d] = + exp(M_LN10 * feedback_props->yield_mass_bins[j]) * result; } } } @@ -752,123 +724,123 @@ inline static void compute_yields(struct stars_props *restrict stars) { * * @param stars the #stars_props data structure */ -inline static void compute_ejecta(struct stars_props *restrict stars) { +inline static void compute_ejecta(struct feedback_props *feedback_props) { /* Declare temporary tables to accumulate yields */ - double SNII_ejecta[stars->feedback.SNII_n_mass]; - double AGB_ejecta[stars->feedback.AGB_n_mass]; + double SNII_ejecta[feedback_props->SNII_n_mass]; + double AGB_ejecta[feedback_props->AGB_n_mass]; float result; int flat_index; /* Resample SNII ejecta */ - for (int i = 0; i < stars->feedback.SNII_n_z; i++) { - for (int k = 0; k < stars->feedback.SNII_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.SNII_n_z, - stars->feedback.SNII_n_mass); - SNII_ejecta[k] = stars->feedback.yield_SNII.ejecta[flat_index] * - exp(M_LN10 * (-stars->feedback.yield_SNII.mass[k])); + for (int i = 0; i < feedback_props->SNII_n_z; i++) { + for (int k = 0; k < feedback_props->SNII_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->SNII_n_z, + feedback_props->SNII_n_mass); + SNII_ejecta[k] = feedback_props->yield_SNII.ejecta[flat_index] * + exp(M_LN10 * (-feedback_props->yield_SNII.mass[k])); } - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { - if (stars->feedback.yield_mass_bins[k] < - stars->feedback.yield_SNII.mass[0]) + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { + if (feedback_props->yield_mass_bins[k] < + feedback_props->yield_SNII.mass[0]) result = SNII_ejecta[0]; - else if (stars->feedback.yield_mass_bins[k] > - stars->feedback.yield_SNII.mass[stars->feedback.SNII_n_mass - 1]) - result = SNII_ejecta[stars->feedback.SNII_n_mass - 1]; + else if (feedback_props->yield_mass_bins[k] > + feedback_props->yield_SNII.mass[feedback_props->SNII_n_mass - 1]) + result = SNII_ejecta[feedback_props->SNII_n_mass - 1]; else result = interpolate_1D_non_uniform( - stars->feedback.yield_SNII.mass, SNII_ejecta, - stars->feedback.SNII_n_mass, stars->feedback.yield_mass_bins[k]); + feedback_props->yield_SNII.mass, SNII_ejecta, + feedback_props->SNII_n_mass, feedback_props->yield_mass_bins[k]); - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_SNII.ejecta_IMF_resampled[flat_index] = - exp(M_LN10 * stars->feedback.yield_mass_bins[k]) * result; + flat_index = feedback_row_major_index_2d(i, k, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + feedback_props->yield_SNII.ejecta_IMF_resampled[flat_index] = + exp(M_LN10 * feedback_props->yield_mass_bins[k]) * result; } } /* resample SNII total metals released */ - for (int i = 0; i < stars->feedback.SNII_n_z; i++) { - for (int k = 0; k < stars->feedback.SNII_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.SNII_n_z, - stars->feedback.SNII_n_mass); - SNII_ejecta[k] = stars->feedback.yield_SNII.total_metals[flat_index] * - exp(M_LN10 * (-stars->feedback.yield_SNII.mass[k])); + for (int i = 0; i < feedback_props->SNII_n_z; i++) { + for (int k = 0; k < feedback_props->SNII_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->SNII_n_z, + feedback_props->SNII_n_mass); + SNII_ejecta[k] = feedback_props->yield_SNII.total_metals[flat_index] * + exp(M_LN10 * (-feedback_props->yield_SNII.mass[k])); } - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { - if (stars->feedback.yield_mass_bins[k] < - stars->feedback.yield_SNII.mass[0]) + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { + if (feedback_props->yield_mass_bins[k] < + feedback_props->yield_SNII.mass[0]) result = SNII_ejecta[0]; - else if (stars->feedback.yield_mass_bins[k] > - stars->feedback.yield_SNII.mass[stars->feedback.SNII_n_mass - 1]) - result = SNII_ejecta[stars->feedback.SNII_n_mass - 1]; + else if (feedback_props->yield_mass_bins[k] > + feedback_props->yield_SNII.mass[feedback_props->SNII_n_mass - 1]) + result = SNII_ejecta[feedback_props->SNII_n_mass - 1]; else result = interpolate_1D_non_uniform( - stars->feedback.yield_SNII.mass, SNII_ejecta, - stars->feedback.SNII_n_mass, stars->feedback.yield_mass_bins[k]); + feedback_props->yield_SNII.mass, SNII_ejecta, + feedback_props->SNII_n_mass, feedback_props->yield_mass_bins[k]); - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.SNII_n_z, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_SNII.total_metals_IMF_resampled[flat_index] = - exp(M_LN10 * stars->feedback.yield_mass_bins[k]) * result; + flat_index = feedback_row_major_index_2d(i, k, feedback_props->SNII_n_z, + feedback_props->n_imf_mass_bins); + feedback_props->yield_SNII.total_metals_IMF_resampled[flat_index] = + exp(M_LN10 * feedback_props->yield_mass_bins[k]) * result; } } /* AGB yields */ - for (int i = 0; i < stars->feedback.AGB_n_z; i++) { - for (int k = 0; k < stars->feedback.AGB_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.AGB_n_z, - stars->feedback.AGB_n_mass); - AGB_ejecta[k] = stars->feedback.yield_AGB.ejecta[flat_index] / - exp(M_LN10 * stars->feedback.yield_AGB.mass[k]); + for (int i = 0; i < feedback_props->AGB_n_z; i++) { + for (int k = 0; k < feedback_props->AGB_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->AGB_n_z, + feedback_props->AGB_n_mass); + AGB_ejecta[k] = feedback_props->yield_AGB.ejecta[flat_index] / + exp(M_LN10 * feedback_props->yield_AGB.mass[k]); } - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { - if (stars->feedback.yield_mass_bins[k] < - stars->feedback.yield_AGB.mass[0]) + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { + if (feedback_props->yield_mass_bins[k] < + feedback_props->yield_AGB.mass[0]) result = AGB_ejecta[0]; - else if (stars->feedback.yield_mass_bins[k] > - stars->feedback.yield_AGB.mass[stars->feedback.AGB_n_mass - 1]) - result = AGB_ejecta[stars->feedback.AGB_n_mass - 1]; + else if (feedback_props->yield_mass_bins[k] > + feedback_props->yield_AGB.mass[feedback_props->AGB_n_mass - 1]) + result = AGB_ejecta[feedback_props->AGB_n_mass - 1]; else result = interpolate_1D_non_uniform( - stars->feedback.yield_AGB.mass, AGB_ejecta, - stars->feedback.AGB_n_mass, stars->feedback.yield_mass_bins[k]); + feedback_props->yield_AGB.mass, AGB_ejecta, + feedback_props->AGB_n_mass, feedback_props->yield_mass_bins[k]); - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_AGB.ejecta_IMF_resampled[flat_index] = - exp(M_LN10 * stars->feedback.yield_mass_bins[k]) * result; + flat_index = feedback_row_major_index_2d(i, k, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + feedback_props->yield_AGB.ejecta_IMF_resampled[flat_index] = + exp(M_LN10 * feedback_props->yield_mass_bins[k]) * result; } } - for (int i = 0; i < stars->feedback.AGB_n_z; i++) { - for (int k = 0; k < stars->feedback.AGB_n_mass; k++) { - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.AGB_n_z, - stars->feedback.AGB_n_mass); - AGB_ejecta[k] = stars->feedback.yield_AGB.total_metals[flat_index] * - exp(M_LN10 * (-stars->feedback.yield_AGB.mass[k])); + for (int i = 0; i < feedback_props->AGB_n_z; i++) { + for (int k = 0; k < feedback_props->AGB_n_mass; k++) { + flat_index = feedback_row_major_index_2d(i, k, feedback_props->AGB_n_z, + feedback_props->AGB_n_mass); + AGB_ejecta[k] = feedback_props->yield_AGB.total_metals[flat_index] * + exp(M_LN10 * (-feedback_props->yield_AGB.mass[k])); } - for (int k = 0; k < stars->feedback.n_imf_mass_bins; k++) { - if (stars->feedback.yield_mass_bins[k] < - stars->feedback.yield_AGB.mass[0]) + for (int k = 0; k < feedback_props->n_imf_mass_bins; k++) { + if (feedback_props->yield_mass_bins[k] < + feedback_props->yield_AGB.mass[0]) result = AGB_ejecta[0]; - else if (stars->feedback.yield_mass_bins[k] > - stars->feedback.yield_AGB.mass[stars->feedback.AGB_n_mass - 1]) - result = AGB_ejecta[stars->feedback.AGB_n_mass - 1]; + else if (feedback_props->yield_mass_bins[k] > + feedback_props->yield_AGB.mass[feedback_props->AGB_n_mass - 1]) + result = AGB_ejecta[feedback_props->AGB_n_mass - 1]; else result = interpolate_1D_non_uniform( - stars->feedback.yield_AGB.mass, AGB_ejecta, - stars->feedback.AGB_n_mass, stars->feedback.yield_mass_bins[k]); + feedback_props->yield_AGB.mass, AGB_ejecta, + feedback_props->AGB_n_mass, feedback_props->yield_mass_bins[k]); - flat_index = feedback_row_major_index_2d(i, k, stars->feedback.AGB_n_z, - stars->feedback.n_imf_mass_bins); - stars->feedback.yield_AGB.total_metals_IMF_resampled[flat_index] = - exp(M_LN10 * stars->feedback.yield_mass_bins[k]) * result; + flat_index = feedback_row_major_index_2d(i, k, feedback_props->AGB_n_z, + feedback_props->n_imf_mass_bins); + feedback_props->yield_AGB.total_metals_IMF_resampled[flat_index] = + exp(M_LN10 * feedback_props->yield_mass_bins[k]) * result; } } } diff --git a/src/feedback_struct.h b/src/feedback_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..be6d480e7a7a6165fd6f73e4ca0ed15078f06488 --- /dev/null +++ b/src/feedback_struct.h @@ -0,0 +1,39 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_FEEDBACK_STRUCT_H +#define SWIFT_FEEDBACK_STRUCT_H + +/** + * @file src/feedback_struct.h + * @brief Branches between the different feedback functions. + */ + +/* Config parameters. */ +#include "../config.h" + +/* Import the right feedback definition */ +#if defined(FEEDBACK_NONE) +#include "./feedback/none/feedback_struct.h" +#elif defined(FEEDBACK_EAGLE) +#include "./feedback/EAGLE/feedback_struct.h" +#else +#error "Invalid choice of feedback function." +#endif + +#endif /* SWIFT_FEEDBACK_STRUCT_H */ diff --git a/src/runner.c b/src/runner.c index 30ae3aa64cbffac6c16a1c0a75eca8f50a79d913..7959a6fe736679bed2b4c5da685d0fbe07dba152 100644 --- a/src/runner.c +++ b/src/runner.c @@ -50,6 +50,7 @@ #include "engine.h" #include "entropy_floor.h" #include "error.h" +#include "feedback.h" #include "gravity.h" #include "hydro.h" #include "hydro_properties.h" diff --git a/src/stars.h b/src/stars.h index bef3cecbd11f26dcd6260aa1f75f3fd37013e96d..dd8390e0206580fc2a07a08e51bb69c6ee5ab5ed 100644 --- a/src/stars.h +++ b/src/stars.h @@ -23,20 +23,14 @@ #include "../config.h" /* Select the correct star model */ -#if defined(FEEDBACK_CONST) -#include "./stars/const/stars.h" -#include "./stars/const/stars_iact.h" -#elif defined(STARS_NONE) +#if defined(STARS_NONE) #include "./stars/Default/stars.h" #include "./stars/Default/stars_iact.h" #elif defined(STARS_EAGLE) #include "./stars/EAGLE/stars.h" #include "./stars/EAGLE/stars_iact.h" -#elif defined(STARS_GEAR) -#include "./stars/GEAR/stars.h" -#include "./stars/GEAR/stars_iact.h" #else #error "Invalid choice of star model" #endif -#endif +#endif /* SWIFT_STARS_H */ diff --git a/src/stars/EAGLE/stars_part.h b/src/stars/EAGLE/stars_part.h index c9dafee7e1e897f4b83d34c8326dcd1dcbd14a23..7bf82d03ecd056e08a339fcca59f891ca74b7f80 100644 --- a/src/stars/EAGLE/stars_part.h +++ b/src/stars/EAGLE/stars_part.h @@ -25,6 +25,7 @@ /* Read chemistry */ #include "chemistry_struct.h" +#include "feedback_struct.h" #include "tracers_struct.h" /** @@ -97,6 +98,9 @@ struct spart { /*! Birth density */ float birth_density; + /*! Feedback structure */ + struct feedback_part_data feedback_data; + /*! Tracer structure */ struct tracers_xpart_data tracers_data;