/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2019 Folkert Nobels (nobels@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 . * ******************************************************************************/ #ifndef SWIFT_COLIBRE_EVENT_LOGGER_R_PROCESSES_H #define SWIFT_COLIBRE_EVENT_LOGGER_R_PROCESSES_H /* Local includes */ #include "event_logger_core.h" #include "event_logger_struct.h" #include "feedback_properties.h" /* MPI headers. */ #ifdef WITH_MPI #include #endif /* feedback history struct for r-processes */ struct feedback_history_r_processes { /* Load the core of logging functions */ struct event_history_logger core; /*! Total new r-processes mass in the simulation */ double NSM_enrichment_mass; double CEJSN_enrichment_mass; double collapsar_enrichment_mass; /*! Number of r-processes events */ int NSM_events; int CEJSN_events; int collapsar_events; }; /** * @brief Initialize the r-processes logger file * * @param e the engine we are running */ INLINE static void event_logger_r_processes_init_log_file( const struct engine *e) { /* Load the structures of the internal units and the physical constants */ const struct unit_system *us = e->internal_units; const struct phys_const *phys_const = e->physical_constants; /* Use the File pointer */ FILE *fp = log_r_processes.core.fp; /* Write some general text to the logger file */ fprintf(fp, "# Stochastic r-processes logger file\n"); fprintf(fp, "######################################################\n"); fprintf(fp, "# The quantities are all given in internal physical units!\n"); fprintf(fp, "#\n"); fprintf(fp, "# (0) Simulation step\n"); fprintf(fp, "# (1) Previous simulation step\n"); fprintf(fp, "# (2) Time since Big Bang (cosmological run), Time since start of " "the simulation (non-cosmological run).\n"); fprintf(fp, "# (3) Previous time since Big Bang (cosmological run), Time since " "start of " "the simulation (non-cosmological run).\n"); fprintf(fp, "# Unit = %e seconds\n", us->UnitTime_in_cgs); fprintf(fp, "# Unit = %e yr or %e Myr\n", 1.f / phys_const->const_year, 1.f / phys_const->const_year / 1e6); fprintf(fp, "# (4) Scale factor (no unit)\n"); fprintf(fp, "# (5) Previous scale factor (no unit)\n"); fprintf(fp, "# (6) Redshift (no unit)\n"); fprintf(fp, "# (7) Previous redshift (no unit)\n"); fprintf(fp, "# (8) Injected mass of r-processes\n"); fprintf(fp, "# Unit = %e g\n", us->UnitMass_in_cgs); fprintf(fp, "# Unit = %e solar mass\n", 1. / phys_const->const_solar_mass); fprintf(fp, "# (9) Injected mass of r-processes per time \n"); fprintf(fp, "# Unit = %e g/s\n", us->UnitMass_in_cgs / us->UnitTime_in_cgs); fprintf(fp, "# Unit = %e solar mass/yr\n", 1. / phys_const->const_solar_mass * phys_const->const_year); fprintf(fp, "# (10) Injected mass of r-processes per time per volume\n"); fprintf(fp, "# Unit = %e g/s/cm^3\n", us->UnitMass_in_cgs / us->UnitTime_in_cgs / pow(us->UnitLength_in_cgs, 3)); fprintf(fp, "# Unit = %e solar mass/yr/Mpc^3\n", 1. / phys_const->const_solar_mass * phys_const->const_year * pow(phys_const->const_parsec * 1e6, 3)); fprintf(fp, "# (11) Number of r-processes (binned in time between current time " "and previous time)\n"); fprintf(fp, "# Unit = no unit\n"); fprintf(fp, "# (12) Number of r-processes per time (binned in time between " "current time " "and previous time).\n"); fprintf(fp, "# Unit = %e #/seconds\n", 1. / us->UnitTime_in_cgs); fprintf(fp, "# Unit = %e #/yr or %e #/Myr\n", phys_const->const_year, phys_const->const_year * 1e6); fprintf(fp, "# (13) Number of r-processes per time per comoving volume (binned " "in time " "between current time and previous time).\n"); fprintf(fp, "# Unit = %e #/seconds/cm^3\n", 1. / us->UnitTime_in_cgs / pow(us->UnitLength_in_cgs, 3)); fprintf(fp, "# Unit = %e #/yr/Mpc^3\n", phys_const->const_year * pow(phys_const->const_parsec * 1e6, 3)); fprintf(fp, "# (14) Number of NSM events (binned in time between current time " "and previous time)\n"); fprintf(fp, "# Unit = no unit\n"); fprintf(fp, "# (15) Number of common-envelop jets SN events (binned in time " "between current time " "and previous time)\n"); fprintf(fp, "# Unit = no unit\n"); fprintf( fp, "# (16) Number of collapsar events (binned in time between current time " "and previous time)\n"); fprintf(fp, "# Unit = no unit\n"); fprintf(fp, "# (17) Injected mass by NSM events\n"); fprintf(fp, "# Unit = %e g\n", us->UnitMass_in_cgs); fprintf(fp, "# Unit = %e solar mass\n", 1. / phys_const->const_solar_mass); fprintf(fp, "# (18) Injected mass by CEJSN events\n"); fprintf(fp, "# Unit = %e g\n", us->UnitMass_in_cgs); fprintf(fp, "# Unit = %e solar mass\n", 1. / phys_const->const_solar_mass); fprintf(fp, "# (19) Injected mass by collapsar events\n"); fprintf(fp, "# Unit = %e g\n", us->UnitMass_in_cgs); fprintf(fp, "# Unit = %e solar mass\n", 1. / phys_const->const_solar_mass); fprintf(fp, "#\n"); fprintf( fp, "# (0) (1) (2) (3) (4) " " (5) (6) (7) (8) (9) " " (10) (11) (12) (13) (14) " " (15) (16) (17) (18) (19)\n"); fprintf(fp, "# step prev. step time prev. time a " " prev a z prev z Inj. mass Inj. mass rate" " Inj.mass rate/V N N rate N rate/V N " " N N Inj. mass Inj. mass Inj. mass\n"); fflush(fp); } /** * @brief Initialize the r-processes global struct * * @param e the engine we are running */ INLINE static void event_logger_r_processes_init(const struct engine *e) { /* Initialize the core variables */ event_logger_core_init(e, &log_r_processes.core); /* Make a constant for the physical constants */ const struct phys_const *phys_const = e->physical_constants; /* Define the swift parameter file */ struct swift_params *params = e->parameter_file; /* Initialize the detla time core value */ const double delta_logger_time_Myr = parser_get_param_double( params, "Event_logger:delta_time_r_processes_Myr"); /* Convert the time to internal units */ log_r_processes.core.delta_logger_time = delta_logger_time_Myr * 1e6 * phys_const->const_year; /* Initialize the energy to zero */ log_r_processes.NSM_enrichment_mass = 0.; log_r_processes.CEJSN_enrichment_mass = 0.; log_r_processes.collapsar_enrichment_mass = 0.; /* Initialize the number of heating events to zero */ log_r_processes.NSM_events = 0; log_r_processes.CEJSN_events = 0; log_r_processes.collapsar_events = 0; } /** * @brief Do a time step and update the r-processes global struct * * @param e the engine we are running */ INLINE static void event_logger_r_processes_time_step(const struct engine *e) { event_logger_core_time_step(e, &log_r_processes.core); } /** * @brief Function that writes to the logger file * * @param e the engine we are running */ INLINE static void event_logger_r_processes_log_data_general( const struct engine *e, const double dt) { /* Get the core struct */ struct event_history_logger *core = &log_r_processes.core; /* Calculate the volume of the box */ const double volume = e->s->dim[0] * e->s->dim[1] * e->s->dim[2]; /* Calculate the inverse of the volume of the box */ const double volume_inv = 1. / volume; /* Calculate Delta time */ const double delta_time = log_r_processes.core.delta_logger_time; /* Calculate the inverse of the delta time */ const double delta_time_inv = 1. / delta_time; /* Get the total number of r-process events */ const int N_r_processes = log_r_processes.NSM_events + log_r_processes.CEJSN_events + log_r_processes.collapsar_events; /* Get the number of NSM, CEJSN and collapsar events separately */ const int N_NSM_events = log_r_processes.NSM_events; const int N_CEJSN_events = log_r_processes.CEJSN_events; const int N_collapsar_events = log_r_processes.collapsar_events; /* Get the total number of r-processes per time */ const double N_r_processes_p_time = (double)N_r_processes * delta_time_inv; /* Get the total number of r-processes per time per volume */ const double N_r_processes_p_time_p_volume = N_r_processes_p_time * volume_inv; /* Get the total enrichment mass */ const double delta_mass = log_r_processes.NSM_enrichment_mass + log_r_processes.CEJSN_enrichment_mass + log_r_processes.collapsar_enrichment_mass; /* Get enrichment mass for each channel */ const double NSM_delta_mass = log_r_processes.NSM_enrichment_mass; const double CEJSN_delta_mass = log_r_processes.CEJSN_enrichment_mass; const double collapsar_delta_mass = log_r_processes.collapsar_enrichment_mass; /* Get the enrichment mass per time */ const double delta_mass_p_time = delta_mass * delta_time_inv; /* Get the enrichment mass per time per volume */ const double delta_mass_p_time_p_volume = delta_mass_p_time * volume_inv; /* Set constants of time */ const double a = e->cosmology->a; const double z = e->cosmology->z; const int step = e->step; const double time = e->time; /* Print the data to the file */ fprintf(core->fp, "%7d %7d %16e %16e %12.7f %12.7f %12.7f %12.7f %12.7e %12.7e " "%12.7e %7d %12.7e %12.7e %7d %7d %7d %12.7e %12.7e %12.7e\n", step, core->step_prev, time, core->time_prev, a, core->a_prev, z, core->z_prev, delta_mass, delta_mass_p_time, delta_mass_p_time_p_volume, N_r_processes, N_r_processes_p_time, N_r_processes_p_time_p_volume, N_NSM_events, N_CEJSN_events, N_collapsar_events, NSM_delta_mass, CEJSN_delta_mass, collapsar_delta_mass); fflush(core->fp); } /** * @brief Write data to the feedback logger file if we are on a write step * * @param e the engine we are running */ INLINE static void event_logger_r_processes_log_data(const struct engine *e) { /* Get the core struct */ struct event_history_logger *core = &log_r_processes.core; /* Are we one a logger time step? */ if (!event_logger_core_log(e, core)) return; /* We need to log */ event_logger_r_processes_log_data_general( e, log_r_processes.core.delta_logger_time); /* Update the logger core */ event_logger_core_update(e, core); /* Update the type specific variables */ log_r_processes.NSM_events = 0; log_r_processes.CEJSN_events = 0; log_r_processes.collapsar_events = 0; log_r_processes.NSM_enrichment_mass = 0.; log_r_processes.CEJSN_enrichment_mass = 0.; log_r_processes.collapsar_enrichment_mass = 0.; } /** * @brief Write data to the feedback logger file on the last time step * * @param e the engine we are running */ INLINE static void event_logger_r_processes_log_data_end( const struct engine *e) { /* Write on the last time step */ if (log_r_processes.core.logger_time_since_last_log > 0. && engine_is_done(e)) event_logger_r_processes_log_data_general( e, log_r_processes.core.logger_time_since_last_log); /* Close the logger file */ fclose(log_r_processes.core.fp); } /** * @brief log a r-process event * * @param si the spart of the enrichment event * @param cosmo the cosmology struct * @param delta_mass the enrichment mass of the r-processes * @param num_events number of events per time step * @param flag, indication of which event: neutron stars (flag==0), rare SN * (flag==1), collapsars (flag==2) */ INLINE static void event_logger_r_processes_log_event( const struct spart *si, const struct cosmology *cosmo, const double delta_mass, const int num_events, const int flag) { if (lock_lock(&log_r_processes.core.lock) == 0) { /* Store the injected mass and add an event */ if (flag == 0) { log_r_processes.NSM_events += num_events; log_r_processes.NSM_enrichment_mass += delta_mass; } if (flag == 1) { log_r_processes.CEJSN_events += num_events; log_r_processes.CEJSN_enrichment_mass += delta_mass; } if (flag == 2) { log_r_processes.collapsar_events += num_events; log_r_processes.collapsar_enrichment_mass += delta_mass; } } if (lock_unlock(&log_r_processes.core.lock) != 0) error("Failed to unlock the lock"); } #ifdef WITH_MPI /** * @brief Do the MPI communication for the r-processes logger * * @param e the engine we are running */ INLINE static void event_logger_r_processes_MPI_Reduce(const struct engine *e) { /* Are we one a logger time step? */ if (!event_logger_core_log(e, &log_r_processes.core)) return; /* Define empty variables for the MPI communication */ int number_events_received_NSM; int number_events_received_CEJSN; int number_events_received_coll; double total_mass_NSM; double total_mass_CEJSN; double total_mass_coll; MPI_Reduce(&log_r_processes.NSM_events, &number_events_received_NSM, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&log_r_processes.CEJSN_events, &number_events_received_CEJSN, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&log_r_processes.collapsar_events, &number_events_received_coll, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&log_r_processes.NSM_enrichment_mass, &total_mass_NSM, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&log_r_processes.CEJSN_enrichment_mass, &total_mass_CEJSN, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(&log_r_processes.collapsar_enrichment_mass, &total_mass_coll, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (e->nodeID != 0) { /* Get the core struct */ struct event_history_logger *core = &log_r_processes.core; /* Update the core struct */ event_logger_core_update(e, core); /* Update the r-process variables */ log_r_processes.NSM_enrichment_mass = 0.; log_r_processes.CEJSN_enrichment_mass = 0.; log_r_processes.collapsar_enrichment_mass = 0.; log_r_processes.NSM_events = 0; log_r_processes.CEJSN_events = 0; log_r_processes.collapsar_events = 0; return; } /* Update the variables for node 0 */ log_r_processes.NSM_enrichment_mass = total_mass_NSM; log_r_processes.CEJSN_enrichment_mass = total_mass_CEJSN; log_r_processes.collapsar_enrichment_mass = total_mass_coll; log_r_processes.NSM_events = number_events_received_NSM; log_r_processes.CEJSN_events = number_events_received_CEJSN; log_r_processes.collapsar_events = number_events_received_coll; } #endif #endif /* SWIFT_COLIBRE_EVENT_LOGGER_R_PROCESSES_H */