/*******************************************************************************
* This file is part of SWIFT.
* Copyright (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 .
*
******************************************************************************/
#ifndef SWIFT_TRACERS_COLIBRE_IO_H
#define SWIFT_TRACERS_COLIBRE_IO_H
/* Config parameters. */
#include
/* Local includes */
#include "black_holes_properties.h"
#include "io_properties.h"
#include "tracers.h"
#ifdef HAVE_HDF5
/**
* @brief Writes the current model of tracers to the file.
*
* @param h_grp The HDF5 group in which to write
*/
__attribute__((always_inline)) INLINE static void tracers_write_flavour(
hid_t h_grp) {
io_write_attribute_s(h_grp, "Tracers", "COLIBRE");
}
#endif
INLINE static void convert_part_averaged_SFR(const struct engine* e,
const struct part* p,
const struct xpart* xp,
float* ret) {
for (int i = 0; i < num_snapshot_triggers_part; ++i) {
if (e->snapshot_recording_triggers_started_part[i])
ret[i] = xp->tracers_data.averaged_SFR[i] /
e->snapshot_recording_triggers_part[i];
else
ret[i] = 0.f;
}
}
INLINE static void convert_spart_averaged_SFR(const struct engine* e,
const struct spart* sp,
float* ret) {
/* Note: We use the 'part' trigger here as the SF would have started when the
* particle was still in gas form */
for (int i = 0; i < num_snapshot_triggers_part; ++i) {
if (e->snapshot_recording_triggers_started_part[i])
ret[i] = sp->tracers_data.averaged_SFR[i] /
e->snapshot_recording_triggers_part[i];
else
ret[i] = 0.f;
}
}
INLINE static void convert_bpart_averaged_accretion_rate(const struct engine* e,
const struct bpart* bp,
float* ret) {
for (int i = 0; i < num_snapshot_triggers_bpart; ++i) {
if (e->snapshot_recording_triggers_started_bpart[i])
ret[i] = bp->tracers_data.averaged_accretion_rate[i] /
e->snapshot_recording_triggers_bpart[i];
else
ret[i] = 0.f;
}
}
/**
* @brief Specifies which particle fields to write to a dataset
*
* @param parts The particle array.
* @param xparts The extended data particle array.
* @param list The list of i/o properties to write.
* @param with_cosmology Are we running with cosmology switched on?
*
* @return Returns the number of fields to write.
*/
__attribute__((always_inline)) INLINE static int tracers_write_particles(
const struct part* parts, const struct xpart* xparts, struct io_props* list,
const int with_cosmology) {
list[0] = io_make_output_field(
"MaximalTemperatures", FLOAT, 1, UNIT_CONV_TEMPERATURE, 0.f, xparts,
tracers_data.maximum_temperature,
"Maximal temperatures ever reached by the particles");
if (with_cosmology) {
list[1] = io_make_physical_output_field(
"MaximalTemperatureScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
xparts, tracers_data.maximum_temperature_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the maximal temperature was reached");
} else {
list[1] = io_make_output_field(
"MaximalTemperatureTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.maximum_temperature_time,
"Times at which the maximal temperature was reached");
}
list[2] = io_make_physical_output_field(
"StellarWindMomentaReceived", FLOAT, 1, UNIT_CONV_MOMENTUM, 0.f, xparts,
tracers_data.stellar_wind_momentum_received,
/*can convert to comoving=*/0,
"Momentum received from stellar winds in physical coordinates");
list[3] = io_make_output_field("HIIregionsEndTime", FLOAT, 1, UNIT_CONV_TIME,
0.f, xparts, tracers_data.HIIregion_timer_gas,
"Time until particle is in HII region");
list[4] = io_make_physical_output_field(
"HIIregionsStarIDs", LONGLONG, 1, UNIT_CONV_NO_UNITS, 0.f, xparts,
tracers_data.HIIregion_starid, /*can convert to comoving=*/0,
"ID of star particle responsible for this HII region");
if (with_cosmology) {
list[5] = io_make_physical_output_field(
"LastSNIIThermalFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, xparts, tracers_data.last_SNII_thermal_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNII thermal "
"feedback. -1 if a particle has never been hit by feedback");
} else {
list[5] = io_make_output_field(
"LastSNIIThermalFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_SNII_thermal_injection_time,
"Times at which the particles were last hit by SNII thermal feedback. "
"-1 if a particle has never been hit by feedback");
}
if (with_cosmology) {
list[6] = io_make_physical_output_field(
"LastSNIaThermalFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, xparts, tracers_data.last_SNIa_thermal_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNIa thermal "
"feedback. -1 if a particle has never been hit by feedback");
} else {
list[6] = io_make_output_field(
"LastSNIaThermalFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_SNIa_thermal_injection_time,
"Times at which the particles were last hit by SNIa thermal feedback. "
"-1 if a particle has never been hit by feedback");
}
if (with_cosmology) {
list[7] = io_make_physical_output_field(
"LastKineticEarlyFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, xparts, tracers_data.last_stellar_wind_kick_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by kinetic early "
"feedback. -1 if a particle has never been hit by feedback");
} else {
list[7] = io_make_output_field(
"LastKineticEarlyFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_stellar_wind_kick_time,
"Times at which the particles were last hit by kinetic early feedback. "
"-1 if a particle has never been hit by feedback");
}
if (with_cosmology) {
list[8] = io_make_physical_output_field(
"LastAGNFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
xparts, tracers_data.last_AGN_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by AGN feedback. "
"-1 if a particle has never been hit by feedback");
} else {
list[8] = io_make_output_field(
"LastAGNFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_AGN_injection_time,
"Times at which the particles were last hit by AGN feedback. -1 if a "
"particle has never been hit by feedback");
}
list[9] = io_make_physical_output_field(
"DensitiesAtLastSupernovaEvent", FLOAT, 1, UNIT_CONV_DENSITY, 0.f, xparts,
tracers_data.density_at_last_SN_thermal_feedback_event,
/*can convert to comoving=*/0,
"Physical density (not subgrid) of the gas at the last SN (type-II or "
"type-Ia) thermal feedback event that hit the particles. -1 if the "
"particles have never been heated.");
list[10] = io_make_physical_output_field(
"TemperatureIncreasesAtLastSupernovaEvent", FLOAT, 1,
UNIT_CONV_TEMPERATURE, 0.f, xparts,
tracers_data.delta_T_at_last_SN_thermal_feedback_event,
/*can convert to comoving=*/0,
"The increase in temperature of the gas at the last SN (type-II or "
"type-Ia) thermal feedback event that hit the particles. -1 if the "
"particles have never been heated.");
list[11] = io_make_physical_output_field(
"EnergiesReceivedFromAGNFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
xparts, tracers_data.AGN_feedback_energy, /*can convert to comoving=*/0,
"Total amount of thermal energy from AGN "
"feedback events received by the particles.");
list[12] = io_make_physical_output_field(
"LastEnergiesReceivedFromAGNFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
xparts, tracers_data.last_AGN_feedback_energy,
/*can convert to comoving=*/0,
"The energy the particles received the "
"last time they were heated by AGN "
"feedback.");
if (with_cosmology) {
list[13] = io_make_physical_output_field(
"LastSNIIKineticFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, xparts, tracers_data.last_SNII_kick_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNII kinetic "
"feedback. -1 if a particle has never been hit by feedback");
} else {
list[13] = io_make_output_field(
"LastSNIIKineticFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_SNII_kick_time,
"Times at which the particles were last hit by SNII kinetic feedback. "
"-1 if a particle has never been hit by feedback");
}
list[14] = io_make_physical_output_field(
"LastSNIIKineticFeedbackvkick", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f, xparts,
tracers_data.last_SNII_kick_velocity, /*can convert to comoving=*/0,
"Physical kick velocity the particles were kicked with at last SNII "
"kinetic feedback event. -1 if a particle has never been hit by "
"feedback");
list[15] = io_make_physical_output_field(
"MaximalSNIIKineticFeedbackvkick", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f,
xparts, tracers_data.max_SNII_kick_velocity,
/*can convert to comoving=*/0,
"Maximal physical kick velocity the particles were kicked with in SNII "
"kinetic feedback. -1 if a particle has never been hit by feedback");
list[16] = io_make_physical_output_field(
"DensitiesAtLastAGNEvent", FLOAT, 1, UNIT_CONV_DENSITY, 0.f, xparts,
tracers_data.density_at_last_AGN_feedback_event,
/*can convert to comoving=*/0,
"Physical density (not subgrid) of the gas at the last AGN feedback "
"event that hit the particles. -1 if the particles have never been "
"heated.");
list[17] = io_make_physical_output_field(
"TemperatureIncreasesAtLastAGNEvent", FLOAT, 1, UNIT_CONV_TEMPERATURE,
0.f, xparts, tracers_data.delta_T_at_last_AGN_feedback_event,
/*can convert to comoving=*/0,
"The increase in temperature of the gas at the last AGN feedback "
"event that hit the particles. -1 if the particles have never been "
"heated.");
if (with_cosmology) {
list[18] = io_make_physical_output_field(
"LastISMScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f, xparts,
tracers_data.last_ISM_scale_factor, /*can convert to comoving=*/0,
"Scale-factor at which the particle was part of the ISM for the last "
"time, i.e. its density was larger than 100 times the mean density and "
"(its neutral fraction larger than 50% OR be an HII region). "
"-1 if the particle was never part of the ISM.");
} else {
list[18] = io_make_physical_output_field(
"LastISMTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_ISM_time, /*can convert to comoving=*/0,
"Time at which the particle was part of the ISM for the last time, "
"i.e. its density was larger than 100 times the mean density and "
"(its neutral fraction larger than 50% OR be an HII region). "
"-1 if the particle was never part of the ISM.");
}
list[19] = io_make_output_field_convert_part(
"AveragedStarFormationRates", FLOAT, 2, UNIT_CONV_SFR, 0.f, parts, xparts,
convert_part_averaged_SFR,
"Star formation rates of the particles averaged over the period set by "
"the first two snapshot triggers");
list[20] = io_make_output_field(
"MinimalSmoothingLengths", FLOAT, 1, UNIT_CONV_LENGTH, 1.f, xparts,
tracers_data.min_h, "Maximal temperatures ever reached by the particles");
if (with_cosmology) {
list[21] = io_make_physical_output_field(
"MinimalSmoothingLengthScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
xparts, tracers_data.min_h_scale_factor, /*can convert to comoving=*/0,
"Scale-factors at which the minimal smoothing length was reached");
} else {
list[21] = io_make_output_field(
"MinimalSmoothingLengthTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.min_h_time,
"Times at which the minimal smoothing length was reached");
}
list[22] = io_make_output_field(
"LastFOFHaloMasses", FLOAT, 1, UNIT_CONV_MASS, 0.f, xparts,
tracers_data.last_halo_mass,
"Masses of the last FOF haloes the particles where part of. -1 if the "
"particle has never been in a FOF group");
if (with_cosmology) {
list[23] = io_make_physical_output_field(
"LastFOFHaloMassesScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
xparts, tracers_data.last_in_halo_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particle was last in a FOF group");
} else {
list[23] = io_make_output_field(
"LastFOFHaloMassesTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_in_halo_time,
"Times at which the particles were last in a FOF group");
}
if (with_jets) {
list[24] = io_make_output_field(
"KickedByJetFeedback", CHAR, 1, UNIT_CONV_NO_UNITS, 0.f, xparts,
tracers_data.hit_by_jet_feedback,
"Flags the particles that have been directly kicked by an AGN jet "
"feedback event at some point in the past. If > 0, contains the number "
"of individual events.");
list[25] = io_make_physical_output_field(
"EnergiesReceivedFromJetFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
xparts, tracers_data.jet_feedback_energy, /*can convert to comoving=*/0,
"Total amount of kinetic energy from AGN jet feedback events received "
"by the particles.");
if (with_cosmology) {
list[26] = io_make_physical_output_field(
"LastAGNJetFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
xparts, tracers_data.last_AGN_jet_feedback_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by jet "
"feedback. -1 if a particle has never been hit by feedback");
} else {
list[26] = io_make_output_field(
"LastAGNJetFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, xparts,
tracers_data.last_AGN_jet_feedback_time,
"Times at which the particles were last hit by jet feedback. "
"-1 if a particle has never been hit by feedback");
}
list[27] = io_make_physical_output_field(
"LastAGNJetKickVelocities", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f, xparts,
tracers_data.last_jet_kick_velocity, /*can convert to comoving=*/0,
"Kick velocity at last AGN jet event.");
list[28] = io_make_output_field(
"LastAGNJetKickMode", CHAR, 1, UNIT_CONV_NO_UNITS, 0.f, xparts,
tracers_data.last_jet_kick_accretion_mode,
"The accretion/feedback mode the BH was in when it kicked this "
"particle. 0 corresponds to the thick disc, 1 to the thin disc and 2 "
"to the slim disc.");
list[29] = io_make_physical_output_field(
"LastAGNJetKickBHId", ULONGLONG, 1, UNIT_CONV_NO_UNITS, 0.f, xparts,
tracers_data.last_jet_kick_BH_id, /*can convert to comoving=*/0,
"The id of the BH that last kicked this "
"particle.");
list[30] = io_make_physical_output_field(
"LastAGNJetFeedbackInitialVolumes", FLOAT, 1, UNIT_CONV_VOLUME, 0.f,
xparts, tracers_data.jet_radio_emission.last_jet_kick_initial_volume,
/*can convert to comoving=*/0,
"The physical volumes the particles had the last time they were heated "
"by AGN.");
list[31] = io_make_physical_output_field(
"JetRadioEmissionShockingIntegrals", FLOAT, 3, UNIT_CONV_ENERGY, 0.f,
xparts, tracers_data.jet_radio_emission.shocking_integrals,
/*can convert to comoving=*/0,
"The integrals over the shocking rates, used for radio emission "
"modeling, in physical frame. The first integral corresponds to the "
"electron integral, the second to the magnetic field integral, and "
"the last to the 'minimum' auxilliary integral (see documentation).");
list[32] = io_make_physical_output_field(
"JetRadioEmissionGammaIntegrals", FLOAT, 2,
UNIT_CONV_ENERGY_DENSITY_TIME, 0.f, xparts,
tracers_data.jet_radio_emission.gamma_integrals,
/*can convert to comoving=*/0,
"Integrals over the synchrotron photon and CMB photon energy "
"densities, respectively, in physical frame. These are used for radio "
"emission modeling (see documentation).");
list[33] = io_make_physical_output_field(
"JetRadioEmissionGammaEffectiveIntegrals", FLOAT, 2,
UNIT_CONV_ENERGY_SQUARED_TIME_PER_UNIT_VOLUME, 0.f, xparts,
tracers_data.jet_radio_emission.gamma_effective_integrals,
/*can convert to comoving=*/0,
"Integrals over the gamma integrals, which are used to compute values "
"weighted by the shock injection rates as a function of time. These "
"are in physical frame.");
list[34] = io_make_physical_output_field(
"WeightedJetInjectionScaleFactors", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
xparts, tracers_data.jet_radio_emission.weighted_injection_scale_factor,
/*can convert to comoving=*/0,
"The integral of the scale factor times shocking rate (injection rate "
"of relativistic electrons), in physical frame. Once divided by a "
"similar integral over the shocking rate, we get a weighted scale "
"factor of when most of the injection occurred.");
return 35;
} else {
return 24;
}
}
__attribute__((always_inline)) INLINE static int tracers_write_sparticles(
const struct spart* sparts, struct io_props* list,
const int with_cosmology) {
list[0] = io_make_output_field(
"MaximalTemperatures", FLOAT, 1, UNIT_CONV_TEMPERATURE, 0.f, sparts,
tracers_data.maximum_temperature,
"Maximal temperatures ever reached by the particles before they got "
"converted to stars");
if (with_cosmology) {
list[1] = io_make_physical_output_field(
"MaximalTemperatureScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
sparts, tracers_data.maximum_temperature_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the maximal temperature was reached");
} else {
list[1] = io_make_output_field(
"MaximalTemperatureTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.maximum_temperature_time,
"Times at which the maximal temperature was reached");
}
list[2] = io_make_physical_output_field(
"StellarWindMomentaReceived", FLOAT, 1, UNIT_CONV_MOMENTUM, 0.f, sparts,
tracers_data.stellar_wind_momentum_received,
/*can convert to comoving=*/0,
"Momentum received by the gas particles from stellar winds before it was "
"converted to a star in physical coordinates");
if (with_cosmology) {
list[3] = io_make_physical_output_field(
"LastSNIIThermalFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, sparts, tracers_data.last_SNII_thermal_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNII thermal "
"feedback when they were still gas particles. -1 if a particle has "
"never been hit by feedback");
} else {
list[3] = io_make_output_field(
"LastSNIIThermalFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.last_SNII_thermal_injection_time,
"Times at which the particles were last hit by SNII thermal feedback "
"when they were still gas particles. -1 if a particle has never been "
"hit by feedback");
}
if (with_cosmology) {
list[4] = io_make_physical_output_field(
"LastSNIaThermalFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, sparts, tracers_data.last_SNIa_thermal_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNIa thermal "
"feedback when they were still gas particles. -1 if a particle has "
"never been hit by feedback");
} else {
list[4] = io_make_output_field(
"LastSNIaThermalFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.last_SNIa_thermal_injection_time,
"Times at which the particles were last hit by SNIa thermal feedback "
"when they were still gas particles. -1 if a particle has never been "
"hit by feedback");
}
if (with_cosmology) {
list[5] = io_make_physical_output_field(
"LastKineticEarlyFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, sparts, tracers_data.last_stellar_wind_kick_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by kinetic early "
"feedback when they were still gas particles. -1 if a particle has "
"never been hit by feedback");
} else {
list[5] = io_make_output_field(
"LastKineticEarlyFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.last_stellar_wind_kick_time,
"Times at which the particles were last hit by kinetic early feedback "
"when they were still gas particles. -1 if a particle has never been "
"hit by feedback");
}
if (with_cosmology) {
list[6] = io_make_physical_output_field(
"LastAGNFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
sparts, tracers_data.last_AGN_injection_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by AGN feedback "
"when they were still gas particles. -1 if a particle has never been "
"hit by feedback");
} else {
list[6] =
io_make_output_field("LastAGNFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME,
0.f, sparts, tracers_data.last_AGN_injection_time,
"Times at which the particles were last hit by "
"AGN feedback when they were still gas particles. "
"-1 if a particle has never been hit by feedback");
}
list[7] = io_make_physical_output_field(
"DensitiesAtLastSupernovaEvent", FLOAT, 1, UNIT_CONV_DENSITY, 0.f, sparts,
tracers_data.density_at_last_SN_thermal_feedback_event,
/*can convert to comoving=*/0,
"Physical density (not subgrid) of the gas at the last SN (type-II or "
"type-Ia) thermal feedback event that hit the particles when they were "
"still gas particles. -1 if the particles have never been heated.");
list[8] = io_make_physical_output_field(
"TemperatureIncreasesAtLastSupernovaEvent", FLOAT, 1,
UNIT_CONV_TEMPERATURE, 0.f, sparts,
tracers_data.delta_T_at_last_SN_thermal_feedback_event,
/*can convert to comoving=*/0,
"The increase in temperature of the gas at the last SN (type-II or "
"type-Ia) thermal feedback event that hit the particles when they were "
"still gas particles. -1 if the particles have never been heated.");
list[9] = io_make_physical_output_field(
"EnergiesReceivedFromAGNFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
sparts, tracers_data.AGN_feedback_energy,
/*can convert to comoving=*/0,
"Total amount of thermal energy from AGN feedback events received by the "
"particles when the particles were still gas particles.");
list[10] = io_make_physical_output_field(
"LastEnergiesReceivedFromAGNFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
sparts, tracers_data.last_AGN_feedback_energy,
/*can convert to comoving=*/0,
"The energy the particles received the last time they were heated by AGN "
"feedback while they were still gas particles.");
if (with_cosmology) {
list[11] = io_make_physical_output_field(
"LastSNIIKineticFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS,
0.f, sparts, tracers_data.last_SNII_kick_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by SNII kinetic "
"feedback when they were still gas particles. -1 if a particle has "
"never been hit by feedback");
} else {
list[11] = io_make_output_field(
"LastSNIIKineticFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.last_SNII_kick_time,
"Times at which the particles were last hit by SNII kinetic feedback "
"when they were still gas particles. -1 if a particle has never been "
"hit by feedback");
}
list[12] = io_make_physical_output_field(
"LastSNIIKineticFeedbackvkick", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f, sparts,
tracers_data.last_SNII_kick_velocity, /*can convert to comoving=*/0,
"Physical kick velocity at last SNII kinetic feedback event when the "
"stellar particles were kicked with when they were still gas particles. "
"-1 if a particle has never been hit by feedback");
list[13] = io_make_physical_output_field(
"MaximalSNIIKineticFeedbackvkick", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f,
sparts, tracers_data.max_SNII_kick_velocity,
/*can convert to comoving=*/0,
"Maximal physical kick velocity in SNII kinetic feedback when the stellar"
" particles were kicked with when they were still gas particles. -1 if a"
" particle has never been hit by feedback");
list[14] = io_make_physical_output_field(
"DensitiesAtLastAGNEvent", FLOAT, 1, UNIT_CONV_DENSITY, 0.f, sparts,
tracers_data.density_at_last_AGN_feedback_event,
/*can convert to comoving=*/0,
"Physical density (not subgrid) of the gas at the last AGN feedback "
"event that hit the particles when they were still gas particles. -1 if "
"the particles have never been heated.");
list[15] = io_make_physical_output_field(
"TemperatureIncreasesAtLastAGNEvent", FLOAT, 1, UNIT_CONV_TEMPERATURE,
0.f, sparts, tracers_data.delta_T_at_last_AGN_feedback_event,
/*can convert to comoving=*/0,
"The increase in temperature of the gas at the last AGN feedback "
"event that hit the particles when they were still gas particles. -1 if "
"the particles have never been heated.");
list[16] = io_make_output_field_convert_spart(
"AveragedStarFormationRates", FLOAT, num_snapshot_triggers_part,
UNIT_CONV_SFR, 0.f, sparts, convert_spart_averaged_SFR,
"Star formation rates of the particles averaged over the period set by "
"the first two snapshot triggers when the particle was still a gas "
"particle.");
list[17] =
io_make_output_field("LastFOFHaloMasses", FLOAT, 1, UNIT_CONV_MASS, 0.f,
sparts, tracers_data.last_halo_mass,
"Masses of the last FOF haloes the particles where "
"part of when they were still a gas particle. -1 if "
"the particle has never been in a FOF group");
if (with_cosmology) {
list[18] = io_make_physical_output_field(
"LastFOFHaloMassesScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
sparts, tracers_data.last_in_halo_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particle was last in a FOF group when they "
"were still a gas particle");
} else {
list[18] =
io_make_output_field("LastFOFHaloMassesTimes", FLOAT, 1, UNIT_CONV_TIME,
0.f, sparts, tracers_data.last_in_halo_time,
"Times at which the particles were last in a FOF "
"group when they were still a gas particle");
}
if (with_jets) {
list[19] = io_make_output_field(
"KickedByJetFeedback", CHAR, 1, UNIT_CONV_NO_UNITS, 0.f, sparts,
tracers_data.hit_by_jet_feedback,
"Flags the particles that have been directly kicked by"
"an AGN jet feedback event at some point in the past. "
"If > 0, contains the number of individual events.");
list[20] = io_make_physical_output_field(
"EnergiesReceivedFromJetFeedback", FLOAT, 1, UNIT_CONV_ENERGY, 0.f,
sparts, tracers_data.jet_feedback_energy, /*can convert to comoving=*/0,
"Total amount of kinetic energy from AGN jet feedback events received "
"by the particles while they were still gas particles.");
if (with_cosmology) {
list[21] = io_make_physical_output_field(
"LastAGNJetFeedbackScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f,
sparts, tracers_data.last_AGN_jet_feedback_scale_factor,
/*can convert to comoving=*/0,
"Scale-factors at which the particles were last hit by jet "
"feedback while they were still gas particles. "
"-1 if a particle has never been hit by feedback");
} else {
list[21] = io_make_output_field(
"LastAGNJetFeedbackTimes", FLOAT, 1, UNIT_CONV_TIME, 0.f, sparts,
tracers_data.last_AGN_jet_feedback_time,
"Times at which the particles were last hit by jet"
"feedback while they were still gas particles. "
"-1 if a particle has never been hit by feedback");
}
list[22] = io_make_physical_output_field(
"LastAGNJetKickVelocities", FLOAT, 1, UNIT_CONV_VELOCITY, 0.f, sparts,
tracers_data.last_jet_kick_velocity, /*can convert to comoving=*/0,
"Kick velocity at last AGN jet event.");
list[23] = io_make_output_field("LastAGNJetKickMode", CHAR, 1,
UNIT_CONV_NO_UNITS, 0.f, sparts,
tracers_data.last_jet_kick_accretion_mode,
"The accretion/feedback mode the BH was "
"in when it kicked this particle. 0 "
"corresponds to the thick disc, 1 to the "
"thin disc and 2 to the slim disc.");
list[24] = io_make_physical_output_field(
"LastAGNJetKickBHId", ULONGLONG, 1, UNIT_CONV_NO_UNITS, 0.f, sparts,
tracers_data.last_jet_kick_BH_id, /*can convert to comoving=*/0,
"The id of the BH that last kicked this particle.");
return 25;
} else {
return 19;
}
}
__attribute__((always_inline)) INLINE static int tracers_write_bparticles(
const struct bpart* bparts, struct io_props* list,
const int with_cosmology) {
list[0] = io_make_output_field_convert_bpart(
"AveragedAccretionRates", FLOAT, num_snapshot_triggers_bpart,
UNIT_CONV_MASS_PER_UNIT_TIME, 0.f, bparts,
convert_bpart_averaged_accretion_rate,
"Accretion rates of the black holes averaged over the period set by the "
"first two snapshot triggers");
list[1] =
io_make_output_field("MinimalTimeBins", CHAR, 1, UNIT_CONV_NO_UNITS, 0.f,
bparts, tracers_data.min_time_bin,
"Minimal Time Bins reached by the black holes");
if (with_cosmology) {
list[2] = io_make_physical_output_field(
"MinimalTimeBinScaleFactors", FLOAT, 1, UNIT_CONV_NO_UNITS, 0.f, bparts,
tracers_data.min_time_bin_scale_factor, /*can convert to comoving=*/0,
"Scale-factors at which the minimal time-bin was reached");
} else {
list[2] =
io_make_output_field("MinimalTimeBinTimes", FLOAT, 1, UNIT_CONV_TIME,
0.f, bparts, tracers_data.min_time_bin_time,
"Times at which the minimal time-bin was reached");
}
return 3;
}
#endif /* SWIFT_TRACERS_COLIBRE_IO_H */