https://github.com/Azeret/galIMF
Revision d829ac3ec2c599f5d56a3d16ee62a6b56eb47d42 authored by juzikong on 18 September 2019, 11:32:21 UTC, committed by GitHub on 18 September 2019, 11:32:21 UTC
1 parent b615fad
Tip revision: d829ac3ec2c599f5d56a3d16ee62a6b56eb47d42 authored by juzikong on 18 September 2019, 11:32:21 UTC
Update README.md
Update README.md
Tip revision: d829ac3
galevo.py
# A python3 code
# This is a single-zone closed-box galaxy chemical evolution module.
# It is coupled with a variable galaxy-wide IMF that depends on the galactic property at the time of star formation.
# The stellar population forms at every 10 Myr (the shortest time step) over 10 Gyr;
# with each stellar population a different galaxy-wide IMF calculated using the IGIMF theory (the galimf.py model).
# The parameters assumed for the simulation are specified at the end of this file or imported from other files,
# i.e., element_weight_table.py, element_abundances_solar.py, element_abundances_primordial.py.
import numpy as np
import time
import math
import importlib
from scipy.integrate import quad
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import gc
import sys
import warnings
import os
import errno
warnings.filterwarnings("ignore")
sys.path.insert(0, 'Generated_IGIMFs')
sys.path.insert(0, 'IMFs')
sys.path.insert(0, 'yield_tables')
import element_weight_table, element_abundances_solar, element_abundances_primordial, stellar_luminosity
from IMFs import Kroupa_IMF, diet_Salpeter_IMF
from yield_tables import SNIa_yield
def galaxy_evol(imf='igimf', STF=0.5, SFEN=1, Z_0=0.000000134, solar_mass_component='Anders1989_mass',
str_yield_table='portinari98',
IMF_name='Kroupa', steller_mass_upper_bound=150,
time_resolution_in_Myr=1, mass_boundary_observe_low=1.5, mass_boundary_observe_up=8,
SFH_model='provided', SFE=0.05,
SNIa_ON=True, SNIa_yield_table='Thielemann1993', solar_abu_table='Anders1989',
high_time_resolution=None, plot_show=None, plot_save=None, outflow=None, check_igimf=False):
start_time = time.time()
######################
# If imf='igimf', the model will use variable IMF, imf='Kroupa' will use Kroupa IMF
# A 1 in SFH.txt stand for SFR = 1 [solar mass/year] in a 10 Myr epoch.
# STF is the total stellar mass/total gas mass in 13Gyr, which determines the initial gas mass. See Yan et al. 2019
# Z_0 is the initial metallicity
######################
global igimf_mass_function, mass_grid_table, mass_grid_table2, Mfinal_table, Mmetal_table, M_element_table
global time_axis, gas_Z_over_X_list, total_star_formed, \
O_over_H_list, Mg_over_H_list, C_over_H_list, N_over_H_list, Ca_over_H_list, Fe_over_H_list, \
S_over_H_list, Si_over_H_list, Ne_over_H_list, \
S_over_H_list, Si_over_H_list, Ne_over_H_list, X_list, Y_list, Z_list, \
ejected_O_mass_till_this_time_tot_list, ejected_O_mass_till_this_time_SNII_list, ejected_O_mass_till_this_time_SNIa_list, \
ejected_Mg_mass_till_this_time_tot_list, ejected_Mg_mass_till_this_time_SNII_list, ejected_Mg_mass_till_this_time_SNIa_list, \
ejected_Fe_mass_till_this_time_tot_list, ejected_Fe_mass_till_this_time_SNII_list, ejected_Fe_mass_till_this_time_SNIa_list, \
ejected_S_mass_till_this_time_tot_list, ejected_S_mass_till_this_time_SNII_list, ejected_S_mass_till_this_time_SNIa_list, \
ejected_Si_mass_till_this_time_tot_list, ejected_Si_mass_till_this_time_SNII_list, ejected_Si_mass_till_this_time_SNIa_list, \
ejected_Ne_mass_till_this_time_tot_list, ejected_Ne_mass_till_this_time_SNII_list, ejected_Ne_mass_till_this_time_SNIa_list, \
ejected_Ca_mass_till_this_time_tot_list, ejected_Ca_mass_till_this_time_SNII_list, ejected_Ca_mass_till_this_time_SNIa_list, \
Mg_over_Fe_list, C_over_Fe_list, N_over_Fe_list, Ca_over_Fe_list, O_over_Fe_list, S_over_Fe_list, Si_over_Fe_list, Ne_over_Fe_list, \
stellar_O_over_H_list, stellar_Mg_over_H_list, stellar_C_over_H_list, stellar_N_over_H_list, \
stellar_Ca_over_H_list, stellar_Fe_over_H_list, stellar_Si_over_H_list, stellar_S_over_H_list, stellar_Ne_over_H_list, \
stellar_X_list, stellar_Y_list, stellar_Z_list, \
stellar_Mg_over_Fe_list, stellar_C_over_Fe_list, stellar_N_over_Fe_list, stellar_Ca_over_Fe_list, \
stellar_S_over_Fe_list, stellar_Si_over_Fe_list, stellar_Ne_over_Fe_list, \
stellar_O_over_Fe_list, stellar_Z_over_X_list, stellar_Z_over_H_list, \
stellar_O_over_H_list_luminosity_weighted, stellar_Mg_over_H_list_luminosity_weighted, \
stellar_C_over_H_list_luminosity_weighted, stellar_N_over_H_list_luminosity_weighted, \
stellar_Ca_over_H_list_luminosity_weighted, stellar_Ne_over_H_list_luminosity_weighted, stellar_Si_over_H_list_luminosity_weighted, stellar_S_over_H_list_luminosity_weighted, \
stellar_X_list_luminosity_weighted, stellar_Y_list_luminosity_weighted, stellar_Z_list_luminosity_weighted, \
stellar_Fe_over_H_list_luminosity_weighted, stellar_Mg_over_Fe_list_luminosity_weighted, \
stellar_C_over_Fe_list_luminosity_weighted, stellar_N_over_Fe_list_luminosity_weighted, \
stellar_Ca_over_Fe_list_luminosity_weighted, stellar_O_over_Fe_list_luminosity_weighted, \
stellar_S_over_Fe_list_luminosity_weighted, stellar_Si_over_Fe_list_luminosity_weighted, stellar_Ne_over_Fe_list_luminosity_weighted, \
stellar_Z_over_X_list_luminosity_weighted, stellar_Z_over_H_list_luminosity_weighted, \
remnant_mass_list, total_gas_mass_list, stellar_mass_list, \
ejected_gas_mass_list, ejected_metal_mass_list, \
ejected_gas_Mg_over_Fe_list, instant_ejected_gas_Mg_over_Fe_list, expansion_factor_list, \
expansion_factor_instantaneous_list, expansion_factor_adiabat_list
global SNIa_energy_release_list, SNIa_number_list, SNIa_number_per_century, \
SNII_energy_release_list, SNII_number_list, SNII_number_per_century, \
total_energy_release_list, SN_number_per_century, total_gas_kinetic_energy_list, original_gas_mass # , binding_energy_list
global BH_mass_list, NS_mass_list, WD_mass_list, all_sf_imf, all_sfr
global times_calculate_igimf, instantaneous_recycling
instantaneous_recycling = False
times_calculate_igimf = 0
###################
### preparation ###
###################
# Warning flags:
Warning_ejected_gas_mass_of_this_epoch = False
Warning_WD_mass_till_this_time = False
Warning_galaxy_mass_ejected_gas_mass = False
# get all avaliable metallicity from stellar evolution table
(Z_table_list, Z_table_list_2, Z_table_list_3) = function_get_avaliable_Z(str_yield_table)
# read in SFH
SFH_input = np.loadtxt('SFH.txt')
length_list_SFH_input = len(SFH_input)
i = 0
total_SF = 0
while i < length_list_SFH_input:
total_SF += SFH_input[i]
(i) = (i + 1)
# Star Trasnformation fraction (STF)
total_star_formed = 10 ** 7 * total_SF
original_gas_mass = total_star_formed / STF # in solar mass unit
# print("original_gas_mass =", math.log(original_gas_mass, 10))
# Create the time steps (x axis) for final output
time_axis = [10**6]
time_resolution = time_resolution_in_Myr * 10 ** 5 * 10
for i in range(10 ** 9, 15 * 10 ** 9, time_resolution * 1000):
time_axis += [i]
if high_time_resolution==True:
for i in range(10 ** 7, 10 ** 8, time_resolution * 10):
time_axis += [i]
for i in range(10 ** 8, 10 ** 9, time_resolution * 100):
time_axis += [i]
else:
plot_at_age = [5 * 10 ** 7, 1 * 10 ** 8, 5 * 10 ** 8, 1 * 10 ** 9, 9 * 10 ** 9, 10 * 10 ** 9, 11 * 10 ** 9]
# plot_at_age = [1 * 10 ** 8, 1 * 10 ** 9, 10.8 * 10 ** 9]
time_axis += plot_at_age
for i in range(10 ** 9, 15 * 10 ** 9, time_resolution * 1000):
time_axis += [i]
# consider also all star formation event happend times
# where the time resolution should be temporarily increased.
time_axis_for_SFH_input = []
time_axis_for_SFH_input_D = []
i = 0
while i < length_list_SFH_input:
if SFH_input[i] > 0:
if high_time_resolution == True:
time_axis_for_SFH_input += [i * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 1 * 10 ** 4]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 4]
time_axis_for_SFH_input += [i * 10 ** 7 + 7 * 10 ** 4]
time_axis_for_SFH_input += [i * 10 ** 7 + 8 * 10 ** 4]
time_axis_for_SFH_input += [i * 10 ** 7 + 9 * 10 ** 4]
time_axis_for_SFH_input += [i * 10 ** 7 + 1 * 10 ** 5]
time_axis_for_SFH_input += [i * 10 ** 7 + 2 * 10 ** 5]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 5]
time_axis_for_SFH_input += [i * 10 ** 7 + 1 * 10 ** 6]
time_axis_for_SFH_input += [i * 10 ** 7 + 2 * 10 ** 6]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 6]
time_axis_for_SFH_input += [i * 10 ** 7 + 1 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 2 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 3 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 4 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 6 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 7 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 8 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 9 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 10 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 11 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 12 * 10 ** 7]
time_axis_for_SFH_input += [i * 10 ** 7 + 2 * 10 ** 8]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 8]
time_axis_for_SFH_input += [i * 10 ** 7 + 1 * 10 ** 9]
time_axis_for_SFH_input += [i * 10 ** 7 + 2 * 10 ** 9]
time_axis_for_SFH_input += [i * 10 ** 7 + 5 * 10 ** 9]
else:
time_axis_for_SFH_input += [i * 10 ** 7]
# time_axis_for_SFH_input += [i * 10 ** 7 + 9 * 10 ** 6]
(i) = (i + 1)
# the final time axis is the sorted combination of the two
time_axis = sorted(list(set(time_axis + time_axis_for_SFH_input)))
# print("\nSimulation results will be give at galactic age [yr] =\n", time_axis)
length_list_time_step = len(time_axis)
###################
### main loop ###
###################
S_F_R_of_this_epoch_list = []
S_F_F = 1
# define an array save SF event informations that will be used in every latter time steps
all_sf_imf = []
all_sfr = []
epoch_info = [] # This array saves the properties,
# i.e., [S_F_R_of_this_epoch, M_tot_of_this_epoch, igimf_mass_function, igimf_normalization],
# of all the stellar populations formed at different time step (the so-called star formation epoch),
# Thus that at any later given time (aging), the effects (yield) of these populations can be easily computed.
BH_mass_list = []
NS_mass_list = []
WD_mass_list = []
gas_Z_over_X_list = []
O_over_H_list = []
ejected_O_mass_till_this_time_tot_list = []
ejected_O_mass_till_this_time_SNII_list = []
ejected_O_mass_till_this_time_SNIa_list = []
ejected_Mg_mass_till_this_time_tot_list = []
ejected_Mg_mass_till_this_time_SNII_list = []
ejected_Mg_mass_till_this_time_SNIa_list = []
ejected_Fe_mass_till_this_time_tot_list = []
ejected_Fe_mass_till_this_time_SNII_list = []
ejected_Fe_mass_till_this_time_SNIa_list = []
ejected_Ca_mass_till_this_time_tot_list = []
ejected_Ca_mass_till_this_time_SNII_list = []
ejected_Ca_mass_till_this_time_SNIa_list = []
ejected_S_mass_till_this_time_tot_list = []
ejected_S_mass_till_this_time_SNII_list = []
ejected_S_mass_till_this_time_SNIa_list = []
ejected_Si_mass_till_this_time_tot_list = []
ejected_Si_mass_till_this_time_SNII_list = []
ejected_Si_mass_till_this_time_SNIa_list = []
ejected_Ne_mass_till_this_time_tot_list = []
ejected_Ne_mass_till_this_time_SNII_list = []
ejected_Ne_mass_till_this_time_SNIa_list = []
X_list = []
Y_list = []
Z_list = []
Mg_over_H_list = []
C_over_H_list = []
N_over_H_list = []
Ca_over_H_list = []
Ne_over_H_list = []
Si_over_H_list = []
S_over_H_list = []
Fe_over_H_list = []
Mg_over_Fe_list = []
C_over_Fe_list = []
N_over_Fe_list = []
Ca_over_Fe_list = []
Ne_over_Fe_list = []
Si_over_Fe_list = []
S_over_Fe_list = []
O_over_Fe_list = []
stellar_O_over_H_list = []
stellar_Mg_over_H_list = []
stellar_C_over_H_list = []
stellar_N_over_H_list = []
stellar_Ca_over_H_list = []
stellar_Ne_over_H_list = []
stellar_Si_over_H_list = []
stellar_S_over_H_list = []
stellar_Fe_over_H_list = []
stellar_X_list = []
stellar_Y_list = []
stellar_Z_list = []
stellar_Mg_over_Fe_list = []
stellar_C_over_Fe_list = []
stellar_N_over_Fe_list = []
stellar_Ca_over_Fe_list = []
stellar_Ne_over_Fe_list = []
stellar_Si_over_Fe_list = []
stellar_S_over_Fe_list = []
stellar_O_over_Fe_list = []
stellar_Z_over_X_list = []
stellar_Z_over_H_list = []
stellar_O_over_H_list_luminosity_weighted = []
stellar_Mg_over_H_list_luminosity_weighted = []
stellar_C_over_H_list_luminosity_weighted = []
stellar_N_over_H_list_luminosity_weighted = []
stellar_Ca_over_H_list_luminosity_weighted = []
stellar_Ne_over_H_list_luminosity_weighted = []
stellar_Si_over_H_list_luminosity_weighted = []
stellar_S_over_H_list_luminosity_weighted = []
stellar_X_list_luminosity_weighted = []
stellar_Y_list_luminosity_weighted = []
stellar_Z_list_luminosity_weighted = []
stellar_Fe_over_H_list_luminosity_weighted = []
stellar_Mg_over_Fe_list_luminosity_weighted = []
stellar_C_over_Fe_list_luminosity_weighted = []
stellar_N_over_Fe_list_luminosity_weighted = []
stellar_Ca_over_Fe_list_luminosity_weighted = []
stellar_Ne_over_Fe_list_luminosity_weighted = []
stellar_Si_over_Fe_list_luminosity_weighted = []
stellar_S_over_Fe_list_luminosity_weighted = []
stellar_O_over_Fe_list_luminosity_weighted = []
stellar_Z_over_X_list_luminosity_weighted = []
stellar_Z_over_H_list_luminosity_weighted = []
remnant_mass_list = []
total_gas_mass_list = []
ejected_gas_mass_list = []
ejected_gas_Mg_over_Fe_list = []
instant_ejected_gas_Mg_over_Fe_list = []
ejected_metal_mass_list = []
expansion_factor_instantaneous_list = []
expansion_factor_adiabat_list = []
expansion_factor_list = []
stellar_mass_list = []
total_energy_release_list = []
SN_number_per_century = []
# binding_energy_list = []
total_gas_kinetic_energy_list = []
SNIa_energy_release_list = []
SNIa_number_list = []
SNIa_number_per_century = []
SNII_energy_release_list = []
SNII_number_list = []
SNII_number_per_century = []
Z_solar = element_abundances_solar.function_solar_element_abundances(solar_mass_component, 'Metal')
X_solar = element_abundances_solar.function_solar_element_abundances(solar_mass_component, 'H')
primary_H_mass_fraction = element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "H", Z_0, Z_solar)
primary_He_mass_fraction = element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "He", Z_0, Z_solar)
Z_over_X = math.log(Z_0 / primary_H_mass_fraction, 10) - math.log(Z_solar / X_solar, 10)
# do calculation for each time start from time 0
time_step = 0
gc_collect_check = 1
# do calculation for each time to the end time
while time_step < length_list_time_step:
# get time
this_time = time_axis[time_step]
# calculated the array index (line number in SFH.txt) this_time has reached
epoch_index_limit = (this_time + 1) / 10 ** 7
if epoch_index_limit > length_list_SFH_input:
epoch_index_limit = length_list_SFH_input
last_time_age = 0
age_of_this_epoch = 0
number_in_SNIa_boundary = 0
# get masses and metallicity at this time (values are calculated by the end of last time step)
# initialize values
total_energy_release = 0
SNIa_energy_release = 0
SNIa_number_from_all_epoch = 0
SNII_energy_release = 0
SNII_number = 0
if time_step == 0:
eject_H_mass = 0
eject_C_mass = 0
eject_N_mass = 0
eject_O_mass = 0
eject_Mg_mass = 0
eject_Ca_mass = 0
eject_Ne_mass = 0
eject_Si_mass = 0
eject_S_mass = 0
eject_Fe_mass = 0
eject_metal_mass = 0
total_gas_mass_at_this_time = original_gas_mass
ejected_gas_mass_at_this_time = 0
ejected_metal_mass_at_last_time = 0
M_tot_up_to_last_time = 0
M_tot_up_to_this_time = 0
stellar_mass_at_last_time = 0
stellar_mass_at_this_time = 0
stellar_luminosity_at_this_time = 0
ejected_gas_mass_till_last_time = 0
ejected_metal_mass_till_last_time = 0
ejected_H_mass_till_last_time = 0
ejected_He_mass_till_last_time = 0
ejected_C_mass_till_last_time = 0
ejected_N_mass_till_last_time = 0
ejected_O_mass_till_last_time = 0
ejected_Mg_mass_till_last_time = 0
ejected_Ca_mass_till_last_time = 0
ejected_Ne_mass_till_last_time = 0
ejected_Si_mass_till_last_time = 0
ejected_S_mass_till_last_time = 0
ejected_Fe_mass_till_last_time = 0
ejected_gas_mass_till_this_time = 0
ejected_metal_mass_till_this_time = 0
ejected_H_mass_till_this_time = 0
ejected_He_mass_till_this_time = 0
ejected_C_mass_till_this_time = 0
ejected_N_mass_till_this_time = 0
ejected_O_mass_till_this_time = 0
ejected_Mg_mass_till_this_time = 0
ejected_Ca_mass_till_this_time = 0
ejected_Ne_mass_till_this_time = 0
ejected_Si_mass_till_this_time = 0
ejected_S_mass_till_this_time = 0
ejected_Fe_mass_till_this_time = 0
BH_mass_till_this_time = 0
NS_mass_till_this_time = 0
WD_mass_till_this_time = 0
remnant_mass_at_this_time = 0
# Fe_H_mass_ratio_at_last_time = 0 #################################
Z_gas_this_time_step = Z_0
total_metal_mass_at_this_time = total_gas_mass_at_this_time * Z_gas_this_time_step
total_H_mass_at_this_time = 0
total_He_mass_at_this_time = 0
total_C_mass_at_this_time = 0
total_N_mass_at_this_time = 0
total_O_mass_at_this_time = 0
total_Mg_mass_at_this_time = 0
total_Ca_mass_at_this_time = 0
total_Ne_mass_at_this_time = 0
total_Si_mass_at_this_time = 0
total_S_mass_at_this_time = 0
total_Fe_mass_at_this_time = 0
total_H_mass_at_last_time = original_gas_mass * primary_H_mass_fraction
H_weight = element_weight_table.function_element_weight("H")
total_He_mass_at_last_time = original_gas_mass * primary_He_mass_fraction
total_C_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "C", Z_0, Z_solar)
total_N_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "N", Z_0, Z_solar)
total_O_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "O", Z_0, Z_solar)
total_Mg_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "Mg", Z_0, Z_solar)
total_Ca_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "Ca", Z_0, Z_solar)
total_Ne_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "Ne", Z_0, Z_solar)
total_Si_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "Si", Z_0, Z_solar)
total_S_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "S", Z_0, Z_solar)
total_Fe_mass_at_last_time = original_gas_mass * element_abundances_primordial.function_element_mass_primary_fraction(
solar_abu_table, "Fe", Z_0, Z_solar)
total_metal_mass_in_gas_at_last_time = original_gas_mass * Z_0
total_gas_mass_at_last_time = original_gas_mass
stellar_metal_mass_at_this_time = 0
stellar_H_mass_at_this_time = 0
stellar_He_mass_at_this_time = 0
stellar_C_mass_at_this_time = 0
stellar_N_mass_at_this_time = 0
stellar_O_mass_at_this_time = 0
stellar_Mg_mass_at_this_time = 0
stellar_Ca_mass_at_this_time = 0
stellar_Fe_mass_at_this_time = 0
stellar_Ne_mass_at_this_time = 0
stellar_Si_mass_at_this_time = 0
stellar_S_mass_at_this_time = 0
stellar_metal_luminosity_at_this_time = 0
stellar_H_luminosity_at_this_time = 0
stellar_He_luminosity_at_this_time = 0
stellar_C_luminosity_at_this_time = 0
stellar_N_luminosity_at_this_time = 0
stellar_O_luminosity_at_this_time = 0
stellar_Mg_luminosity_at_this_time = 0
stellar_Ca_luminosity_at_this_time = 0
stellar_Fe_luminosity_at_this_time = 0
stellar_Ne_luminosity_at_this_time = 0
stellar_Si_luminosity_at_this_time = 0
stellar_S_luminosity_at_this_time = 0
metal_mass_fraction_in_gas = [Z_gas_this_time_step, primary_H_mass_fraction, primary_He_mass_fraction,
total_C_mass_at_last_time / original_gas_mass,
total_N_mass_at_last_time / original_gas_mass,
total_O_mass_at_last_time / original_gas_mass,
total_Mg_mass_at_last_time / original_gas_mass,
total_Ca_mass_at_last_time / original_gas_mass,
total_Fe_mass_at_last_time / original_gas_mass,
total_Ne_mass_at_last_time / original_gas_mass,
total_Si_mass_at_last_time / original_gas_mass,
total_S_mass_at_last_time / original_gas_mass]
# H He C N O Mg Ca Fe Ne Si S
else:
total_gas_mass_at_last_time = total_gas_mass_at_this_time
# total_gas_mass_at_this_time is set in below
ejected_gas_mass_at_this_time = 0
total_metal_mass_in_gas_at_last_time = total_metal_mass_at_this_time
total_metal_mass_at_this_time = 0
total_H_mass_at_last_time = total_H_mass_at_this_time
total_H_mass_at_this_time = 0
total_He_mass_at_last_time = total_He_mass_at_this_time
total_He_mass_at_this_time = 0
total_C_mass_at_last_time = total_C_mass_at_this_time
total_C_mass_at_this_time = 0
total_N_mass_at_last_time = total_N_mass_at_this_time
total_N_mass_at_this_time = 0
total_O_mass_at_last_time = total_O_mass_at_this_time
total_O_mass_at_this_time = 0
total_Mg_mass_at_last_time = total_Mg_mass_at_this_time
total_Mg_mass_at_this_time = 0
total_Ca_mass_at_last_time = total_Ca_mass_at_this_time
total_Ca_mass_at_this_time = 0
total_Si_mass_at_last_time = total_Si_mass_at_this_time
total_Si_mass_at_this_time = 0
total_S_mass_at_last_time = total_S_mass_at_this_time
total_S_mass_at_this_time = 0
total_Ne_mass_at_last_time = total_Ne_mass_at_this_time
total_Ne_mass_at_this_time = 0
total_Fe_mass_at_last_time = total_Fe_mass_at_this_time
total_Fe_mass_at_this_time = 0
M_tot_up_to_last_time = M_tot_up_to_this_time
M_tot_up_to_this_time = 0
stellar_mass_at_last_time = stellar_mass_at_this_time
stellar_mass_at_this_time = 0
stellar_luminosity_at_this_time = 0
BH_mass_till_this_time = 0
NS_mass_till_this_time = 0
WD_mass_till_this_time = 0
remnant_mass_at_this_time = 0
ejected_gas_mass_till_last_time = ejected_gas_mass_till_this_time
ejected_metal_mass_till_last_time = ejected_metal_mass_till_this_time
ejected_H_mass_till_last_time = ejected_H_mass_till_this_time
ejected_He_mass_till_last_time = ejected_He_mass_till_this_time
ejected_C_mass_till_last_time = ejected_C_mass_till_this_time
ejected_N_mass_till_last_time = ejected_N_mass_till_this_time
ejected_O_mass_till_last_time = ejected_O_mass_till_this_time
ejected_Mg_mass_till_last_time = ejected_Mg_mass_till_this_time
ejected_Ca_mass_till_last_time = ejected_Ca_mass_till_this_time
ejected_Ne_mass_till_last_time = ejected_Ne_mass_till_this_time
ejected_Si_mass_till_last_time = ejected_Si_mass_till_this_time
ejected_S_mass_till_last_time = ejected_S_mass_till_this_time
ejected_Fe_mass_till_last_time = ejected_Fe_mass_till_this_time
ejected_gas_mass_till_this_time = 0
ejected_metal_mass_till_this_time = 0
ejected_H_mass_till_this_time = 0
ejected_He_mass_till_this_time = 0
ejected_C_mass_till_this_time = 0
ejected_N_mass_till_this_time = 0
ejected_O_mass_till_this_time = 0
ejected_Mg_mass_till_this_time = 0
ejected_Ca_mass_till_this_time = 0
ejected_Ne_mass_till_this_time = 0
ejected_Si_mass_till_this_time = 0
ejected_S_mass_till_this_time = 0
ejected_Fe_mass_till_this_time = 0
ejected_metal_mass_at_last_time = ejected_metal_mass_at_this_time
# Fe_H_mass_ratio_at_last_time = Fe_H_mass_ratio_at_this_time
Z_gas_this_time_step = total_metal_mass_in_gas_at_last_time / total_gas_mass_at_last_time
metal_mass_fraction_in_gas = [Z_gas_this_time_step,
total_H_mass_at_last_time / total_gas_mass_at_last_time,
total_He_mass_at_last_time / total_gas_mass_at_last_time,
total_C_mass_at_last_time / total_gas_mass_at_last_time,
total_N_mass_at_last_time / total_gas_mass_at_last_time,
total_O_mass_at_last_time / total_gas_mass_at_last_time,
total_Mg_mass_at_last_time / total_gas_mass_at_last_time,
total_Ca_mass_at_last_time / total_gas_mass_at_last_time,
total_Fe_mass_at_last_time / total_gas_mass_at_last_time,
total_Ne_mass_at_last_time / total_gas_mass_at_last_time,
total_Si_mass_at_last_time / total_gas_mass_at_last_time,
total_S_mass_at_last_time / total_gas_mass_at_last_time]
stellar_metal_mass_at_this_time = 0
stellar_H_mass_at_this_time = 0
stellar_He_mass_at_this_time = 0
stellar_C_mass_at_this_time = 0
stellar_N_mass_at_this_time = 0
stellar_O_mass_at_this_time = 0
stellar_Mg_mass_at_this_time = 0
stellar_Ca_mass_at_this_time = 0
stellar_Ne_mass_at_this_time = 0
stellar_Si_mass_at_this_time = 0
stellar_S_mass_at_this_time = 0
stellar_Fe_mass_at_this_time = 0
stellar_metal_luminosity_at_this_time = 0
stellar_H_luminosity_at_this_time = 0
stellar_He_luminosity_at_this_time = 0
stellar_C_luminosity_at_this_time = 0
stellar_N_luminosity_at_this_time = 0
stellar_O_luminosity_at_this_time = 0
stellar_Mg_luminosity_at_this_time = 0
stellar_Ca_luminosity_at_this_time = 0
stellar_Fe_luminosity_at_this_time = 0
stellar_Ne_luminosity_at_this_time = 0
stellar_Si_luminosity_at_this_time = 0
stellar_S_luminosity_at_this_time = 0
# add up metals contributed by SSP from each SF epoch
# consider only the SF event (epoch) that had happend
Fe_production_SNII = 0
Mg_production_SNII = 0
Ca_production_SNII = 0
Ne_production_SNII = 0
Si_production_SNII = 0
S_production_SNII = 0
O_production_SNII = 0
epoch_index = 0
while epoch_index < epoch_index_limit:
# get age
age_of_this_epoch = this_time - epoch_index * 10 ** 7
# get SFR, M_tot, igimf, integrated igimf, stellar lifetime and stellar remnant mass for this metallicity
# check if the info of this epoch has been recorded in previous time steps...
if epoch_index == len(epoch_info): # if not:
# SFR
if SFH_model == 'provided':
# This model apply the SFH specified by the SFH.txt
S_F_R_of_this_epoch = SFH_input[epoch_index]
elif SFH_model == 'gas_mass_dependent':
# In this model, the SFR is determined by the current gas mass
# if the current time is shorter than SFEN * 10^7 yr.
S_F_R_of_this_epoch = total_gas_mass_at_this_time * SFE / 10 ** 7
if SFH_input[epoch_index] == 0:
S_F_R_of_this_epoch = 0
else:
print("Wrong input parameter for 'SFH_model'.")
# M_tot
# if total_gas_mass_at_last_time > 10**12:
# M_tot_of_this_epoch = max((min(((total_gas_mass_at_last_time - 10 * stellar_mass_at_last_time) / 5), 10**12)), 0)
# else:
# M_tot_of_this_epoch = 0
M_tot_of_this_epoch = S_F_R_of_this_epoch * 10 ** 7
# if S_F_F == 1:
# S_F_R_of_this_epoch = total_gas_mass_at_last_time**(0.99) * 3.97 * 10**(-10) # Pflamm-Altenburg & Kroupa 2009
# S_F_R_of_this_epoch_list += [S_F_R_of_this_epoch]
# if S_F_R_of_this_epoch < S_F_R_of_this_epoch_list[0] * 0.8:
# S_F_F = 0
# else:
# S_F_R_of_this_epoch = 0
#
#
# print(S_F_R_of_this_epoch)
# M_tot_of_this_epoch = S_F_R_of_this_epoch * 10 ** 7
# if S_F_R_of_this_epoch > 0:
# if high_time_resolution == True:
# time_axis_for_SFH_input_D += [epoch_index * 10 ** 7]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 5 * 10 ** 5]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 1 * 10 ** 6]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 2 * 10 ** 6]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 4 * 10 ** 6]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 6 * 10 ** 6]
# # time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 8 * 10 ** 6]
# time_axis_for_SFH_input_D += [epoch_index * 10 ** 7 + 10 * 10 ** 6]
# else:
# time_axis_for_SFH_input_D += [epoch_index * 10 ** 7]
# time_axis = sorted(list(set(time_axis + time_axis_for_SFH_input_D)))
# length_list_time_step = len(time_axis)
if S_F_R_of_this_epoch > 0:
# Total mass normalized IGIMF and unnormalized other IMFs
if imf == 'igimf':
igimf_of_this_epoch = function_get_igimf_for_this_epoch(S_F_R_of_this_epoch, Z_over_X,
this_time, epoch_index,
check_igimf) # Fe_over_H_number_ratio)
elif imf == 'Kroupa':
igimf_of_this_epoch = Kroupa_IMF
elif imf == 'Salpeter':
from IMFs import Salpeter_IMF
igimf_of_this_epoch = Salpeter_IMF
elif imf == 'diet_Salpeter':
igimf_of_this_epoch = diet_Salpeter_IMF
elif imf == 'given':
from IMFs import given_IMF
igimf_of_this_epoch = given_IMF
igimf = igimf_of_this_epoch
#
def igimf_xi_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time)
def igimf_mass_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time) * mass
def igimf_luminous_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time) * \
stellar_luminosity.stellar_luminosity_function(mass)
# integrated igimf_mass_function from 0.08 to steller_mass_upper_bound
integrate_igimf_mass = quad(igimf_mass_function, 0.08, steller_mass_upper_bound, limit=50)[0]
# as the integration of the IGIMF always has a small (at least for low SFRs) computational error,
# it need to be fixed by mutiplying a calibration factor which is close to 1:
mass_calibration_factor = M_tot_of_this_epoch / integrate_igimf_mass
# print("mass_calibration_factor:", mass_calibration_factor) # the calibration factor is about 1%
# integrate_igimf_mass_l = quad(igimf_mass_function, 0.08, 3, limit=40)[0]
# integrate_igimf_mass_h = quad(igimf_mass_function, 8, steller_mass_upper_bound, limit=50)[0]
# integrate_igimf_mass_m = quad(igimf_mass_function, 1.5, 8, limit=40)[0]
# print("high mass star mass ratio:", integrate_igimf_mass_h/integrate_igimf_mass)
# print("middle mass star mass ratio:", integrate_igimf_mass_m/integrate_igimf_mass)
# print("Low mass star mass ratio:", integrate_igimf_mass_l/integrate_igimf_mass)
# integrate_igimf_number = quad(igimf_xi_function, 0.08, steller_mass_upper_bound, limit=50)[0]
# integrate_igimf_number_l = quad(igimf_xi_function, 0.08, 3, limit=40)[0]
# integrate_igimf_number_h = quad(igimf_xi_function, 8, steller_mass_upper_bound, limit=50)[0]
# integrate_igimf_number_m = quad(igimf_xi_function, 1.5, 8, limit=40)[0]
# print("high mass star number ratio:", integrate_igimf_number_h/integrate_igimf_number)
# print("middle mass star number ratio:", integrate_igimf_number_m/integrate_igimf_number)
# print("Low mass star number ratio:", integrate_igimf_number_l/integrate_igimf_number)
# Choose the closest metallicity
Z_select_in_table = function_select_metal(Z_gas_this_time_step, Z_table_list)
Z_select_in_table_2 = function_select_metal(Z_gas_this_time_step, Z_table_list_2)
if str_yield_table != "portinari98":
Z_select_in_table_3 = function_select_metal(Z_gas_this_time_step, Z_table_list_3)
else:
Z_select_in_table_3 = None
# read in interpolated stellar lifetime table
(mass_1, mass, lifetime_table) = function_read_lifetime(str_yield_table, Z_select_in_table)
# read in interpolated stellar final mass
(mass_12, Mfinal_table) = function_read_Mfinal(str_yield_table, Z_select_in_table)
# read in interpolated stellar ejected metal mass
(mass_2, mass2, Mmetal_table) = function_read_Mmetal(str_yield_table, Z_select_in_table_2,
Z_select_in_table_3)
# read in interpolated stellar ejected elements mass
MH_table = function_read_M_element("H", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MHe_table = function_read_M_element("He", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MC_table = function_read_M_element("C", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MN_table = function_read_M_element("N", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MO_table = function_read_M_element("O", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MMg_table = function_read_M_element("Mg", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MNe_table = function_read_M_element("Ne", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MSi_table = function_read_M_element("Si", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MS_table = function_read_M_element("S", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MCa_table = function_read_M_element("Ca", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
MFe_table = function_read_M_element("Fe", str_yield_table, Z_select_in_table_2, Z_select_in_table_3)
M_element_table = [MH_table, MHe_table, MC_table, MN_table, MO_table, MMg_table, MNe_table,
MSi_table, MS_table, MCa_table, MFe_table]
# check if the in put lifetime and final mass table used the same mass grid
# if mass_1 != mass_12:
# print('Error! Stellar lifetime and final mass input data do not match.\n'
# 'Check the table file: yield_tables/rearranged/setllar_final_mass_from_portinari98/portinari98_Z={}.txt\n'
# 'and table file: yield_tables/rearranged/setllar_lifetime_from_portinari98/portinari98_Z={}.txt'.format(
# Z_select_in_table,
# Z_select_in_table))
# else:
# mass_grid_table = mass
# mass_grid_table2 = mass2
mass_grid_table = mass
mass_grid_table2 = mass2
last_time_age = age_of_this_epoch
number_in_SNIa_boundary = mass_calibration_factor * quad(igimf_xi_function, 1.5, 8, limit=40)[
0] # see function_number_SNIa below
number_all = quad(igimf_xi_function, 0.08, steller_mass_upper_bound, limit=50)[
0] # see function_number_SNIa below
# number_low = quad(igimf_xi_function, 0.08, 2, limit=40)[0] # see function_number_SNIa below
# number_up = quad(igimf_xi_function, 8, steller_mass_upper_bound, limit=50)[0] # see function_number_SNIa below
# print("up", number_up/number_all)
# SNIa_number_prob = number_in_SNIa_boundary**2 / number_all * 10**2 * 0.61
# number_in_SNIa_boundary = SNIa_number_prob
# SNIa_number_prob = number_in_SNIa_boundary / integrate_igimf_mass
# print("SNIa SNIa_number_prob:", SNIa_number_prob)
# print("total star number", number_all)
# print("low", number_low/number_all)
age_of_this_epoch_at_end = (length_list_SFH_input - epoch_index - 1) * 10 ** 7
mass_boundary_at_end = fucntion_mass_boundary(age_of_this_epoch_at_end, mass_grid_table,
lifetime_table)
all_sf_imf.append([igimf, mass_boundary_at_end, this_time])
time_of_the_epoch_in_Gyr = epoch_index / 100
all_sfr.append([S_F_R_of_this_epoch, time_of_the_epoch_in_Gyr])
epoch_info.append(
[S_F_R_of_this_epoch, M_tot_of_this_epoch, igimf_of_this_epoch, integrate_igimf_mass,
mass_grid_table, lifetime_table, Mfinal_table, mass_grid_table2, Mmetal_table, M_element_table,
last_time_age, number_in_SNIa_boundary, metal_mass_fraction_in_gas, mass_calibration_factor])
metal_in_gas = metal_mass_fraction_in_gas
else: # if SFR == 0
time_of_the_epoch_in_Gyr = epoch_index / 100
all_sfr.append([10 ** -10, time_of_the_epoch_in_Gyr])
epoch_info.append(
[0, 0, 0, 0, 0, 0, 0, 0, 0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0, 0, [0, 0, 0, 0, 0], 0])
else: # if epoch_index =! len(epoch_info)
S_F_R_of_this_epoch = epoch_info[epoch_index][0]
M_tot_of_this_epoch = epoch_info[epoch_index][1]
igimf_of_this_epoch = epoch_info[epoch_index][2]
integrate_igimf_mass = epoch_info[epoch_index][3]
mass_grid_table = epoch_info[epoch_index][4]
lifetime_table = epoch_info[epoch_index][5]
Mfinal_table = epoch_info[epoch_index][6]
mass_grid_table2 = epoch_info[epoch_index][7]
Mmetal_table = epoch_info[epoch_index][8]
M_element_table = epoch_info[epoch_index][9]
last_time_age = epoch_info[epoch_index][10]
epoch_info[epoch_index][10] = age_of_this_epoch
number_in_SNIa_boundary = epoch_info[epoch_index][11]
metal_in_gas = epoch_info[epoch_index][12]
mass_calibration_factor = epoch_info[epoch_index][13]
def igimf_xi_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time)
def igimf_mass_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time) * mass
def igimf_luminous_function(mass):
return igimf_of_this_epoch.custom_imf(mass, this_time) * \
stellar_luminosity.stellar_luminosity_function(mass)
if S_F_R_of_this_epoch > 0:
# get M_tot (total initial mass of all star ever formed)
M_tot_up_to_this_time += M_tot_of_this_epoch
# calculate stellar initial mass that is still alive (dead star mass boundary)
mass_boundary = fucntion_mass_boundary(age_of_this_epoch, mass_grid_table, lifetime_table)
# output of this epoch
# Mtarget_table_number:
# 1: Mfinal_table
# 2: Mmetal_table
# 3: MH_table
# 4: M_element_table
# ...
if integrate_igimf_mass != 0:
# m1 = quad(igimf_mass_function, 0.08, 10, limit=40)[0]
# m2 = quad(igimf_mass_function, 10, 150, limit=40)[0]
# print(m1)
# print(m2)
# print(m1 / m2)
inte_limit = max(round((math.log(mass_boundary, 10)+1) / (math.log(steller_mass_upper_bound, 10)+1) * 50), 20)
integrate_star_mass = quad(igimf_mass_function, 0.08, mass_boundary, limit=inte_limit)[0] # normalized mass
stellar_luminosity_of_a_epoch_at_a_time_step = quad(igimf_luminous_function, 0.08, mass_boundary, limit=inte_limit)[0]
stellar_mass_of_a_epoch_at_a_time_step = mass_calibration_factor * integrate_star_mass # real mass
# apprent metal mass (neglect stellar evolution, only account for the initial metal mass when SF):
# the stellar metal abandance is the gas abdandance at the time of star foramtion (metal_in_gas).
stellar_metal_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[0]
stellar_H_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[1]
stellar_He_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[2]
stellar_C_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[3]
stellar_N_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[4]
stellar_O_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[5]
stellar_Mg_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[6]
stellar_Ca_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[7]
stellar_Fe_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[8]
stellar_Ne_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[9]
stellar_Si_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[10]
stellar_S_mass_of_this_epoch = stellar_mass_of_a_epoch_at_a_time_step * metal_in_gas[11]
# The luminosity-weighted metallicity is in its exact form. However,
# the luminosity-weighted element abundance, e.g., weighted-with-luminosity([Fe/H]) is approximated
# by [the-number-of(weighted-with-luminosity(mass-fraction-of(Fe)))/the-number-of(weighted-with-luminosity(mass-fraction-of(H)))]
# below is the first step to calculate the weighted-with-luminosity(mass-fraction-of(An-element))
stellar_metal_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[0]
stellar_H_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[1]
stellar_He_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[2]
stellar_C_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[3]
stellar_N_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[4]
stellar_O_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[5]
stellar_Mg_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[6]
stellar_Ca_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[7]
stellar_Fe_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[8]
stellar_Ne_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[9]
stellar_Si_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[10]
stellar_S_luminosity_of_this_epoch = stellar_luminosity_of_a_epoch_at_a_time_step * metal_in_gas[11]
#
BH_mass_of_this_epoch = get_BH_mass(mass_boundary, 1, 1, mass_calibration_factor,
steller_mass_upper_bound)
NS_mass_of_this_epoch = get_NS_mass(mass_boundary, 1, 1, mass_calibration_factor)
WD_mass_of_this_epoch = get_WD_mass(mass_boundary, 1, 1, mass_calibration_factor)
remnant_mass_of_this_epoch = WD_mass_of_this_epoch + NS_mass_of_this_epoch + BH_mass_of_this_epoch
# Note: M_tot_of_this_epoch =! ejected_gas_mass_of_this_epoch +
# stellar_mass_of_a_epoch_at_a_time_step + remnant_mass_of_this_epoch
# because the remnant_mass is a spline fitted value
# while metall mass ejection is calculated with M_metal = M_ini - M_final - M_H - M_He,
# where M_final is the remnant mass given by the stellar yield table.
#
# # consider direct black hole as in Heger et al. (2003) (maybe not self-consistant with the stellar evolution table)
# if mass_boundary > 100:
# SNII_number_of_this_epoch_1 = quad(igimf_mass_function, mass_boundary, steller_mass_upper_bound, limit=50)[0]
# SNII_number_of_this_epoch_2 = 0
# elif mass_boundary > 40:
# SNII_number_of_this_epoch_1 = quad(igimf_mass_function, 100, steller_mass_upper_bound, limit=50)[0]
# SNII_number_of_this_epoch_2 = 0
# elif mass_boundary > 8:
# SNII_number_of_this_epoch_1 = quad(igimf_mass_function, 100, steller_mass_upper_bound, limit=50)[0]
# SNII_number_of_this_epoch_2 = quad(igimf_mass_function, mass_boundary, 40, limit=40)[0]
# else:
# SNII_number_of_this_epoch_1 = quad(igimf_mass_function, 100, steller_mass_upper_bound, limit=50)[0]
# SNII_number_of_this_epoch_2 = quad(igimf_mass_function, 8, 40, limit=40)[0]
# SNII_number_of_this_epoch = (SNII_number_of_this_epoch_1 + SNII_number_of_this_epoch_2) * mass_calibration_factor
if mass_boundary > 8:
SNII_number_of_this_epoch = \
quad(igimf_mass_function, mass_boundary, steller_mass_upper_bound, limit=50)[0]
SNII_ejected_mass_of_this_epoch = \
quad(igimf_mass_function, mass_boundary, steller_mass_upper_bound, limit=50)[0]
else:
SNII_number_of_this_epoch = quad(igimf_mass_function, 8, steller_mass_upper_bound, limit=50)[0]
SNII_number_of_this_epoch = SNII_number_of_this_epoch * mass_calibration_factor
SNII_energy_release_per_event = 10 ** 51
SNII_number += SNII_number_of_this_epoch
SNII_energy_release += SNII_energy_release_per_event * SNII_number_of_this_epoch
# ejected_ :
metal_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary,
steller_mass_upper_bound, 2, 2,
mass_calibration_factor)
H_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound, 2,
"H", mass_calibration_factor)
He_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "He", mass_calibration_factor)
ejected_gas_mass_of_this_epoch = H_mass_of_this_epoch + He_mass_of_this_epoch + \
metal_mass_of_this_epoch
C_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "C", mass_calibration_factor)
N_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "N", mass_calibration_factor)
O_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "O", mass_calibration_factor)
Mg_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "Mg", mass_calibration_factor)
Ca_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "Ca", mass_calibration_factor)
S_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "S", mass_calibration_factor)
Si_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "Si", mass_calibration_factor)
Ne_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "Ne", mass_calibration_factor)
Fe_mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound,
2, "Fe", mass_calibration_factor)
Fe_production_SNII += Fe_mass_of_this_epoch
Ca_production_SNII += Ca_mass_of_this_epoch
Ne_production_SNII += Ne_mass_of_this_epoch
Si_production_SNII += Si_mass_of_this_epoch
S_production_SNII += S_mass_of_this_epoch
Mg_production_SNII += Mg_mass_of_this_epoch
O_production_SNII += O_mass_of_this_epoch
# if age_of_this_epoch == 1 * 10 ** 9:
# print("Fe_production_SNII", Fe_production_SNII)
# print("O_production_SNII", O_production_SNII)
# print("Mg_production_SNII", Mg_production_SNII)
# _mass_of_this_epoch = function_get_target_mass_in_range(mass_boundary, steller_mass_upper_bound, 2, "",
# mass_calibration_factor)
else:
print("Error: integrate_igimf_mass == 0 while S_F_R_of_this_epoch != 0.")
stellar_mass_of_a_epoch_at_a_time_step = 0
BH_mass_of_this_epoch = 0
NS_mass_of_this_epoch = 0
WD_mass_of_this_epoch = 0
remnant_mass_of_this_epoch = 0
ejected_gas_mass_of_this_epoch = 0
metal_mass_of_this_epoch = 0
H_mass_of_this_epoch = 0
He_mass_of_this_epoch = 0
C_mass_of_this_epoch = 0
N_mass_of_this_epoch = 0
O_mass_of_this_epoch = 0
Mg_mass_of_this_epoch = 0
Ca_mass_of_this_epoch = 0
Si_mass_of_this_epoch = 0
S_mass_of_this_epoch = 0
Ne_mass_of_this_epoch = 0
Fe_mass_of_this_epoch = 0
# if consider SNIa
if SNIa_ON == True:
# read in SNIa yield table
# (here only account for the most abandant element yields)
# (but should account as long as the SNIa yield is comparable with SNII yield)
Fe_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Fe')
Si_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Si')
O_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'O')
S_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'S')
Mg_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Mg')
Ne_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Ne')
if SNIa_yield_table=='Seitenzahl2013':
Ca_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Ca')
Ne_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Ne')
S_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'S')
Si_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'Si')
C_mass_eject = SNIa_yield.function_mass_ejected(SNIa_yield_table, 'C')
total_mass_eject_per_SNIa = Fe_mass_eject + Si_mass_eject + O_mass_eject + S_mass_eject + Mg_mass_eject + Ne_mass_eject
Chandrasekhar_mass = 1.44
pre_SNIa_NS_mass = 1
SNIa_energy_release_per_event = 10 ** 51 # in the unit of 10^51 erg
# integrate SNIa number from last_delay_time to this_delay_time contributed by this SF epoch
SNIa_number_from_this_epoch_till_this_time = function_number_SNIa(0, age_of_this_epoch,
number_in_SNIa_boundary,
S_F_R_of_this_epoch)
# the following should result in 0.0022+-50% for a SSP,
# but now calibrate to a different value to fit with galaxy [Fe/H] observation
if age_of_this_epoch == 10 * 10 ** 9 - 1 * 10 ** 7:
# print(function_number_SNIa(0, 10 * 10 ** 9, 1, 0))
# print("SN number per star in range:", SNIa_number_from_this_epoch_till_this_time/number_in_SNIa_boundary)
print("\nType Ia supernova activated. "
"Total SNIa number per solar mass of star formed at t = 10Gyr:",
SNIa_number_from_this_epoch_till_this_time / M_tot_of_this_epoch)
# update the element masses
ejected_gas_mass_of_this_epoch += total_mass_eject_per_SNIa * SNIa_number_from_this_epoch_till_this_time
metal_mass_of_this_epoch += (Chandrasekhar_mass - (Chandrasekhar_mass - pre_SNIa_NS_mass) *
Z_gas_this_time_step) * SNIa_number_from_this_epoch_till_this_time
O_mass_of_SNIa = O_mass_eject * SNIa_number_from_this_epoch_till_this_time
Mg_mass_of_SNIa = Mg_mass_eject * SNIa_number_from_this_epoch_till_this_time
Fe_mass_of_SNIa = (Fe_mass_eject
# - (Chandrasekhar_mass - pre_SNIa_NS_mass) * Fe_H_mass_ratio_at_last_time * 0.7057 # this term is small and can be neglected
) * SNIa_number_from_this_epoch_till_this_time
# Si_mass_of_SNIa = Si_mass_eject * SNIa_number_from_this_epoch_till_this_time
# S_mass_of_SNIa = S_mass_eject * SNIa_number_from_this_epoch_till_this_time
# Ne_mass_of_SNIa = Ne_mass_eject * SNIa_number_from_this_epoch_till_this_time
if SNIa_yield_table == 'Seitenzahl2013':
Ca_mass_of_SNIa = Ca_mass_eject * SNIa_number_from_this_epoch_till_this_time
Si_mass_of_SNIa = Si_mass_eject * SNIa_number_from_this_epoch_till_this_time
S_mass_of_SNIa = S_mass_eject * SNIa_number_from_this_epoch_till_this_time
Ne_mass_of_SNIa = Ne_mass_eject * SNIa_number_from_this_epoch_till_this_time
C_mass_of_SNIa = C_mass_eject * SNIa_number_from_this_epoch_till_this_time
O_mass_of_this_epoch += O_mass_of_SNIa
Mg_mass_of_this_epoch += Mg_mass_of_SNIa
Fe_mass_of_this_epoch += Fe_mass_of_SNIa
# Si_mass_of_this_epoch += Si_mass_of_SNIa
# S_mass_of_this_epoch += S_mass_of_SNIa
# Ne_mass_of_this_epoch += Ne_mass_of_SNIa
if SNIa_yield_table == 'Seitenzahl2013':
Ca_mass_of_this_epoch += Ca_mass_of_SNIa
Ne_mass_of_this_epoch += Ne_mass_of_SNIa
S_mass_of_this_epoch += S_mass_of_SNIa
Si_mass_of_this_epoch += Si_mass_of_SNIa
C_mass_of_this_epoch += C_mass_of_SNIa
remnant_mass_of_this_epoch -= pre_SNIa_NS_mass * SNIa_number_from_this_epoch_till_this_time
WD_mass_of_this_epoch -= pre_SNIa_NS_mass * SNIa_number_from_this_epoch_till_this_time
SNIa_number_from_all_epoch += SNIa_number_from_this_epoch_till_this_time
SNIa_energy_release += SNIa_energy_release_per_event * SNIa_number_from_this_epoch_till_this_time
#
stellar_mass_at_this_time += stellar_mass_of_a_epoch_at_a_time_step
stellar_metal_mass_at_this_time += stellar_metal_mass_of_this_epoch
stellar_H_mass_at_this_time += stellar_H_mass_of_this_epoch
stellar_He_mass_at_this_time += stellar_He_mass_of_this_epoch
stellar_O_mass_at_this_time += stellar_O_mass_of_this_epoch
stellar_C_mass_at_this_time += stellar_C_mass_of_this_epoch
stellar_N_mass_at_this_time += stellar_N_mass_of_this_epoch
stellar_Ca_mass_at_this_time += stellar_Ca_mass_of_this_epoch
stellar_Si_mass_at_this_time += stellar_Si_mass_of_this_epoch
stellar_S_mass_at_this_time += stellar_S_mass_of_this_epoch
stellar_Ne_mass_at_this_time += stellar_Ne_mass_of_this_epoch
stellar_Mg_mass_at_this_time += stellar_Mg_mass_of_this_epoch
stellar_Fe_mass_at_this_time += stellar_Fe_mass_of_this_epoch
#
# The luminosity-weighted element mass fraction is,
# e.g., stellar_Fe_luminosity_at_this_time / stellar_luminosity_at_this_time
stellar_luminosity_at_this_time += stellar_luminosity_of_a_epoch_at_a_time_step
stellar_metal_luminosity_at_this_time += stellar_metal_luminosity_of_this_epoch
stellar_H_luminosity_at_this_time += stellar_H_luminosity_of_this_epoch
stellar_He_luminosity_at_this_time += stellar_He_luminosity_of_this_epoch
stellar_O_luminosity_at_this_time += stellar_O_luminosity_of_this_epoch
stellar_C_luminosity_at_this_time += stellar_C_luminosity_of_this_epoch
stellar_N_luminosity_at_this_time += stellar_N_luminosity_of_this_epoch
stellar_Ca_luminosity_at_this_time += stellar_Ca_luminosity_of_this_epoch
stellar_Ne_luminosity_at_this_time += stellar_Ne_luminosity_of_this_epoch
stellar_S_luminosity_at_this_time += stellar_S_luminosity_of_this_epoch
stellar_Si_luminosity_at_this_time += stellar_Si_luminosity_of_this_epoch
stellar_Mg_luminosity_at_this_time += stellar_Mg_luminosity_of_this_epoch
stellar_Fe_luminosity_at_this_time += stellar_Fe_luminosity_of_this_epoch
BH_mass_till_this_time += BH_mass_of_this_epoch
NS_mass_till_this_time += NS_mass_of_this_epoch
WD_mass_till_this_time += WD_mass_of_this_epoch
remnant_mass_at_this_time += remnant_mass_of_this_epoch
ejected_gas_mass_till_this_time += ejected_gas_mass_of_this_epoch
ejected_metal_mass_till_this_time += metal_mass_of_this_epoch
ejected_H_mass_till_this_time += H_mass_of_this_epoch
ejected_He_mass_till_this_time += He_mass_of_this_epoch
ejected_O_mass_till_this_time += O_mass_of_this_epoch
ejected_C_mass_till_this_time += C_mass_of_this_epoch
ejected_N_mass_till_this_time += N_mass_of_this_epoch
ejected_Ca_mass_till_this_time += Ca_mass_of_this_epoch
ejected_Si_mass_till_this_time += Si_mass_of_this_epoch
ejected_S_mass_till_this_time += S_mass_of_this_epoch
ejected_Ne_mass_till_this_time += Ne_mass_of_this_epoch
ejected_Mg_mass_till_this_time += Mg_mass_of_this_epoch
ejected_Fe_mass_till_this_time += Fe_mass_of_this_epoch
# Goes to the next SF epoch until all SF event before this time step is accounted:
(epoch_index) = (epoch_index + 1)
# output of this time step
total_energy_release = SNIa_energy_release + SNII_energy_release
### yeilds at this time step from all SF epoch:
ejected_gas_mass_at_this_time = ejected_gas_mass_till_this_time - ejected_gas_mass_till_last_time
ejected_metal_mass_at_this_time = ejected_metal_mass_till_this_time - ejected_metal_mass_till_last_time
ejected_H_mass_at_this_time = ejected_H_mass_till_this_time - ejected_H_mass_till_last_time
ejected_He_mass_at_this_time = ejected_He_mass_till_this_time - ejected_He_mass_till_last_time
ejected_C_mass_at_this_time = ejected_C_mass_till_this_time - ejected_C_mass_till_last_time
ejected_N_mass_at_this_time = ejected_N_mass_till_this_time - ejected_N_mass_till_last_time
ejected_O_mass_at_this_time = ejected_O_mass_till_this_time - ejected_O_mass_till_last_time
ejected_Mg_mass_at_this_time = ejected_Mg_mass_till_this_time - ejected_Mg_mass_till_last_time
ejected_Ca_mass_at_this_time = ejected_Ca_mass_till_this_time - ejected_Ca_mass_till_last_time
ejected_Ne_mass_at_this_time = ejected_Ne_mass_till_this_time - ejected_Ne_mass_till_last_time
ejected_S_mass_at_this_time = ejected_S_mass_till_this_time - ejected_S_mass_till_last_time
ejected_Si_mass_at_this_time = ejected_Si_mass_till_this_time - ejected_Si_mass_till_last_time
ejected_Fe_mass_at_this_time = ejected_Fe_mass_till_this_time - ejected_Fe_mass_till_last_time
ejected_gas_Mg_over_Fe_till_this_time = function_element_abundunce(solar_abu_table, "Mg", "Fe",
ejected_Mg_mass_till_this_time,
ejected_Fe_mass_till_this_time, False)
ejected_gas_Mg_over_Fe_at_this_time = function_element_abundunce(solar_abu_table, "Mg", "Fe",
ejected_Mg_mass_at_this_time,
ejected_Fe_mass_at_this_time, True)
M_tot_of_this_time = M_tot_up_to_this_time - M_tot_up_to_last_time # new SF mass added at this time step
#
galaxy_mass_without_gas_at_this_time = stellar_mass_at_this_time + remnant_mass_at_this_time
if galaxy_mass_without_gas_at_this_time == 0 or ejected_gas_mass_at_this_time == 0:
expansion_factor_instantaneous = 1
expansion_factor_adiabat = 1
elif galaxy_mass_without_gas_at_this_time < ejected_gas_mass_at_this_time:
Warning_galaxy_mass_ejected_gas_mass = True
# Warning: galaxy_mass < ejected_gas_mass.
# This is due to too large a timestep.
# It is easy to aviod this issue by applying the "high_time_resolution=True"
# but the simulation will take much longer time.
expansion_factor_instantaneous = 10
expansion_factor_adiabat = (
galaxy_mass_without_gas_at_this_time + ejected_gas_mass_at_this_time) / galaxy_mass_without_gas_at_this_time
else:
expansion_factor_instantaneous = galaxy_mass_without_gas_at_this_time / (
galaxy_mass_without_gas_at_this_time - ejected_gas_mass_at_this_time)
expansion_factor_adiabat = (
galaxy_mass_without_gas_at_this_time + ejected_gas_mass_at_this_time) / galaxy_mass_without_gas_at_this_time
expansion_factor = 10 ** (
(math.log(expansion_factor_instantaneous, 10) + math.log(expansion_factor_adiabat, 10)) / 2)
### Element abundances in the gas phase (in solar unit):
if outflow is True:
lockup_and_outflow_mass = M_tot_of_this_time * 2 # lockup gas mass in BDs is about 4% thus neglected while the uniform outflow is often assumed to be the same value as the formed stellar mass.
else:
lockup_and_outflow_mass = M_tot_of_this_time
total_gas_mass_at_this_time = total_gas_mass_at_last_time - lockup_and_outflow_mass + ejected_gas_mass_at_this_time
if total_gas_mass_at_this_time < 0.0001:
total_gas_mass_at_this_time = 0.0001
total_metal_mass_at_this_time = total_metal_mass_in_gas_at_last_time - lockup_and_outflow_mass * \
Z_gas_this_time_step + ejected_metal_mass_at_this_time
if total_metal_mass_at_this_time < 0.0001:
total_metal_mass_at_this_time = 0.0001
total_H_mass_at_this_time = total_H_mass_at_last_time - lockup_and_outflow_mass * (
total_H_mass_at_last_time / total_gas_mass_at_last_time) + ejected_H_mass_at_this_time
if total_H_mass_at_this_time < 0.0001:
total_H_mass_at_this_time = 0.0001
total_He_mass_at_this_time = total_He_mass_at_last_time - lockup_and_outflow_mass * (
total_He_mass_at_last_time / total_gas_mass_at_last_time) + ejected_He_mass_at_this_time
if total_He_mass_at_this_time < 0.0001:
total_He_mass_at_this_time = 0.0001
total_C_mass_at_this_time = total_C_mass_at_last_time - lockup_and_outflow_mass * (
total_C_mass_at_last_time / total_gas_mass_at_last_time) + ejected_C_mass_at_this_time
if total_C_mass_at_this_time < 0.0001:
total_C_mass_at_this_time = 0.0001
total_N_mass_at_this_time = total_N_mass_at_last_time - lockup_and_outflow_mass * (
total_N_mass_at_last_time / total_gas_mass_at_last_time) + ejected_N_mass_at_this_time
if total_N_mass_at_this_time < 0.0001:
total_N_mass_at_this_time = 0.0001
total_O_mass_at_this_time = total_O_mass_at_last_time - lockup_and_outflow_mass * (
total_O_mass_at_last_time / total_gas_mass_at_last_time) + ejected_O_mass_at_this_time
if total_O_mass_at_this_time < 0.0001:
total_O_mass_at_this_time = 0.0001
total_Mg_mass_at_this_time = total_Mg_mass_at_last_time - lockup_and_outflow_mass * (
total_Mg_mass_at_last_time / total_gas_mass_at_last_time) + ejected_Mg_mass_at_this_time
if total_Mg_mass_at_this_time < 0.0001:
total_Mg_mass_at_this_time = 0.0001
total_Ca_mass_at_this_time = total_Ca_mass_at_last_time - lockup_and_outflow_mass * (
total_Ca_mass_at_last_time / total_gas_mass_at_last_time) + ejected_Ca_mass_at_this_time
if total_Ca_mass_at_this_time < 0.0001:
total_Ca_mass_at_this_time = 0.0001
total_Ne_mass_at_this_time = total_Ne_mass_at_last_time - lockup_and_outflow_mass * (
total_Ne_mass_at_last_time / total_gas_mass_at_last_time) + ejected_Ne_mass_at_this_time
if total_Ne_mass_at_this_time < 0.0001:
total_Ne_mass_at_this_time = 0.0001
total_Si_mass_at_this_time = total_Si_mass_at_last_time - lockup_and_outflow_mass * (
total_Si_mass_at_last_time / total_gas_mass_at_last_time) + ejected_Si_mass_at_this_time
if total_Si_mass_at_this_time < 0.0001:
total_Si_mass_at_this_time = 0.0001
total_S_mass_at_this_time = total_S_mass_at_last_time - lockup_and_outflow_mass * (
total_S_mass_at_last_time / total_gas_mass_at_last_time) + ejected_S_mass_at_this_time
if total_S_mass_at_this_time < 0.0001:
total_S_mass_at_this_time = 0.0001
total_Fe_mass_at_this_time = total_Fe_mass_at_last_time - lockup_and_outflow_mass * (
total_Fe_mass_at_last_time / total_gas_mass_at_last_time) + ejected_Fe_mass_at_this_time
if total_Fe_mass_at_this_time < 0.0001:
total_Fe_mass_at_this_time = 0.0001
# # calculate the gravitational binding engergy:
#
# # galaxy_mass_without_gas_at_this_time, original_gas_mass, total_gas_mass_at_this_time, ejected_gas_mass_at_this_time
# # gas_mass = max(ejected_gas_mass_at_this_time, 1)
#
# # galaxy mass--radii relation adopted from Dabringhausen 2008 eq.4
# Dabringhausen_2008_a = 2.95
# Dabringhausen_2008_b = 0.596
# initial_expansion_factor = 10000 # need change for every simulation. use the expansion_factor at final time
# # initial_expansion_factor = expansion_factor_list[-1]
# if expansion_factor_list == []:
# current_expansion_factor = initial_expansion_factor
# else:
# current_expansion_factor = initial_expansion_factor - expansion_factor_list[-1]
#
# log_binding_energy = round(
# math.log(3 / 5 * gravitational_constant * 1.989**2 / 3.086, 10) + 40 + (2 - Dabringhausen_2008_b) *
# math.log(original_gas_mass, 10) - math.log(Dabringhausen_2008_a, 10) +
# 6 * Dabringhausen_2008_b + math.log(current_expansion_factor, 10), 3)
# # 40 = 30 (solar mass) * 2 - 11 (Gravitational constant) - 16 (pc to meter) + 7 (J to erg)
# binding_energy = 10 ** log_binding_energy # [erg]
# calculate the kinetic energy of the gas if they have a uniform temperature of 2 keV:
X_for_H = total_H_mass_at_this_time / total_gas_mass_at_this_time
Y_for_He = total_He_mass_at_this_time / total_gas_mass_at_this_time
Z_for_metal = total_metal_mass_at_this_time / total_gas_mass_at_this_time
mean_molecular_weight = 1 / (2 * X_for_H + 3 / 4 * Y_for_He + Z_for_metal / 2) * \
element_weight_table.function_element_weight("H") / 6.022140857 / 1.9891
# / 10**23 / 10**33 (i.e., 10**56) mean_molecular_weight in solar mass unit.
log_mean_molecular_weight = math.log(mean_molecular_weight, 10) - 56 # log [M_sun]
log_total_number_of_molecule = math.log(total_gas_mass_at_this_time,
10) - log_mean_molecular_weight # log [Number]
# 1 [keV] = 1.60217662 * 10**(-9) [erg]
log_energy_per_molecule = math.log(2 * 1.60217662, 10) - 9 # [erg]
log_total_gas_kinetic_energy = log_total_number_of_molecule + log_energy_per_molecule # log [erg]
total_gas_kinetic_energy = 10 ** log_total_gas_kinetic_energy
# if outflow is None:
# if total_energy_release == 0:
# outflow = None
# elif math.log(total_energy_release, 10) + 51 > log_binding_energy:
# outflow = True
# elif outflow == True:
# if total_energy_release == 0:
# outflow = None
# elif math.log(total_energy_release, 10) + 51 < log_binding_energy:
# outflow = None
#
# if gas_infall == True:
# function_update_element_gas_infall()
# gas metallicity_at_this_time = total_metal_mass_at_this_time (in gas) / total_gas_mass_at_this_time
Z_over_X = math.log(total_metal_mass_at_this_time / total_H_mass_at_this_time, 10) - math.log(Z_solar / X_solar,
10)
# Fe_H_mass_ratio_at_this_time = total_Fe_mass_at_this_time / total_H_mass_at_this_time
gas_X_at_this_time = X_for_H
gas_Y_at_this_time = Y_for_He
gas_Z_at_this_time = Z_for_metal
O_over_H_number_ratio = function_element_abundunce(solar_abu_table, "O", "H",
total_O_mass_at_this_time, total_H_mass_at_this_time, False)
Mg_over_H_number_ratio = function_element_abundunce(solar_abu_table, "Mg", "H",
total_Mg_mass_at_this_time, total_H_mass_at_this_time, False)
C_over_H_number_ratio = function_element_abundunce(solar_abu_table, "C", "H",
total_C_mass_at_this_time, total_H_mass_at_this_time, False)
N_over_H_number_ratio = function_element_abundunce(solar_abu_table, "N", "H",
total_N_mass_at_this_time, total_H_mass_at_this_time, False)
Ca_over_H_number_ratio = function_element_abundunce(solar_abu_table, "Ca", "H",
total_Ca_mass_at_this_time, total_H_mass_at_this_time, False)
S_over_H_number_ratio = function_element_abundunce(solar_abu_table, "S", "H",
total_S_mass_at_this_time, total_H_mass_at_this_time, False)
Si_over_H_number_ratio = function_element_abundunce(solar_abu_table, "Si", "H",
total_Si_mass_at_this_time, total_H_mass_at_this_time, False)
Ne_over_H_number_ratio = function_element_abundunce(solar_abu_table, "Ne", "H",
total_Ne_mass_at_this_time, total_H_mass_at_this_time, False)
Fe_over_H_number_ratio = function_element_abundunce(solar_abu_table, "Fe", "H",
total_Fe_mass_at_this_time, total_H_mass_at_this_time, False)
C_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "C", "Fe",
total_C_mass_at_this_time, total_Fe_mass_at_this_time, False)
N_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "N", "Fe",
total_N_mass_at_this_time, total_Fe_mass_at_this_time, False)
O_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "O", "Fe",
total_O_mass_at_this_time, total_Fe_mass_at_this_time, False)
Mg_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "Mg", "Fe",
total_Mg_mass_at_this_time, total_Fe_mass_at_this_time, False)
Ca_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "Ca", "Fe",
total_Ca_mass_at_this_time, total_Fe_mass_at_this_time, False)
Ne_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "Ne", "Fe",
total_Ne_mass_at_this_time, total_Fe_mass_at_this_time, False)
S_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "S", "Fe",
total_S_mass_at_this_time, total_Fe_mass_at_this_time, False)
Si_over_Fe_number_ratio = function_element_abundunce(solar_abu_table, "Si", "Fe",
total_Si_mass_at_this_time, total_Fe_mass_at_this_time, False)
### Element abundances in of stars (consider only the metal of stellar surface, i.e., neglect stellar evolution
# This raises errors from very low mass stars which are fully convective but may not be observationally important):
##### mass weighted abundances
# (total metal in stars / total H in stars):
if stellar_mass_at_this_time > 0:
mass_weighted_stellar_X = stellar_H_mass_at_this_time / stellar_mass_at_this_time
else:
mass_weighted_stellar_X = 0
if stellar_mass_at_this_time > 0:
mass_weighted_stellar_Y = stellar_He_mass_at_this_time / stellar_mass_at_this_time
else:
mass_weighted_stellar_Y = 0
if stellar_mass_at_this_time > 0:
mass_weighted_stellar_Z = stellar_metal_mass_at_this_time / stellar_mass_at_this_time
else:
mass_weighted_stellar_Z = 0
mass_weighted_stellar_O_over_H = function_element_abundunce(solar_abu_table, "O", "H",
stellar_O_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_Mg_over_H = function_element_abundunce(solar_abu_table, "Mg", "H",
stellar_Mg_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_C_over_H = function_element_abundunce(solar_abu_table, "C", "H",
stellar_C_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_N_over_H = function_element_abundunce(solar_abu_table, "N", "H",
stellar_N_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_Ca_over_H = function_element_abundunce(solar_abu_table, "Ca", "H",
stellar_Ca_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_Si_over_H = function_element_abundunce(solar_abu_table, "Si", "H",
stellar_Si_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_S_over_H = function_element_abundunce(solar_abu_table, "S", "H",
stellar_S_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_Ne_over_H = function_element_abundunce(solar_abu_table, "Ne", "H",
stellar_Ne_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_Fe_over_H = function_element_abundunce(solar_abu_table, "Fe", "H",
stellar_Fe_mass_at_this_time,
stellar_H_mass_at_this_time, False)
mass_weighted_stellar_C_over_Fe = function_element_abundunce(solar_abu_table, "C", "Fe",
stellar_C_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_N_over_Fe = function_element_abundunce(solar_abu_table, "N", "Fe",
stellar_N_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_O_over_Fe = function_element_abundunce(solar_abu_table, "O", "Fe",
stellar_O_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_Mg_over_Fe = function_element_abundunce(solar_abu_table, "Mg", "Fe",
stellar_Mg_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_Ca_over_Fe = function_element_abundunce(solar_abu_table, "Ca", "Fe",
stellar_Ca_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_Ne_over_Fe = function_element_abundunce(solar_abu_table, "Ne", "Fe",
stellar_Ne_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_S_over_Fe = function_element_abundunce(solar_abu_table, "S", "Fe",
stellar_S_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
mass_weighted_stellar_Si_over_Fe = function_element_abundunce(solar_abu_table, "Si", "Fe",
stellar_Si_mass_at_this_time,
stellar_Fe_mass_at_this_time, False)
##### luminosity weighted abundances
# (total metal in stars / total H in stars):
if stellar_luminosity_at_this_time > 0:
luminosity_weighted_stellar_X = stellar_H_luminosity_at_this_time / stellar_luminosity_at_this_time
else:
luminosity_weighted_stellar_X = 0
if stellar_luminosity_at_this_time > 0:
luminosity_weighted_stellar_Y = stellar_He_luminosity_at_this_time / stellar_luminosity_at_this_time
else:
luminosity_weighted_stellar_Y = 0
if stellar_luminosity_at_this_time > 0:
luminosity_weighted_stellar_Z = stellar_metal_luminosity_at_this_time / stellar_luminosity_at_this_time
else:
luminosity_weighted_stellar_Z = 0
# below the input shall be the luminosity-weighted element mass,
# e.g., stellar_O_luminosity_at_this_time / stellar_luminosity_at_this_time * total-stellar-mass-at-this-time,
# but since stellar_luminosity_at_this_time and total-stellar-mass-at-this-time are the same for both element,
# the constants cancel in function_element_abundunce.
luminosity_weighted_stellar_O_over_H = function_element_abundunce(solar_abu_table, "O", "H",
stellar_O_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_Mg_over_H = function_element_abundunce(solar_abu_table, "Mg", "H",
stellar_Mg_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_C_over_H = function_element_abundunce(solar_abu_table, "C", "H",
stellar_C_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_N_over_H = function_element_abundunce(solar_abu_table, "N", "H",
stellar_N_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_Ca_over_H = function_element_abundunce(solar_abu_table, "Ca", "H",
stellar_Ca_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_Si_over_H = function_element_abundunce(solar_abu_table, "Si", "H",
stellar_Si_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_S_over_H = function_element_abundunce(solar_abu_table, "S", "H",
stellar_S_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_Ne_over_H = function_element_abundunce(solar_abu_table, "Ne", "H",
stellar_Ne_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_Fe_over_H = function_element_abundunce(solar_abu_table, "Fe", "H",
stellar_Fe_luminosity_at_this_time,
stellar_H_luminosity_at_this_time, False)
luminosity_weighted_stellar_C_over_Fe = function_element_abundunce(solar_abu_table, "C", "Fe",
stellar_C_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_N_over_Fe = function_element_abundunce(solar_abu_table, "N", "Fe",
stellar_N_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_O_over_Fe = function_element_abundunce(solar_abu_table, "O", "Fe",
stellar_O_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_Mg_over_Fe = function_element_abundunce(solar_abu_table, "Mg", "Fe",
stellar_Mg_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_Ca_over_Fe = function_element_abundunce(solar_abu_table, "Ca", "Fe",
stellar_Ca_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_Ne_over_Fe = function_element_abundunce(solar_abu_table, "Ne", "Fe",
stellar_Ne_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_S_over_Fe = function_element_abundunce(solar_abu_table, "S", "Fe",
stellar_S_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
luminosity_weighted_stellar_Si_over_Fe = function_element_abundunce(solar_abu_table, "Si", "Fe",
stellar_Si_luminosity_at_this_time,
stellar_Fe_luminosity_at_this_time, False)
if stellar_H_mass_at_this_time == 0:
mass_weighted_stellar_Z_over_X = math.log(Z_0 / Z_solar, 10) # approximated with [Z]
luminosity_weighted_stellar_Z_over_X = mass_weighted_stellar_Z_over_X
else:
mass_weighted_stellar_Z_over_X = math.log(stellar_metal_mass_at_this_time / stellar_H_mass_at_this_time, 10) \
- math.log(Z_solar / X_solar, 10)
luminosity_weighted_stellar_Z_over_X = math.log(
stellar_metal_luminosity_at_this_time / stellar_H_luminosity_at_this_time, 10) \
- math.log(Z_solar / X_solar, 10)
# the so called [Z/H] as determined by observation with equation: [Z/H] = [Fe/H] + A[Mg/Fe] where A=0.94 (Thomas 2003)
if mass_weighted_stellar_Fe_over_H is None or mass_weighted_stellar_Mg_over_Fe is None:
mass_weighted_stellar_Z_over_H = None
else:
mass_weighted_stellar_Z_over_H = mass_weighted_stellar_Fe_over_H + 0.94 * mass_weighted_stellar_Mg_over_Fe
luminosity_weighted_stellar_Z_over_H = luminosity_weighted_stellar_Fe_over_H + 0.94 * luminosity_weighted_stellar_Mg_over_Fe
##########################################
##### luminosity weighted abundances #####
##########################################
if BH_mass_till_this_time == 0:
BH_mass_list += [10 ** (-10)]
else:
BH_mass_list += [BH_mass_till_this_time]
if NS_mass_till_this_time == 0:
NS_mass_list += [10 ** (-10)]
else:
NS_mass_list += [NS_mass_till_this_time]
if WD_mass_till_this_time == 0:
WD_mass_list += [10 ** (-10)]
elif WD_mass_till_this_time < 0:
Warning_WD_mass_till_this_time = True
# Warning: more SNIa formed than WD avaliable. Please modify the SNIa rate assumption
WD_mass_list += [10 ** (-10)]
else:
WD_mass_list += [WD_mass_till_this_time]
if Z_over_X == 0:
print("Warning: Z_over_X == 0")
gas_Z_over_X_list += [math.log(Z_0 / Z_solar, 10)] # approximated with [Z]
else:
gas_Z_over_X_list += [Z_over_X]
ejected_O_mass_till_this_time_tot_list += [ejected_O_mass_till_this_time]
ejected_O_mass_till_this_time_SNII_list += [O_production_SNII]
ejected_O_mass_till_this_time_SNIa_list += [ejected_O_mass_till_this_time - O_production_SNII]
ejected_Mg_mass_till_this_time_tot_list += [ejected_Mg_mass_till_this_time]
ejected_Mg_mass_till_this_time_SNII_list += [Mg_production_SNII]
ejected_Mg_mass_till_this_time_SNIa_list += [ejected_Mg_mass_till_this_time - Mg_production_SNII]
ejected_Fe_mass_till_this_time_tot_list += [ejected_Fe_mass_till_this_time]
ejected_Fe_mass_till_this_time_SNII_list += [Fe_production_SNII]
ejected_Fe_mass_till_this_time_SNIa_list += [ejected_Fe_mass_till_this_time - Fe_production_SNII]
ejected_Ca_mass_till_this_time_tot_list += [ejected_Ca_mass_till_this_time]
ejected_Ca_mass_till_this_time_SNII_list += [Ca_production_SNII]
ejected_Ca_mass_till_this_time_SNIa_list += [ejected_Ca_mass_till_this_time - Ca_production_SNII]
ejected_S_mass_till_this_time_tot_list += [ejected_S_mass_till_this_time]
ejected_S_mass_till_this_time_SNII_list += [S_production_SNII]
ejected_S_mass_till_this_time_SNIa_list += [ejected_S_mass_till_this_time - S_production_SNII]
ejected_Si_mass_till_this_time_tot_list += [ejected_Si_mass_till_this_time]
ejected_Si_mass_till_this_time_SNII_list += [Si_production_SNII]
ejected_Si_mass_till_this_time_SNIa_list += [ejected_Si_mass_till_this_time - Si_production_SNII]
ejected_Ne_mass_till_this_time_tot_list += [ejected_Ne_mass_till_this_time]
ejected_Ne_mass_till_this_time_SNII_list += [Ne_production_SNII]
ejected_Ne_mass_till_this_time_SNIa_list += [ejected_Ne_mass_till_this_time - Ne_production_SNII]
X_list += [gas_X_at_this_time]
Y_list += [gas_Y_at_this_time]
Z_list += [gas_Z_at_this_time]
O_over_H_list += [O_over_H_number_ratio]
Mg_over_H_list += [Mg_over_H_number_ratio]
C_over_H_list += [C_over_H_number_ratio]
N_over_H_list += [N_over_H_number_ratio]
Ca_over_H_list += [Ca_over_H_number_ratio]
Si_over_H_list += [Si_over_H_number_ratio]
S_over_H_list += [S_over_H_number_ratio]
Ne_over_H_list += [Ne_over_H_number_ratio]
Fe_over_H_list += [Fe_over_H_number_ratio]
C_over_Fe_list += [C_over_Fe_number_ratio]
N_over_Fe_list += [N_over_Fe_number_ratio]
O_over_Fe_list += [O_over_Fe_number_ratio]
Mg_over_Fe_list += [Mg_over_Fe_number_ratio]
Ca_over_Fe_list += [Ca_over_Fe_number_ratio]
Ne_over_Fe_list += [Ne_over_Fe_number_ratio]
S_over_Fe_list += [S_over_Fe_number_ratio]
Si_over_Fe_list += [Si_over_Fe_number_ratio]
stellar_O_over_H_list += [mass_weighted_stellar_O_over_H]
stellar_Mg_over_H_list += [mass_weighted_stellar_Mg_over_H]
stellar_C_over_H_list += [mass_weighted_stellar_C_over_H]
stellar_N_over_H_list += [mass_weighted_stellar_N_over_H]
stellar_Ca_over_H_list += [mass_weighted_stellar_Ca_over_H]
stellar_Si_over_H_list += [mass_weighted_stellar_Si_over_H]
stellar_S_over_H_list += [mass_weighted_stellar_S_over_H]
stellar_Ne_over_H_list += [mass_weighted_stellar_Ne_over_H]
stellar_X_list += [mass_weighted_stellar_X]
stellar_Y_list += [mass_weighted_stellar_Y]
stellar_Z_list += [mass_weighted_stellar_Z]
stellar_Fe_over_H_list += [mass_weighted_stellar_Fe_over_H]
stellar_C_over_Fe_list += [mass_weighted_stellar_C_over_Fe]
stellar_N_over_Fe_list += [mass_weighted_stellar_N_over_Fe]
stellar_O_over_Fe_list += [mass_weighted_stellar_O_over_Fe]
stellar_Mg_over_Fe_list += [mass_weighted_stellar_Mg_over_Fe]
stellar_Ca_over_Fe_list += [mass_weighted_stellar_Ca_over_Fe]
stellar_Ne_over_Fe_list += [mass_weighted_stellar_Ne_over_Fe]
stellar_S_over_Fe_list += [mass_weighted_stellar_S_over_Fe]
stellar_Si_over_Fe_list += [mass_weighted_stellar_Si_over_Fe]
stellar_Z_over_X_list += [mass_weighted_stellar_Z_over_X]
stellar_Z_over_H_list += [mass_weighted_stellar_Z_over_H]
stellar_O_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_O_over_H]
stellar_Mg_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Mg_over_H]
stellar_C_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_C_over_H]
stellar_N_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_N_over_H]
stellar_Ca_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Ca_over_H]
stellar_Si_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Si_over_H]
stellar_S_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_S_over_H]
stellar_Ne_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Ne_over_H]
stellar_X_list_luminosity_weighted += [luminosity_weighted_stellar_X]
stellar_Y_list_luminosity_weighted += [luminosity_weighted_stellar_Y]
stellar_Z_list_luminosity_weighted += [luminosity_weighted_stellar_Z]
stellar_Fe_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Fe_over_H]
stellar_C_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_C_over_Fe]
stellar_N_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_N_over_Fe]
stellar_O_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_O_over_Fe]
stellar_Mg_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_Mg_over_Fe]
stellar_Ca_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_Ca_over_Fe]
stellar_Ne_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_Ne_over_Fe]
stellar_S_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_S_over_Fe]
stellar_Si_over_Fe_list_luminosity_weighted += [luminosity_weighted_stellar_Si_over_Fe]
stellar_Z_over_X_list_luminosity_weighted += [luminosity_weighted_stellar_Z_over_X]
stellar_Z_over_H_list_luminosity_weighted += [luminosity_weighted_stellar_Z_over_H]
if remnant_mass_at_this_time == 0:
remnant_mass_list += [10 ** (-10)]
else:
remnant_mass_list += [remnant_mass_at_this_time]
if total_gas_mass_at_this_time == 0:
total_gas_mass_list += [10 ** (-10)]
else:
total_gas_mass_list += [total_gas_mass_at_this_time]
if ejected_gas_mass_till_this_time == 0 or ejected_gas_mass_till_this_time < 0:
ejected_gas_mass_list += [10 ** (-10)]
else:
ejected_gas_mass_list += [ejected_gas_mass_till_this_time]
ejected_gas_Mg_over_Fe_list += [ejected_gas_Mg_over_Fe_till_this_time]
instant_ejected_gas_Mg_over_Fe_list += [ejected_gas_Mg_over_Fe_at_this_time]
if M_tot_up_to_this_time > 0:
ejected_metal_mass_list += [ejected_metal_mass_till_this_time / M_tot_up_to_this_time]
else:
ejected_metal_mass_list += [0]
if expansion_factor_instantaneous_list == []:
expansion_factor_instantaneous_list += [1]
else:
expansion_factor_instantaneous_list += [
expansion_factor_instantaneous * expansion_factor_instantaneous_list[-1]]
if expansion_factor_adiabat_list == []:
expansion_factor_adiabat_list += [1]
else:
expansion_factor_adiabat_list += [expansion_factor_adiabat * expansion_factor_adiabat_list[-1]]
if expansion_factor_list == []:
expansion_factor_list += [1]
else:
expansion_factor_list += [expansion_factor * expansion_factor_list[-1]]
if stellar_mass_at_this_time == 0:
stellar_mass_list += [10 ** (-10)]
else:
stellar_mass_list += [stellar_mass_at_this_time]
SNIa_energy_release_list += [SNIa_energy_release]
SNIa_number_list += [SNIa_number_from_all_epoch]
if len(SNIa_number_per_century) == 0:
SNIa_number_per_century += [SNIa_number_list[0]]
else:
SNIa_number_per_century += [
(SNIa_number_list[-1] - SNIa_number_list[-2]) / (time_axis[time_step] - time_axis[time_step - 1]) * 100]
SNII_energy_release_list += [SNII_energy_release]
SNII_number_list += [SNII_number]
if len(SNII_number_per_century) == 0:
SNII_number_per_century += [SNII_number_list[0]]
else:
SNII_number_per_century += [
(SNII_number_list[-1] - SNII_number_list[-2]) / (time_axis[time_step] - time_axis[time_step - 1]) * 100]
if total_energy_release == 0:
total_energy_release_list += [0]
else:
total_energy_release_list += [total_energy_release] # [math.log((total_energy_release), 10)]
# if binding_energy == 0:
# binding_energy_list += [0]
# else:
# binding_energy_list += [binding_energy]#[math.log((binding_energy), 10)]
if total_gas_kinetic_energy_list == 0:
total_gas_kinetic_energy_list += [0]
else:
total_gas_kinetic_energy_list += [total_gas_kinetic_energy] # [math.log((total_gas_kinetic_energy), 10)]
SN_number_per_century += [SNIa_number_per_century[-1] + SNII_number_per_century[-1]]
# go to next time step
if time_step / 50 > gc_collect_check:
gc_collect_check += 1
print("gc_collect:", gc_collect_check)
gc.collect()
(time_step) = (time_step + 1)
######################
### Show Warnings ###
######################
if Warning_ejected_gas_mass_of_this_epoch == True:
print('Warning: ejected_gas_mass_of_this_epoch < 0. See comments in galevo.py')
if Warning_WD_mass_till_this_time == True:
print("Warning: WD_mass_till_this_time < 0. See comments in galevo.py")
if Warning_galaxy_mass_ejected_gas_mass == True:
print('Warning: galaxy_mass < ejected_gas_mass. See comments in galevo.py.')
# Warning: galaxy_mass < ejected_gas_mass.
# This is due to too large a timestep.
# It is easy to aviod this issue by applying the "high_time_resolution=True"
# but the simulation will take much longer time.
computation_time_seconds = round((time.time() - start_time), 2)
minutes, seconds = divmod(computation_time_seconds, 60)
hours, minutes = divmod(minutes, 60)
days, hours = divmod(hours, 24)
print("- Simulation complete. Computation time: {} d {} h {} m {} s -".format(days, hours, minutes, seconds))
###################
### output data ###
###################
# Remnant_Star_ratio = [0]*len(stellar_mass_list)
# for i in range(len(remnant_mass_list)):
# Remnant_Star_ratio[i] = remnant_mass_list[i]/stellar_mass_list[i]
# import csv
# with open('GalEvo_time.txt', 'w') as f:
# writer = csv.writer(f, delimiter=' ')
# f.write("# galevo.py output file.\n# time\n")
# writer.writerows(
# zip(time_axis))
# with open('GalEvo_ratio.txt', 'w') as f:
# writer = csv.writer(f, delimiter=' ')
# f.write("# galevo.py output file.\n# Remnant_Star_ratio\n")
# writer.writerows(
# zip(Remnant_Star_ratio))
###################
### output ###
###################
log_Z_0 = round(math.log(Z_0 / Z_solar, 10), 2)
text_output(imf, STF, round(math.log(max(SFH_input), 10), 1), SFEN, original_gas_mass, log_Z_0)
# if output plot applies
plot_output(plot_show, plot_save, imf, igimf, round(math.log(max(SFH_input), 10), 1), SFEN, log_Z_0, STF)
###################
### end ###
###################
return
# def function_update_element_gas_infall():
# return
# # calculate the diet_Salpeter_mass_to_number_ratio:
# Bell & de Jong (2001). Salpeter IMF x = 1.35 with a flat x = 0 slope below 0.35
def function_xi_diet_Salpeter_IMF(mass):
# integrate this function's output xi result in the number of stars in mass limits.
xi = diet_Salpeter_IMF.custom_imf(mass, 0)
return xi
def function_mass_diet_Salpeter_IMF(mass):
# integrate this function's output m result in the total stellar mass for stars in mass limits.
m = mass * diet_Salpeter_IMF.custom_imf(mass, 0)
return m
integrate_all_for_function_mass_SNIa = quad(function_mass_diet_Salpeter_IMF, 0.1, 100, limit=50)[0]
integrate_28_for_function_number_SNIa = quad(function_xi_diet_Salpeter_IMF, 1.5, 8, limit=30)[0]
diet_Salpeter_mass_to_number_ratio = integrate_all_for_function_mass_SNIa / integrate_28_for_function_number_SNIa
def function_number_SNIa(last_delay_time, this_delay_time, stellar_number_in_SNIa_boundary, S_F_R_of_this_epoch):
# This function calculate the number of SNIa between last_delay_time and this_delay_time
# It is commonly assumed that the maximum stellar mass able to produce a degenerate C–O white dwarf is 8 M⊙,
# The minimum possible binary mass is assumed to be 3 M⊙ in order to ensure that the
# smallest possible white dwarf can accrete enough mass from the secondary star to reach the Chandrasekhar mass.
# see Greggio, L., & Renzini, A. 1983, A & A, 118, 217
# Thus we should normalize the DTD according to the number (but currently, mass) of stars between 1.5 and 8 solar mass
# normalized with a SNIa assuming fixed diet-Salpeter IMF (Bell et al. 149:289–312, 2003)
# See Dan Maoz and Filippo Mannucci 2012 review
global diet_Salpeter_mass_to_number_ratio
SNIa_normalization_parameter = funtion_SNIa_DTD_normalization_parameter(S_F_R_of_this_epoch)
# SNIa_normalization_parameter considers the possible variation of binary encounter rate in different system density
# integrate SNIa number from last_delay_time to this_delay_time using observationally determined DTD assuming diet-Salpeter IMF
diet_Salpeter_SNIa_number_per_solar_mass = quad(function_SNIa_DTD, last_delay_time, this_delay_time, limit=40)[0]
# calculate actual SNIa event number
SNIa_number = stellar_number_in_SNIa_boundary * SNIa_normalization_parameter * diet_Salpeter_SNIa_number_per_solar_mass * diet_Salpeter_mass_to_number_ratio
# if this_delay_time == 1 * 10 ** 9:
# print("stellar_number_in_SNIa_boundary ===", stellar_number_in_SNIa_boundary)
# print("diet_Salpeter_SNIa_number_per_solar_mass", diet_Salpeter_SNIa_number_per_solar_mass)
# print("SNIa_number ===", SNIa_number)
# SNIa_number = S_F_R_of_this_epoch * 10**7 * 0.0023 * diet_Salpeter_SNIa_number_per_solar_mass / quad(function_SNIa_DTD, 0, 10**10, limit=40)[0]
return SNIa_number
def funtion_SNIa_DTD_normalization_parameter(SFR):
# this modification on the SNIa rate is to honor the fact that the number of SNIa should
# not only depends on the number of potential progenitor but also the density of the stellar system
# as is expected by the dynamical encounter rate.
SFR = 0.0001 # *** comment *** this line to enable the renormalizaion of SNIa number as a function of SFR
x = 2
SFRmatter = SFR + x
logSFR = math.log(SFRmatter, 10)
gamma = 2
SNIa_normalization_parameter = 1 * (logSFR ** gamma + 4)
# This is a toy model relation. Roughly keep the SNIa-rate/stellar-mass-formed unchanged for different SFRs (IMFs).
# When SFR is high, top-heavy IMF reduce the number possible SNIa progenitor within mass range 1.5-8 solar mass.
# the dense stellar region pump the SNIa rate as the stars have a larger chance to meet with another star.
# The lower SFR do not further reduce the SNIa number as the low SFR happens after the star burst epoch
# thus the newly formed star can still meet with stars formed at ealier epochs regredless of its current SFR.
return SNIa_normalization_parameter
####### the following code is for test, showing the renormalization function of SNIa# #######
# xxx = [-4, -3, -2, -1, 0, 1, 2, 3, 4]
# y0 = funtion_SNIa_DTD_normalization_parameter(0.0001)
# yyy = [1, funtion_SNIa_DTD_normalization_parameter(0.001)/y0,
# funtion_SNIa_DTD_normalization_parameter(0.01)/y0, funtion_SNIa_DTD_normalization_parameter(0.1)/y0,
# funtion_SNIa_DTD_normalization_parameter(1)/y0, funtion_SNIa_DTD_normalization_parameter(10)/y0,
# funtion_SNIa_DTD_normalization_parameter(100)/y0, funtion_SNIa_DTD_normalization_parameter(1000)/y0,
# funtion_SNIa_DTD_normalization_parameter(10000)/y0]
#
# plt.rc('font', family='serif')
# plt.rc('xtick', labelsize='x-small')
# plt.rc('ytick', labelsize='x-small')
# fig = plt.figure(200, figsize=(6, 5))
# fig.add_subplot(1, 1, 1)
# plt.plot(xxx, yyy)
# plt.xlabel(r'log$_{10}$(SFR [M$_\odot$/yr])')
# plt.ylabel(r'SNIa Number renormalization')
# plt.legend()
# plt.tight_layout()
# plt.show()
def function_SNIa_DTD(delay_time):
# The delay time distribution (DTD) in the unit of per year per total stellar mass [solar]
# DTD for SNIa is adopted from Maoz & Mannucci 2012, 29, 447–465, their equation 13
# with a consistent assumed IMF – the Bell et al. 2003 diet-Salpeter IMF
if delay_time < 4 * 10 ** 7: # [yr] # 2.3 * 10 ** 7 for a burst of star formation from Greggio 1983
number = 0
else:
number = 10 ** (-4) * delay_time ** (
-1) # Normalized such the DTD integral over 10Gyr for IGIMF is N_SN/M_sun = 2.23* 10^-3 (M_sun^-1)
# number = 2 * 10 ** (-1) * delay_time**(-1.3) #
# number = 9.3200246746 * 10 ** (-4) * delay_time**(-1) # Normalized such the DTD integral over 10Gyr for a diet-Salpeter IMF is N_SN/M_sun = 3* 10^-3 (M_sun^-1).
# This value changes with igimf where top-heavy and bottom-heavy IGIMF will have lower number of SNIa
# as the number of stars within the mass range 3.0001 to 8 solar mass is smaller.
# The observational uncertainty being +-25%. See Maoz & Mannucci 2012 their Table 1
return number
def function_read_lifetime(str_yield_table, Z_select_in_table):
#### if apply instantaneous recycling approximation ####
global instantaneous_recycling
if instantaneous_recycling == True:
mass_1 = 0
mass = [0.08, 1, 1.00001, 150]
lifetime_table = [1e12, 1e12, 0.1, 0.1]
else:
file_lifetime = open(
'yield_tables/rearranged/setllar_lifetime_from_portinari98/portinari98_Z={}.txt'.format(Z_select_in_table),
'r')
data = file_lifetime.readlines()
metallicity = data[1]
mass_1 = data[3]
lifetime_ = data[5]
file_lifetime.close()
mass = [float(x) for x in mass_1.split()]
lifetime_table = [float(x) for x in lifetime_.split()]
return (mass_1, mass, lifetime_table)
def function_read_Mfinal(str_yield_table, Z_select_in_table):
file_final_mass = open(
"yield_tables/rearranged/setllar_final_mass_from_portinari98/portinari98_Z={}.txt".format(Z_select_in_table),
'r')
data = file_final_mass.readlines()
metallicity2 = data[1]
mass_2 = data[3]
Mfinal_ = data[5]
file_final_mass.close()
Mfinal_table = [float(x) for x in Mfinal_.split()]
return (mass_2, Mfinal_table)
def lindexsplit(List, *lindex):
index = list(lindex)
index.sort()
templist1 = []
templist2 = []
templist3 = []
breakcounter = 0
itemcounter = 0
finalcounter = 0
numberofbreaks = len(index)
totalitems = len(List)
lastindexval = index[(len(index) - 1)]
finalcounttrigger = (totalitems - (lastindexval + 1))
for item in List:
itemcounter += 1
indexofitem = itemcounter - 1
nextbreakindex = index[breakcounter]
# Less than the last cut
if breakcounter <= numberofbreaks:
if indexofitem < nextbreakindex:
templist1.append(item)
elif breakcounter < (numberofbreaks - 1):
templist1.append(item)
templist2.append(templist1)
templist1 = []
breakcounter += 1
else:
if indexofitem <= lastindexval and indexofitem <= totalitems:
templist1.append(item)
templist2.append(templist1)
templist1 = []
else:
if indexofitem >= lastindexval and indexofitem < totalitems + 1:
finalcounter += 1
templist3.append(item)
if finalcounter == finalcounttrigger:
templist2.append(templist3)
return templist2
def function_read_Mmetal(str_yield_table, Z_select_in_table_2, Z_select_in_table_3):
global mm, zz
if str_yield_table == "portinari98":
file_Metal_eject = open(
'yield_tables/rearranged/setllar_Metal_eject_mass_from_{}/{}_Z={}.txt'.format(str_yield_table, str_yield_table,
Z_select_in_table_2),
'r')
data = file_Metal_eject.readlines()
metallicity = data[1]
mass_2 = data[3]
Metal_eject_ = data[5]
file_Metal_eject.close()
mass = [float(x) for x in mass_2.split()]
Metal_eject_table = [float(x) for x in Metal_eject_.split()]
elif str_yield_table == "WW95":
file_Metal_eject = open(
'yield_tables/rearranged/setllar_Metal_eject_mass_from_{}/{}_Z={}.txt'.format(str_yield_table, str_yield_table,
Z_select_in_table_2),
'r')
data = file_Metal_eject.readlines()
mass_2 = data[3]
Metal_eject_ = data[5]
file_Metal_eject.close()
mass = [float(x) for x in mass_2.split()]
mass = lindexsplit(mass, 153)[1]
Metal_eject_table = [float(x) for x in Metal_eject_.split()]
Metal_eject_table = lindexsplit(Metal_eject_table, 153)[1]
file_Metal_eject = open(
'yield_tables/rearranged/setllar_Metal_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
data = file_Metal_eject.readlines()
mass_2 = data[3]
Metal_eject_ = data[5]
file_Metal_eject.close()
mass_agb = [float(x) for x in mass_2.split()]
mass_agb = lindexsplit(mass_agb, 153)[0]
Metal_eject_table_agb = [float(x) for x in Metal_eject_.split()]
Metal_eject_table_agb = lindexsplit(Metal_eject_table_agb, 153)[0]
mass = mass_agb + mass
Metal_eject_table = Metal_eject_table_agb + Metal_eject_table
return (mass_2, mass, Metal_eject_table)
def function_read_M_element(element, str_yield_table, Z_select_in_table_2, Z_select_in_table_3):
if str_yield_table == "portinari98":
if element == "H":
file_M_eject = open(
'yield_tables/rearranged/setllar_H_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "He":
file_M_eject = open(
'yield_tables/rearranged/setllar_He_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "C":
file_M_eject = open(
'yield_tables/rearranged/setllar_C_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "N":
file_M_eject = open(
'yield_tables/rearranged/setllar_N_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "O":
file_M_eject = open(
'yield_tables/rearranged/setllar_O_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "Mg":
file_M_eject = open(
'yield_tables/rearranged/setllar_Mg_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "Ne":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ne_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "Si":
file_M_eject = open(
'yield_tables/rearranged/setllar_Si_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "S":
file_M_eject = open(
'yield_tables/rearranged/setllar_S_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "Ca":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ca_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
elif element == "Fe":
file_M_eject = open(
'yield_tables/rearranged/setllar_Fe_eject_mass_from_portinari98/portinari98_Z={}.txt'.format(
Z_select_in_table_2),
'r')
else:
file_M_eject = 0
print("Error: element parameter for function_read_M_element do not exsit.")
data = file_M_eject.readlines()
M_eject_ = data[5]
file_M_eject.close()
M_eject_table = [float(x) for x in M_eject_.split()]
elif str_yield_table == "WW95":
if element == "H":
file_M_eject = open(
'yield_tables/rearranged/setllar_H_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "He":
file_M_eject = open(
'yield_tables/rearranged/setllar_He_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "C":
file_M_eject = open(
'yield_tables/rearranged/setllar_C_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "N":
file_M_eject = open(
'yield_tables/rearranged/setllar_N_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "O":
file_M_eject = open(
'yield_tables/rearranged/setllar_O_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "Mg":
file_M_eject = open(
'yield_tables/rearranged/setllar_Mg_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "Ne":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ne_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "Si":
file_M_eject = open(
'yield_tables/rearranged/setllar_Si_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "S":
file_M_eject = open(
'yield_tables/rearranged/setllar_S_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "Ca":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ca_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
elif element == "Fe":
file_M_eject = open(
'yield_tables/rearranged/setllar_Fe_eject_mass_from_WW95/WW95_Z={}.txt'.format(Z_select_in_table_2),
'r')
else:
file_M_eject = 0
print("Error: element parameter for function_read_M_element do not exsit.")
data = file_M_eject.readlines()
M_eject_ = data[5]
file_M_eject.close()
M_eject_table = [float(x) for x in M_eject_.split()]
M_eject_table = lindexsplit(M_eject_table, 153)[1]
if element == "H":
file_M_eject = open(
'yield_tables/rearranged/setllar_H_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "He":
file_M_eject = open(
'yield_tables/rearranged/setllar_He_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "C":
file_M_eject = open(
'yield_tables/rearranged/setllar_C_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "N":
file_M_eject = open(
'yield_tables/rearranged/setllar_N_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "O":
file_M_eject = open(
'yield_tables/rearranged/setllar_O_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "Mg":
file_M_eject = open(
'yield_tables/rearranged/setllar_Mg_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "Ne":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ne_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "Si":
file_M_eject = open(
'yield_tables/rearranged/setllar_Si_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "S":
file_M_eject = open(
'yield_tables/rearranged/setllar_S_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "Ca":
file_M_eject = open(
'yield_tables/rearranged/setllar_Ca_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
elif element == "Fe":
file_M_eject = open(
'yield_tables/rearranged/setllar_Fe_eject_mass_from_marigo01/marigo01_Z={}.txt'.format(
Z_select_in_table_3),
'r')
else:
file_M_eject = 0
print("Error: element parameter for function_read_M_element do not exsit.")
data = file_M_eject.readlines()
M_eject_ = data[5]
file_M_eject.close()
M_eject_table_agb = [float(x) for x in M_eject_.split()]
M_eject_table_agb = lindexsplit(M_eject_table_agb, 153)[0]
M_eject_table = M_eject_table_agb + M_eject_table
return M_eject_table
def get_BH_mass(mass_boundary, mass_grid_table_number, Mtarget_table_number, mass_calibration_factor,
steller_mass_upper_bound):
if mass_boundary < steller_mass_upper_bound:
BH_mass = function_get_target_mass_in_range(max(mass_boundary, 40), steller_mass_upper_bound,
mass_grid_table_number,
Mtarget_table_number, mass_calibration_factor)
else:
BH_mass = 0
return BH_mass
def get_NS_mass(mass_boundary, mass_grid_table_number, Mtarget_table_number, mass_calibration_factor):
if mass_boundary < 40:
NS_mass = function_get_target_mass_in_range(max(mass_boundary, 8), 40, mass_grid_table_number,
Mtarget_table_number, mass_calibration_factor)
else:
NS_mass = 0
return NS_mass
def get_WD_mass(mass_boundary, mass_grid_table_number, Mtarget_table_number, mass_calibration_factor):
if mass_boundary < 8:
WD_mass = function_get_target_mass_in_range(max(mass_boundary, 0.08), 8, mass_grid_table_number,
Mtarget_table_number, mass_calibration_factor)
else:
WD_mass = 0
return WD_mass
def function_get_target_mass_in_range(lower_mass_limit, upper_mass_limit, mass_grid_table_number, Mtarget_table_number,
mass_calibration_factor):
integrate_in_range = quad(integrator_for_function_get_target_mass_in_range, lower_mass_limit, upper_mass_limit,
(mass_grid_table_number, Mtarget_table_number), limit=40)[
0] ####################################
target_mass_in_range = mass_calibration_factor * integrate_in_range
return target_mass_in_range
def integrator_for_function_get_target_mass_in_range(initial_mass, mass_grid_table_number, Mtarget_table_number):
global igimf_mass_function
mass = igimf_mass_function(initial_mass)
mass_fraction = function_get_target_mass(initial_mass, mass_grid_table_number, Mtarget_table_number) / initial_mass
integrator = mass * mass_fraction
return integrator
def function_get_target_mass(initial_mass, mass_grid_table_number, Mtarget_table_number):
global mass_grid_table, mass_grid_table2, Mfinal_table, Mmetal_table, M_element_table
if Mtarget_table_number == 1:
Mtarget_table = Mfinal_table
if Mtarget_table_number == 2:
Mtarget_table = Mmetal_table
if Mtarget_table_number == "H":
Mtarget_table = M_element_table[0]
if Mtarget_table_number == "He":
Mtarget_table = M_element_table[1]
if Mtarget_table_number == "C":
Mtarget_table = M_element_table[2]
if Mtarget_table_number == "N":
Mtarget_table = M_element_table[3]
if Mtarget_table_number == "O":
Mtarget_table = M_element_table[4]
if Mtarget_table_number == "Mg":
Mtarget_table = M_element_table[5]
if Mtarget_table_number == "Ne":
Mtarget_table = M_element_table[6]
if Mtarget_table_number == "Si":
Mtarget_table = M_element_table[7]
if Mtarget_table_number == "S":
Mtarget_table = M_element_table[8]
if Mtarget_table_number == "Ca":
Mtarget_table = M_element_table[9]
if Mtarget_table_number == "Fe":
Mtarget_table = M_element_table[10]
if mass_grid_table_number == 1:
mass_grid_table_n = mass_grid_table
if mass_grid_table_number == 2:
mass_grid_table_n = mass_grid_table2
if initial_mass < mass_grid_table_n[0] or initial_mass > mass_grid_table_n[-1]:
print('Warning: function_get_remnant_mass initial_mass out of range')
print("initial_mass=", initial_mass, "< mass grid lower boundary =", mass_grid_table_n[0])
length_list_mass = len(mass_grid_table_n)
x = round(length_list_mass / 2)
i = 0
low = 0
high = length_list_mass
if initial_mass == mass_grid_table_n[0]:
x = 0
elif initial_mass == mass_grid_table_n[-1]:
x = -1
else:
while i < math.ceil(math.log(length_list_mass, 2)):
if initial_mass == mass_grid_table_n[x]:
break
elif initial_mass > mass_grid_table_n[x]:
low = x
x = x + round((high - x) / 2)
else:
high = x
x = x - round((x - low) / 2)
(i) = (i + 1)
if mass_grid_table_n[x - 1] < initial_mass < mass_grid_table_n[x]:
x = x - 1
target_mass = round(
(Mtarget_table[x] + (Mtarget_table[x + 1] - Mtarget_table[x]) * (initial_mass - mass_grid_table_n[x]) /
(mass_grid_table_n[x + 1] - mass_grid_table_n[x])), 5)
return target_mass
# ### Define initial stellar mass boundary for WD, NS, and BH.
# mass_boundary_WD_to_NS = 8 # [solar mass]
# mass_boundary_NS_to_BH = 40 # [solar mass]
#
# # Define the observational sensitive mass range for galaxy total mass estimation
# mass_boundary_observe = [mass_boundary_observe_low, mass_boundary_observe_up]
# ### Calculate total mass at each time ###
# M_tot = 0
# M_tot_time_list = []
# new_time = 1
# M_tot_list = []
# for SFH in SFH_input:
# formed_mass = SFH * 10 ** 7
# M_tot += formed_mass
# M_tot_time_list += [new_time]
# if M_tot == 0:
# M_tot_list += [1, 1]
# else:
# M_tot_list += [M_tot, M_tot]
# new_time += 10 ** 7
# M_tot_time_list += [new_time]
#
# Log_M_tot = math.log(M_tot, 10)
# M_tot_time_list += [time_axis[-1]]
# M_tot_list += [M_tot_list[-1]]
#
#
# ### Calculate the observational estimated total mass of the galaxy ###
# # Assuming the estimation done everything right, e.g., stellar evolution module, SFH, dust extinction, metallicity,
# # excepet assumed an universal Kroupa IMF that is not what really happend
# # (although this assumption contradict itself because it is impossible to get everything else right with a wrong IMF).
# # We using the stellar population with mass in 0.08 - 3 solar mass to estimate the total stellar mass with Kroupa IMF
# # and compare it with the real total mass
#
# imf_file_name = "{}_IMF".format(IMF_name)
#
# # estimated total mass with Kroupa IMF =
# M_tot_est_list = []
# IMF = __import__(imf_file_name)
# a = quad(IMF.imf, 0.08, steller_mass_upper_bound, limit=50)[0]
# b = quad(IMF.imf, mass_boundary_observe[0], mass_boundary_observe[1], limit=40)[0]
# for mass_in_range in M_in_range_list:
# est_mass = mass_in_range * a / b
# if est_mass == 0:
# M_tot_est_list += [1]
# else:
# M_tot_est_list += [est_mass]
def function_get_igimf_for_this_epoch(SFR_input, Z_over_X, this_time, this_epoch, check_igimf):
# this function calculate igimf, write them in directory Generated_IGIMFs, and import the file
# with igimf = function_get_igimf_for_every_epoch(SFH_input, Z, Z_solar),
# the igimf can be called by: igimf.custom_imf(stellar_mass, this_time).
function_generate_igimf_file(SFR=SFR_input, Z_over_X=Z_over_X, printout=None, sf_epoch=this_epoch,
check_igimf=check_igimf)
if SFR_input == 0:
igimf_file_name = "igimf_SFR_Zero"
else:
igimf_file_name = "igimf_SFR_{}_Fe_over_H_{}".format(round(math.log(SFR_input, 10) * 100000),
round(Z_over_X * 100000))
igimf = __import__(igimf_file_name)
# import os
# if os.path.isfile('Generated_IGIMFs/' + igimf_file_name + '.py'):
# igimf = __import__(igimf_file_name)
# else:
# cwd = os.getcwd()
# igimf = __import__(cwd + '/galIMF/Generated_IGIMFs/' + igimf_file_name)
# if shows ModuleNotFoundError:
# No module named 'igimf_SFR_..._Fe_over_H_...',
# then try clear all (except for the first and last) lines in the file Generated_IGIMFs/all_igimf_list.txt.
# This will force the program to generate new IGIMF functions for future use,
# instead of looking for the IGIMF in the old generated ones.
return igimf
def function_generate_igimf_file(SFR=None, Z_over_X=None, printout=False, sf_epoch=0, check_igimf=False):
# This funtion check if the parameter for generating a new IGIMF match an old one,
# if not, the function generate a new IGIMF and add it to the generated-IGIMF list.
# --------------------------------------------------------------------------------------------------------------------------------
# import modules and libraries
# --------------------------------------------------------------------------------------------------------------------------------
import galimf # galIMF containing IGIMF function and OSGIMF function and additional computational modules
import numpy as np
import math
import time
import os
Generated_IGIMFs_path = 'Generated_IGIMFs'
if os.path.isdir(Generated_IGIMFs_path) == False:
Generated_IGIMFs_path = '/galIMF/Generated_IGIMFs'
if os.path.isdir(Generated_IGIMFs_path) == False:
cwd = os.getcwd()
Generated_IGIMFs_path = cwd + '/galIMF/Generated_IGIMFs'
file_name = '/igimf_SFR_{}_Fe_over_H_{}.py'.format(round(math.log(SFR, 10) * 100000),
round(Z_over_X * 100000))
file_path_and_name = Generated_IGIMFs_path + file_name
# --------------------------------------------------------------------------------------------------------------------------------
# check if the required IGIMF has already been generated
# --------------------------------------------------------------------------------------------------------------------------------
exist = 0
if check_igimf == True:
if os.path.isfile(file_path_and_name):
igimf_file_name = "igimf_SFR_{}_Fe_over_H_{}".format(round(math.log(SFR, 10) * 100000),
round(Z_over_X * 100000))
igimf_____ = __import__(igimf_file_name)
if hasattr(igimf_____, "custom_imf"):
# print("find IGIMF file '{}' for a galaxy with [Z/X]={}, SFR={}".format(file_path_and_name, round(Z_over_X, 2), SFR))
exist = 1
# else:
# print("{} is not a file".format(file_path_and_name))
# check_file = open(Generated_IGIMFs_path + '/all_igimf_list.txt', 'r')
# igimf_list_line = check_file.readlines()
# check_file.close()
# i = 0
# while i < len(igimf_list_line):
# data = [float(a_block) for a_block in igimf_list_line[i].split()]
# if SFR == data[0] and Z_over_X == data[1]:
# exist = 1
# break
# (i) = (i + 1)
if exist == 0 and SFR != 0:
# print("Generating new IGIMF file '{}' for a galaxy with [Z/X]={}, SFR={}".format(file_path_and_name, Z_over_X, SFR))
# # --------------------------------------------------------------------------------------------------------------------------------
# # add new headline into the list file -- all_igimf_list.txt:
# # --------------------------------------------------------------------------------------------------------------------------------
#
# check_file = open('Generated_IGIMFs/all_igimf_list.txt', 'r')
# igimf_list = check_file.read()
# check_file.close()
#
# check_file = open('Generated_IGIMFs/all_igimf_list.txt', 'w')
# new_headline = igimf_list + '{} {}\n'.format(SFR, Z_over_X)
# check_file.write(new_headline)
# check_file.close()
# --------------------------------------------------------------------------------------------------------------------------------
# Define code parameters necesarry for the computations:
# --------------------------------------------------------------------------------------------------------------------------------
# the most crutial ones, which you most likely might want to change
if SFR is None:
SFR = float(
input(
"Please input the galaxy-wide SFR in solar mass per year and ended the input with the return key. "
"(A typical input SFR is from 0.0001 to 10000. "
"We recommed a value smallar than 0.01 for the first run as high SFR calculations take more time.)\n"
"You can input 1e-4 as 0.0001\n"
"\nSFR [Msolar/yr] = "))
# Star Formation Rate [solar mass / yr]
if SFR != 0:
bindw = galimf.resolution_histogram_relative = 10 ** (max((0 - math.log(SFR, 10)), 0) ** (0.2) - 1.9)
# will change the resolution of histogram for optimall sampling automatically addjusted with SFR value.
alpha3_model = 2 # 1 # IMF high-mass-end power-index model, see Function_alpha_3_change in file 'galimf.py'
alpha_2 = 2.3 # IMF middle-mass power-index
alpha_1 = 1.3 # IMF low-mass-end power-index
alpha2_model = 1 # see file 'galimf.py'
alpha1_model = 1 # see file 'galimf.py'
beta_model = 1
# ----------------------------------------------------------------
# Parameters below are internal parameters of the theory.
# Read Yan et al. 2017 carefully before change them!
delta_t = 10. # star formation epoch [Myr]
I_ecl = 1. # normalization factor in the Optimal Sampling condition equation
M_ecl_U = 10 ** 9 # 10**(0.75 * math.log(SFR, 10) + 4.8269) # Recchi 2009
# 10 ** 15 # embedded cluster mass upper limit [solar mass]
M_ecl_L = 5. # embedded cluster mass lower limit [solar mass]
I_str = 1. # normalization factor in the Optimal Sampling condition equation
M_str_L = 0.08 # star mass lower limit [solar mass]
M_turn = 0.5 # IMF power-index breaking mass [solar mass]
M_turn2 = 1. # IMF power-index breaking mass [solar mass]
M_str_U = 150 # star mass upper limit [solar mass]
if printout == True:
print("\n - GalIMF run in progress..")
start_time = time.time()
# --------------------------------------------------------------------------------------------------------------------------------
# Construct IGIMF:
# --------------------------------------------------------------------------------------------------------------------------------
if printout == True:
print("\nCalculating IGIMF......")
galimf.function_galimf(
"I", # IorS ### "I" for IGIMF; "OS" for OSGIMF
SFR, # Star Formation Rate [solar mass / yr]
alpha3_model, # IMF high-mass-end power-index model, see file 'alpha3.py'
delta_t, # star formation epoch [Myr]
Z_over_X,
I_ecl, # normalization factor in the Optimal Sampling condition equation
M_ecl_U, # embedded cluster mass upper limit [solar mass]
M_ecl_L, # embedded cluster mass lower limit [solar mass]
beta_model, ### ECMF power-index model, see file 'beta.py'
I_str, # normalization factor in the Optimal Sampling condition equation
M_str_L, # star mass lower limit [solar mass]
alpha_1, # IMF low-mass-end power-index
alpha1_model, # see file 'alpha1.py'
M_turn, # IMF power-index change point [solar mass]
alpha_2, # IMF middle-mass power-index
alpha2_model, # see file 'alpha2.py'
M_turn2, # IMF power-index change point [solar mass]
M_str_U, # star mass upper limit [solar mass]
printout
)
if printout == True:
### Decorate the output file ###
igimf_raw = np.loadtxt('GalIMF_IGIMF.txt')
if M_str_U - igimf_raw[-1][0] > 0.01:
file = open('GalIMF_IGIMF.txt', 'a')
file.write("{} 0\n\n".format(igimf_raw[-1][0] + 0.01))
file.write("{} 0".format(M_str_U))
file.close()
else:
file = open('GalIMF_IGIMF.txt', 'a')
file.write("{} 0".format(M_str_U))
file.close()
global masses, igimf
masses = np.array(galimf.List_M_str_for_xi_str)
igimf = np.array(galimf.List_xi)
#######################################################
# generated igimf is normalized by default to a total mass formed in 10 Myr given the SFR,
# i.e., total stellar mass.
# to change the normalization, uncomment the below commented part:
#######################################################
# Norm = simps(igimf*masses,masses) #- normalization to a total mass
# Norm = simps(igimf,masses) #- normalization to number of stars
# Mtot1Myr = SFR*10*1.e6 #total mass formed in 10 Myr
# igimf = np.array(igimf)*Mtot1Myr/Norm
#######################################################
global length_of_igimf
length_of_igimf = len(igimf)
def write_imf_input2():
global file, masses, igimf
if SFR == 0:
file = open('Generated_IGIMFs/igimf_SFR_Zero.py', 'w')
file.write("def custom_imf(mass, time): # there is no time dependence for IGIMF\n")
file.write(" return 0\n")
file.close()
else:
file = open('Generated_IGIMFs/igimf_SFR_{}_Fe_over_H_{}.py'.format(round(math.log(SFR, 10) * 100000),
round(Z_over_X * 100000)), 'w')
file.write("# File to define a custom IMF\n"
"# The return value represents the chosen IMF value for the input mass\n\n\n")
file.write("def custom_imf(mass, time): # there is no time dependence for IGIMF\n")
file.write(" if mass < 0.08:\n")
file.write(" return 0\n")
file.write(" elif mass < %s:\n" % masses[1])
if masses[0] - masses[1] == 0:
k = 0
b = 0
else:
k = (igimf[0] - igimf[1]) / (masses[0] - masses[1])
b = igimf[0] - k * masses[0]
file.write(" return {} * mass + {}\n".format(k, b))
write_imf_input_middle2(1)
file.write(" else:\n")
file.write(" return 0\n")
file.close()
return
def write_imf_input_middle2(i):
global file, length_of_igimf
while i < length_of_igimf - 1:
file.write(" elif mass < %s:\n" % masses[i + 1])
if masses[i] - masses[i + 1] == 0:
k = 0
b = 0
else:
k = (igimf[i] - igimf[i + 1]) / (masses[i] - masses[i + 1])
b = igimf[i] - k * masses[i]
file.write(" return {} * mass + {}\n".format(k, b))
(i) = (i + 3)
return
write_imf_input2()
def write_imf_input3():
global file, masses, igimf
if SFR == 0:
file = open('Generated_IGIMFs/igimf_epoch_{}.py'.format(sf_epoch), 'w')
file.write("def custom_imf(mass, time): # there is no time dependence for IGIMF\n")
file.write(" return 0\n")
file.close()
else:
file = open('Generated_IGIMFs/igimf_epoch_{}.py'.format(sf_epoch), 'w')
file.write("# File to define a custom IMF\n"
"# The return value represents the chosen IMF value for the input mass\n\n\n")
file.write("def custom_imf(mass, time): # there is no time dependence for IGIMF\n")
file.write(" if mass < 0.08:\n")
file.write(" return 0\n")
file.write(" elif mass < %s:\n" % masses[1])
if masses[0] - masses[1] == 0:
k = 0
b = 0
else:
k = (igimf[0] - igimf[1]) / (masses[0] - masses[1])
b = igimf[0] - k * masses[0]
file.write(" return {} * mass + {}\n".format(k, b))
write_imf_input_middle2(1)
file.write(" else:\n")
file.write(" return 0\n")
file.close()
return
write_imf_input3()
if printout == True:
print("imf_input.py rewritten for SFR = {} and metallicity = {}\n".format(SFR, Z_over_X))
file = open('../gimf_Fe_over_H.txt', 'w')
file.write("{}".format(Z_over_X))
file.close()
file = open('../gimf_SFR.txt', 'w')
file.write("{}".format(SFR))
file.close()
print(" - GalIMF run completed - Run time: %ss -\n\n" % round((time.time() - start_time), 2))
return
return
def function_element_abundunce(solar_abu_table, element_1_name, element_2_name, metal_1_mass, metal_2_mass, instant_ejection):
# this function calculate the atom number ratio compare to solar value [metal/H]
# The following warning might be due to too large a timestep.
# Try applying the "high_time_resolution=True"
# but the simulation will take longer time.
if metal_2_mass == 0:
if metal_1_mass == 0:
metal_1_over_2 = -6
elif metal_1_mass > 0:
metal_1_over_2 = None
elif metal_1_mass < 0:
if instant_ejection==False:
print("Warning: current {} mass < 0. See galevo.py".format(element_1_name))
metal_1_over_2 = -6
elif metal_2_mass < 0:
if instant_ejection == False:
print("Warning: current {} mass < 0. See galevo.py".format(element_2_name))
if metal_1_mass == 0:
metal_1_over_2 = -6
elif metal_1_mass > 0:
metal_1_over_2 = -6
elif metal_1_mass < 0:
if instant_ejection == False:
print("Warning: current {} mass < 0. See galevo.py".format(element_1_name))
metal_1_over_2 = None
else:
if metal_1_mass == 0:
metal_1_over_2 = None
elif metal_1_mass < 0:
if instant_ejection == False:
print("Warning: current {} mass < 0. See galevo.py".format(element_1_name))
metal_1_over_2 = None
else:
solar_metal_1_logarithmic_abundances = element_abundances_solar.function_solar_element_abundances(
solar_abu_table, element_1_name)
solar_metal_2_logarithmic_abundances = element_abundances_solar.function_solar_element_abundances(
solar_abu_table, element_2_name)
metal_1_element_weight = element_weight_table.function_element_weight(element_1_name)
metal_2_element_weight = element_weight_table.function_element_weight(element_2_name)
metal_1_over_2 = math.log(metal_1_mass / metal_2_mass / metal_1_element_weight * metal_2_element_weight, 10) \
- (solar_metal_1_logarithmic_abundances - solar_metal_2_logarithmic_abundances)
return metal_1_over_2
def function_get_avaliable_Z(str_yield_table):
# extract avalible metallicity in the given grid table
# stellar life-time table and metal production tables have different avalible metal grid.
import os
yield_path = 'yield_tables'
if os.path.isdir(yield_path) == False:
yield_path = '/galIMF/yield_tables'
if os.path.isdir(yield_path) == False:
cwd = os.getcwd()
yield_path = cwd + '/galIMF/yield_tables'
# list 1
file_names_setllar_lifetime_from_str_yield_table = os.listdir(
yield_path + '/rearranged/setllar_lifetime_from_portinari98')
Z_table_list = []
for name in file_names_setllar_lifetime_from_str_yield_table:
length_file_name = len(name)
i = 0
i_start = 0
i_end = 0
while i < length_file_name:
if name[i] == '=':
i_start = i
if name[i] == '.':
i_end = i
(i) = (i + 1)
i = i_start + 1
Z = ''
while i < i_end:
Z += name[i]
(i) = (i + 1)
Z_table_list += [float(Z)]
sorted_Z_table_list = sorted(Z_table_list)
# list 2
file_names_setllar_lifetime_from_str_yield_table = os.listdir(
yield_path + '/rearranged/setllar_Metal_eject_mass_from_{}'.format(str_yield_table))
Z_table_list_2 = []
for name in file_names_setllar_lifetime_from_str_yield_table:
length_file_name = len(name)
i = 0
i_start = 0
i_end = 0
while i < length_file_name:
if name[i] == '=':
i_start = i
if name[i] == '.':
i_end = i
(i) = (i + 1)
i = i_start + 1
Z = ''
while i < i_end:
Z += name[i]
(i) = (i + 1)
Z_table_list_2 += [float(Z)]
sorted_Z_table_list_2 = sorted(Z_table_list_2)
if str_yield_table != "portinari98":
# list 3
file_names_setllar_lifetime_from_str_yield_table = os.listdir(
yield_path + '/rearranged/setllar_Metal_eject_mass_from_marigo01')
Z_table_list_3 = []
for name in file_names_setllar_lifetime_from_str_yield_table:
length_file_name = len(name)
i = 0
i_start = 0
i_end = 0
while i < length_file_name:
if name[i] == '=':
i_start = i
if name[i] == '.':
i_end = i
(i) = (i + 1)
i = i_start + 1
Z = ''
while i < i_end:
Z += name[i]
(i) = (i + 1)
Z_table_list_3 += [float(Z)]
sorted_Z_table_list_3 = sorted(Z_table_list_3)
else:
sorted_Z_table_list_3 = []
return (sorted_Z_table_list, sorted_Z_table_list_2, sorted_Z_table_list_3)
def function_select_metal(Z, Z_table_list):
# the list for stellar lifetime is
# [0.0004, 0.0008, 0.0012, 0.0016, 0.002, 0.0024, 0.0028, 0.0032, 0.0036, 0.004, 0.008, 0.012]
# the list for stellar metallicity is
# [0.0004, 0.004, 0.008, 0.0127]
if Z <= Z_table_list[0]:
Z_select__ = Z_table_list[0]
return Z_select__
elif Z >= Z_table_list[-1]:
Z_select__ = Z_table_list[-1]
return Z_select__
else:
i = 1
while i < len(Z_table_list):
if Z < Z_table_list[i]:
if Z <= (Z_table_list[i] + Z_table_list[i - 1]) / 2:
Z_select__ = Z_table_list[i - 1]
return Z_select__
else:
Z_select__ = Z_table_list[i]
return Z_select__
(i) = (i + 1)
def fucntion_mass_boundary(time, mass_grid_for_lifetime, lifetime):
mass = mass_grid_for_lifetime
length_list_lifetime = len(lifetime)
x = round(length_list_lifetime / 2)
loop_number_fucntion_mass_boundary = math.ceil(math.log(length_list_lifetime, 2))
mass_boundary = 10000
if lifetime[x] == time:
mass_boundary = mass[x]
else:
i = 0
low = 0
high = length_list_lifetime
while i < loop_number_fucntion_mass_boundary:
if lifetime[x] > time:
low = x
x = x + round((high - x) / 2)
else:
high = x
x = x - round((x - low) / 2)
(i) = (i + 1)
if x == length_list_lifetime - 1:
mass_boundary = mass[x]
else:
if lifetime[x - 1] > time > lifetime[x]:
x = x - 1
mass_boundary = round(mass[x] + (mass[x + 1] - mass[x]) * (lifetime[x] - time) / (
lifetime[x] - lifetime[x + 1]), 5)
return mass_boundary
# def function_get_observed_mass(lower_limit, upper_limit, M_tot_for_one_epoch, SFR, integrated_igimf):
# integrator = quad(function_get_xi_from_IGIMF, lower_limit, upper_limit, SFR, limit=40)[0]
# observed_mass = M_tot_for_one_epoch * integrator / integrated_igimf
# return observed_mass
def function_xi_Kroupa_IMF(mass):
# integrate this function's output xi result in the number of stars in mass limits.
xi = Kroupa_IMF.custom_imf(mass, 0)
return xi
def function_mass_Kroupa_IMF(mass):
# integrate this function's output m result in the total stellar mass for stars in mass limits.
m = mass * Kroupa_IMF.custom_imf(mass, 0)
return m
def text_output(imf, STF, SFR, SFEN, original_gas_mass, log_Z_0):
print('Generating txt output files...')
global time_axis
# print("time:", time_axis)
global all_sf_imf
number_of_sf_epoch = len(all_sf_imf)
# data = exec(open("simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/chemical_and_SN_evolution.txt".format(IMF, SFE[0], SFR[0], SFEN[0])).read())
#
# print(data)
#################
### F05 study ###
#################
#
# mass_range_1 = [0.3, 0.4]
# mass_boundary_low = all_sf_imf[0][1]
# mass_boundary_high = all_sf_imf[-1][1]
# print("mass_range_2_boundary_low", all_sf_imf[0][1])
# print("mass_range_2_boundary_high", all_sf_imf[-1][1])
# mass_range_2 = [mass_boundary_low, mass_boundary_high]
# mass_range_1 = [0.3, 0.4]
# mass_range_2 = [0.08, 1]
#
# integrate_Kroupa_stellar_mass_range_1 = quad(function_mass_Kroupa_IMF, mass_range_1[0], mass_range_1[1], limit=40)[0]
# integrate_Kroupa_stellar_mass_range_2 = quad(function_mass_Kroupa_IMF, mass_range_2[0], mass_range_2[1], limit=40)[0]
# integrate_Kroupa_stellar_number_mass_range_1 = \
# quad(function_xi_Kroupa_IMF, mass_range_1[0], mass_range_1[1], limit=40)[0]
# integrate_Kroupa_stellar_number_mass_range_2 = \
# quad(function_xi_Kroupa_IMF, mass_range_2[0], mass_range_2[1], limit=40)[0]
#
# F_mass_Kroupa_IMF = integrate_Kroupa_stellar_mass_range_1 / integrate_Kroupa_stellar_mass_range_2
# F_number_Kroupa_IMF = integrate_Kroupa_stellar_number_mass_range_1 / integrate_Kroupa_stellar_number_mass_range_2
#
# integrate_IGIMF_stellar_mass_range_1 = 0
# integrate_IGIMF_stellar_mass_range_2 = 0
# integrate_IGIMF_stellar_number_mass_range_1 = 0
# integrate_IGIMF_stellar_number_mass_range_2 = 0
# i = 0
# while i < number_of_sf_epoch:
# def function_xi_IGIMF(mass):
# xi = all_sf_imf[i][0].custom_imf(mass, 0)
# return xi
#
# def function_mass_IGIMF(mass):
# m = mass * all_sf_imf[i][0].custom_imf(mass, 0)
# return m
#
# integrate_IGIMF_stellar_mass_range_1 += quad(function_mass_IGIMF, mass_range_1[0], mass_range_1[1], limit=40)[0]
# integrate_IGIMF_stellar_mass_range_2 += quad(function_mass_IGIMF, mass_range_2[0], mass_range_2[1], limit=40)[0]
# integrate_IGIMF_stellar_number_mass_range_1 += \
# quad(function_xi_IGIMF, mass_range_1[0], mass_range_1[1], limit=40)[0]
# integrate_IGIMF_stellar_number_mass_range_2 += \
# quad(function_xi_IGIMF, mass_range_2[0], mass_range_2[1], limit=40)[0]
# (i) = (i + 1)
#
# F_mass_IGIMF = integrate_IGIMF_stellar_mass_range_1 / integrate_IGIMF_stellar_mass_range_2
# F_number_IGIMF = integrate_IGIMF_stellar_number_mass_range_1 / integrate_IGIMF_stellar_number_mass_range_2
#
# print("F_mass_Kroupa_IMF", F_mass_Kroupa_IMF)
# print("F_mass_IGIMF", F_mass_IGIMF)
# print("F_number_Kroupa_IMF", F_number_Kroupa_IMF)
# print("F_number_IGIMF", F_number_IGIMF)
# print("Number of star formation event epoch (10^7 yr): ", number_of_sf_epoch)
# print("modeled star formation duration:", number_of_sf_epoch/100, "Gyr")
global total_energy_release_list
# print("total number of SN: 10^", round(math.log(total_energy_release_list[-1], 10), 1))
global BH_mass_list, NS_mass_list, WD_mass_list, remnant_mass_list, stellar_mass_list, ejected_gas_mass_list
stellar_mass = round(math.log(stellar_mass_list[-1], 10), 4)
# print("Mass of all alive stars at final time: 10 ^", stellar_mass)
downsizing_relation__star_formation_duration = round(10 ** (2.38 - 0.24 * stellar_mass), 4) # Recchi 2009
# print("star formation duration (downsizing relation):", downsizing_relation__star_formation_duration, "Gyr")
stellar_and_remnant_mass = round(math.log(stellar_mass_list[-1] + remnant_mass_list[-1], 10), 4)
# print("Mass of stars and remnants at final time: 10 ^", stellar_and_remnant_mass)
total_mas_in_box = original_gas_mass
# # Dabringhausen 2008 eq.4
# Dabringhausen_2008_a = 2.95
# Dabringhausen_2008_b = 0.596
# expansion_factor = 5 ################ the expansion_factor should be a funtion of galaxy mass and rise with the mass
# log_binding_energy = round(
# math.log(4.3 * 6 / 5, 10) + 40 + (2 - Dabringhausen_2008_b) * math.log(total_mas_in_box, 10) - math.log(
# Dabringhausen_2008_a, 10) + 6 * Dabringhausen_2008_b + math.log(expansion_factor, 10), 1)
# # print("the gravitational binding energy: 10^", log_binding_energy, "erg")
global Fe_over_H_list, stellar_Fe_over_H_list, stellar_Fe_over_H_list_luminosity_weighted
# print("Gas [Fe/H]:", round(Fe_over_H_list[-1], 3))
# print("Stellar [Fe/H]:", round(stellar_Fe_over_H_list[-1], 3))
global Mg_over_Fe_list, stellar_Mg_over_Fe_list, stellar_Mg_over_Fe_list_luminosity_weighted
# print("Gas [Mg/Fe]:", round(Mg_over_Fe_list[-1], 3))
# print("Stellar [Mg/Fe]:", round(stellar_Mg_over_Fe_list[-1], 3))
global O_over_Fe_list, stellar_O_over_Fe_list, stellar_O_over_Fe_list_luminosity_weighted
# print("Gas [O/Fe]:", round(O_over_Fe_list[-1], 3))
# print("Stellar [O/Fe]:", round(stellar_O_over_Fe_list[-1], 3))
global Mg_over_H_list, stellar_Mg_over_H_list, stellar_Mg_over_H_list_luminosity_weighted
global C_over_H_list, stellar_C_over_H_list, stellar_C_over_H_list_luminosity_weighted
global N_over_H_list, stellar_N_over_H_list, stellar_N_over_H_list_luminosity_weighted
global Ca_over_H_list, stellar_Ca_over_H_list, stellar_Ca_over_H_list_luminosity_weighted
global Si_over_H_list, stellar_Si_over_H_list, stellar_Si_over_H_list_luminosity_weighted
global S_over_H_list, stellar_S_over_H_list, stellar_S_over_H_list_luminosity_weighted
global Ne_over_H_list, stellar_Ne_over_H_list, stellar_Ne_over_H_list_luminosity_weighted
# print("Gas [Mg/H]:", round(Mg_over_H_list[-1], 3))
# print("Stellar [Mg/H]:", round(stellar_Mg_over_H_list[-1], 3))
global O_over_H_list, stellar_O_over_H_list, stellar_O_over_H_list_luminosity_weighted
# print("Gas [O/H]:", round(O_over_H_list[-1], 3))
# print("Stellar [O/H]:", round(stellar_O_over_H_list[-1], 3))
global gas_Z_over_X_list, stellar_Z_over_X_list, stellar_Z_over_X_list_luminosity_weighted, stellar_Z_over_H_list
# print("Gas metallicity:", round(gas_Z_over_X_list[-1], 3))
# print("Stellar metallicity:", round(stellar_Z_over_X_list[-1], 3))
# print("Stellar [Z/H]:", round(stellar_Z_over_H_list[-1], 3))
filename = "simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/chemical_and_SN_evolution.txt".format(imf, STF, SFR, SFEN, log_Z_0)
if not os.path.exists(os.path.dirname(filename)):
try:
os.makedirs(os.path.dirname(filename))
except OSError as exc: # Guard against race condition
if exc.errno != errno.EEXIST:
raise
file = open(
'simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/chemical_and_SN_evolution.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
print("simulation results saved in the file: "
"simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/(plots/)...txt".format(imf, STF, SFR, SFEN,
log_Z_0))
file.write("# Number of star formation event epoch (10^7 yr):\n")
file.write("%s\n" % number_of_sf_epoch)
file.write("# Modeled star formation duration (Gyr):\n")
file.write("{}\n".format(number_of_sf_epoch / 100))
file.write("# Total number of SN (log_10):\n")
file.write("%s\n" % round(math.log(total_energy_release_list[-1], 10), 1))
file.write("# Mass of all alive stars at final time (log_10):\n")
file.write("%s\n" % stellar_mass)
file.write("# Star formation duration of this final stellar mass according to the downsizing relation, Gyr):\n")
file.write("%s\n" % downsizing_relation__star_formation_duration)
file.write("# Mass of stars and remnants at final time (log_10):\n")
file.write("%s\n" % stellar_and_remnant_mass)
file.write("# total mass in the closed-box model:\n")
file.write("%s\n" % total_mas_in_box)
length_of_time_axis = len(time_axis)
file.write("# time step list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % time_axis[i])
(i) = (i + 1)
file.write("\n")
file.write("# Number of SNIa + SNII (log_10):\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % total_energy_release_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Fe/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Fe_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Fe/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Fe_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Mg/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Mg_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Mg/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Mg_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
Mass_weighted_stellar_Mg_over_Fe = stellar_Mg_over_Fe_list[-1]
# print("Mass-weighted stellar [Mg/Fe] at final time:", Mass_weighted_stellar_Mg_over_Fe)
file.write("# Gas [O/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % O_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [O/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_O_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Mg/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Mg_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [C/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % C_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [N/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % N_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Ca/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Ca_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Ne/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Ne_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [Si/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Si_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [S/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % S_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Mg/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Mg_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [C/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_C_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [N/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_N_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Ca/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ca_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Ne/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ne_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [Si/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Si_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [S/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_S_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas [O/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % O_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted [O/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_O_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Gas metallicity, [Z/X]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % gas_Z_over_X_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar mass-weighted metallicity, [Z/X]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Z_over_X_list[i])
(i) = (i + 1)
file.write("\n")
Mass_weighted_stellar_metallicity = stellar_Z_over_X_list[-1]
# print("Mass-weighted stellar [Z/X] at final time:", Mass_weighted_stellar_metallicity)
if SNIa_energy_release_list[-1] < 10 ** (-10):
SNIa_energy_release_list[-1] = 10 ** (-10)
file.write("# Total number of SNIa (log_10):\n")
file.write("%s\n" % round(math.log(SNIa_energy_release_list[-1], 10), 1))
if SNII_energy_release_list[-1] < 10 ** (-10):
SNII_energy_release_list[-1] = 10 ** (-10)
file.write("# Total number of SNII (log_10):\n")
file.write("%s\n" % round(math.log(SNII_energy_release_list[-1], 10), 1))
file.write("# Number of SNIa (log_10):\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % SNIa_energy_release_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Number of SNII (log_10):\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % SNII_energy_release_list[i])
(i) = (i + 1)
file.write("\n")
global ejected_gas_Mg_over_Fe_list
file.write("# [Mg/Fe] for total ejected gas till this time:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % ejected_gas_Mg_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
global instant_ejected_gas_Mg_over_Fe_list
file.write("# [Mg/Fe] for instant ejected gas at this time:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % instant_ejected_gas_Mg_over_Fe_list[i])
(i) = (i + 1)
file.write("\n")
global ejected_metal_mass_list
file.write("# total ejected metal mass till this time:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % ejected_metal_mass_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# initial [M/H]:\n")
file.write("%s " % log_Z_0)
file.write("\n")
file.write("# Stellar [Z/H]. [Z/H] = [Fe/H] + A[Mg/Fe] where A=0.94:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Z_over_H_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted metallicity, [Z/X]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Z_over_X_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Mg/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Mg_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [C/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_C_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [N/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_N_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [O/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_O_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Ca/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ca_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Ne/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ne_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Si/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Si_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [S/Fe]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_S_over_Fe_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [C/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_C_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [N/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_N_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [O/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_O_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Mg/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Mg_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Fe/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Fe_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Ca/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ca_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Ne/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Ne_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [Si/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Si_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Stellar luminosity-weighted [S/H]:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_S_over_H_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# X_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % X_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_X_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_X_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_X_list_luminosity_weighted:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_X_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Y_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Y_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_Y_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Y_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_Y_list_luminosity_weighted:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Y_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.write("# Z_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % Z_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_Z_list:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Z_list[i])
(i) = (i + 1)
file.write("\n")
file.write("# stellar_Z_list_luminosity_weighted:\n")
i = 0
while i < length_of_time_axis:
file.write("%s " % stellar_Z_list_luminosity_weighted[i])
(i) = (i + 1)
file.write("\n")
file.close()
return
def plot_output(plot_show, plot_save, imf, igimf, SFR, SFEN, log_Z_0, STF): # SFR is the maximum SFR.
if plot_show is True:
print('\nGenerating plot outputs...\n')
# plot SFH
global all_sfr
SFR_list = []
age_list = []
age_list.append(0)
SFR_list.append(-10)
age_list.append(0.01)
SFR_list.append(-10)
for i in range(len(all_sfr)):
age_list.append(all_sfr[i][1])
SFR_list.append(math.log(all_sfr[i][0], 10))
age_list.append(all_sfr[i][1] + 0.01)
SFR_list.append(math.log(all_sfr[i][0], 10))
age_list.append(all_sfr[i][1] + 0.01)
SFR_list.append(-10)
age_list.append(10)
SFR_list.append(-10)
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(0, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(age_list, SFR_list)
plt.xlabel('time [Gyr]')
plt.ylabel(r'log$_{10}({\rm SFR} [{\rm M}_\odot$/yr])')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.title('Star formation history')
plt.tight_layout()
# plt.legend()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_SFH.pdf', dpi=250)
filename = "simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/SFH.txt".format(imf, STF, SFR, SFEN, log_Z_0)
if not os.path.exists(os.path.dirname(filename)):
try:
os.makedirs(os.path.dirname(filename))
except OSError as exc: # Guard against race condition
if exc.errno != errno.EEXIST:
raise
length_of_SFH_list = len(SFR_list)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/SFH.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# age_list\n")
i = 0
while i < length_of_SFH_list:
file.write("{} ".format(age_list[i]))
(i) = (i + 1)
file.write("\n# SFR_list\n")
i = 0
while i < length_of_SFH_list:
file.write("{} ".format(SFR_list[i]))
(i) = (i + 1)
file.write("\n")
file.close()
# # plot IMF
global all_sf_imf
number_of_sf_epoch = len(all_sf_imf)
mass_list = []
xi_last_time = []
xi_Kroupa = []
xi_Kroupa_not_log = []
xi_observe = []
xi_each_epoch = []
xi_each_time_log = []
xi_each_time = []
i = 0
while i < number_of_sf_epoch:
xi_each_epoch.append([])
xi_each_time_log.append([])
xi_each_time.append([])
mass = 200
while mass > 0.05:
xi_each_epoch__ = all_sf_imf[i][0].custom_imf(mass, 0)
if xi_each_epoch__ == 0:
xi_each_epoch[i] += [-10]
else:
xi_each_epoch[i] += [math.log(xi_each_epoch__, 10)]
j = 0
xi_each_time__ = 0
while j < i + 1:
xi_each_time__ += all_sf_imf[j][0].custom_imf(mass, 0)
(j) = (j + 1)
if xi_each_time__ == 0:
xi_each_time_log[i] += [-10]
xi_each_time[i] += [0]
else:
xi_each_time_log[i] += [math.log(xi_each_time__, 10)]
xi_each_time[i] += [xi_each_time__]
(mass) = (mass * 0.99)
(i) = (i + 1)
j = 0
xi_1_last_time = 0
while j < number_of_sf_epoch:
xi_1_last_time += all_sf_imf[j][0].custom_imf(1, 0)
(j) = (j + 1)
normal = xi_1_last_time / Kroupa_IMF.custom_imf(1, 0)
mass = 200
while mass > 0.05:
mass_list += [mass]
xi_last_time += [all_sf_imf[-1][0].custom_imf(mass, 0)]
# xi_last_time += [igimf.custom_imf(mass, 0)]
xi_observe__ = 0
for i in range(number_of_sf_epoch):
xi_observe__ += all_sf_imf[i][0].custom_imf(mass, 0)
# if mass < all_sf_imf[i][1]:
# xi_observe__ += all_sf_imf[i][0].custom_imf(mass, 0)
xi_observe += [xi_observe__]
xi_Kroupa__ = Kroupa_IMF.custom_imf(mass, 0) * normal
if xi_Kroupa__ == 0:
xi_Kroupa += [-10]
else:
xi_Kroupa += [math.log(xi_Kroupa__, 10)]
xi_Kroupa_not_log += [xi_Kroupa__]
(mass) = (mass * 0.99)
i = 0
while i < number_of_sf_epoch:
time = round(all_sf_imf[i][2] / 10 ** 6)
file = open('Generated_IGIMFs/imf_at_time_{}_Myr.txt'.format(time), 'w')
file.write("# This file gives the total number of stars in a unit mass interval for a given stellar mass "
"for the entire galaxy, i.e., galaxy-wide Initial Mass Function (gwIMF), at {} Myr.\n".format(time))
file.write("# Below showing the given stellar mass on the left and the corresponding xi on the right, "
"where xi = d number / d mass.\n")
mass_list_length = len(mass_list)
j = mass_list_length - 1
while j > 0:
file.write("{} {}\n".format(mass_list[j], xi_each_time[i][j]))
(j) = (j - 1)
file.close()
(i) = (i + 1)
i = 0
while i < number_of_sf_epoch:
time = round(all_sf_imf[i][2] / 10 ** 6)
length_of_xi = len(mass_list)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/imf_at_time_{}_Myr.txt'.format(imf, STF, SFR, SFEN, log_Z_0, time), 'w')
file.write("# mass_list\n")
j = 0
while j < length_of_xi:
file.write("{} ".format(mass_list[j]))
(j) = (j + 1)
file.write("\n")
file.write("# xi_each_time\n")
j = 0
while j < length_of_xi:
file.write("{} ".format(xi_each_time[i][j]))
(j) = (j + 1)
file.write("\n")
file.write("# xi_Kroupa\n")
j = 0
while j < length_of_xi:
file.write("{} ".format(xi_Kroupa_not_log[j]))
(j) = (j + 1)
file.write("\n")
file.close()
(i) = (i + 1)
for i in range(len(mass_list)):
mass_list[i] = math.log(mass_list[i], 10)
if xi_last_time[i] == 0:
xi_last_time[i] = -10
else:
xi_last_time[i] = math.log(xi_last_time[i], 10)
if xi_observe[i] == 0:
xi_observe[i] = -10
else:
xi_observe[i] = math.log(xi_observe[i], 10)
# if xi_Kroupa[i] == 0:
# xi_Kroupa[i] = -10
# else:
# xi_Kroupa[i] = math.log(xi_Kroupa[i], 10)
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(1, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(mass_list, xi_Kroupa, linestyle='dashed', color='r', label='Kroupa IMF')
i = 0
while i < number_of_sf_epoch:
time = round(all_sf_imf[i][2] / 10**6)
if i < 3:
plt.plot(mass_list, xi_each_time_log[i], label='TIgwIMF at {} Myr'.format(time))
else:
plt.plot(mass_list, xi_each_time_log[i])
(i) = (i + 1)
plt.plot(mass_list, xi_observe, label='final TIgwIMF')
plt.xlabel(r'log$_{10}(M_\star [M_\odot$])')
plt.ylabel(r'log$_{10}(\xi_\star)$')
# plt.ylim(0, 11)
plt.title('Time Integrated galaxy-wide IMF')
plt.legend()
plt.tight_layout()
#
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(2, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(mass_list, xi_Kroupa, linestyle='dashed', color='r', label='Kroupa IMF')
i = 0
while i < number_of_sf_epoch:
if i < 3:
plt.plot(mass_list, xi_each_epoch[i], label='epoch {}'.format(i))
else:
plt.plot(mass_list, xi_each_epoch[i])
(i) = (i + 1)
plt.plot(mass_list, xi_observe, label='final TIgwIMF')
plt.xlabel(r'log$_{10}(M_\star)$ [M$_{\odot}$]')
plt.ylabel(r'$\log_(\xi_\star)$')
plt.title('galaxy-wide IMF of each star formation epoch')
plt.legend()
plt.tight_layout()
################# evolution plots #################
global time_axis
length_of_time_axis = len(time_axis)
log_time_axis = []
for i in range(length_of_time_axis):
if time_axis[i] != 0:
log_time_axis += [math.log((time_axis[i]), 10)]
else:
log_time_axis += [0]
global X_list, stellar_X_list, stellar_X_list_luminosity_weighted
global Y_list, stellar_Y_list, stellar_Y_list_luminosity_weighted
global Z_list, stellar_Z_list, stellar_Z_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(61, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.stackplot(log_time_axis, Y_list, X_list, Z_list, labels=["Y", "X", "Z"])
plt.title('gas-phase H, He, and metal mass fraction')
plt.xlim(7, log_time_axis[-1])
plt.ylim(0, 1)
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('stacked mass fraction')
plt.legend(loc='lower left')
fig = plt.figure(62, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.stackplot(log_time_axis, stellar_Y_list, stellar_X_list, stellar_Z_list, labels=["Y", "X", "Z"])
plt.title('stellar H, He, and metal mass fraction')
plt.xlim(7, log_time_axis[-1])
plt.ylim(0, 1)
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('stacked mass fraction')
plt.legend(loc='lower left')
fig = plt.figure(63, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.stackplot(log_time_axis, stellar_Y_list_luminosity_weighted, stellar_X_list_luminosity_weighted, stellar_Z_list_luminosity_weighted, labels=["Y", "X", "Z"])
plt.title('stellar luminosity-weighted H, He, and metal mass fraction')
plt.xlim(7, log_time_axis[-1])
plt.ylim(0, 1)
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('stacked mass fraction')
plt.legend(loc='lower left')
# global mm, zz
# fig = plt.figure(0, figsize=(6, 5))
# plt.plot(mm, zz)
global Fe_over_H_list, stellar_Fe_over_H_list, stellar_Fe_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(3, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Fe_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_Fe_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Fe_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Fe/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_FeH_{}.pdf'.format(imf), dpi=250)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Fe_over_H_time.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# log_time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(log_time_axis[i]))
(i) = (i + 1)
file.write("\n# gas_Fe_over_H_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(Fe_over_H_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Fe_over_H_list\n")
i = 0
while i < length_of_time_axis:
if stellar_Fe_over_H_list[i] is None:
file.write("{} ".format(-6))
else:
file.write("{} ".format(stellar_Fe_over_H_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Fe_over_H_list_luminosity_weighted\n")
i = 0
while i < length_of_time_axis:
if stellar_Fe_over_H_list_luminosity_weighted[i] is None:
file.write("{} ".format(-6))
else:
file.write("{} ".format(stellar_Fe_over_H_list_luminosity_weighted[i]))
(i) = (i + 1)
file.write("\n")
file.close()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Fe_over_H_mass.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# gas_Fe_over_H\n")
file.write("{} ".format(Fe_over_H_list[-1]))
file.write("\n# stellar_Fe_over_H\n")
file.write("{} ".format(stellar_Fe_over_H_list[-1]))
file.write("\n# stellar_Fe_over_H_list_luminosity_weighted\n")
file.write("{} ".format(stellar_Fe_over_H_list_luminosity_weighted[-1]))
file.write("\n")
file.close()
#
global O_over_H_list, stellar_O_over_H_list, stellar_O_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(4, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, O_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_O_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_O_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[O/H]')
plt.title('Element abundance evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_OH_{}.pdf'.format(imf), dpi=250)
#
global Mg_over_H_list, stellar_Mg_over_H_list, stellar_Mg_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(5, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Mg_over_H_list, label='gas')
# print(stellar_Mg_over_H_list)
plt.plot(log_time_axis, stellar_Mg_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Mg_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Mg/H]')
plt.title('Element abundance evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_MgH_{}.pdf'.format(imf), dpi=250)
###
global C_over_H_list, stellar_C_over_H_list, stellar_C_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(31, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, C_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_C_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_C_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[C/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_CH_{}.pdf'.format(imf), dpi=250)
#
global N_over_H_list, stellar_N_over_H_list, stellar_N_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(32, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, N_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_N_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_N_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[N/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_NH_{}.pdf'.format(imf), dpi=250)
#
global Ca_over_H_list, stellar_Ca_over_H_list, stellar_Ca_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(33, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Ca_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_Ca_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Ca_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Ca/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_CaH_{}.pdf'.format(imf), dpi=250)
#
global Ne_over_H_list, stellar_Ne_over_H_list, stellar_Ne_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(331, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Ne_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_Ne_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Ne_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Ne/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_NeH_{}.pdf'.format(imf), dpi=250)
#
global Si_over_H_list, stellar_Si_over_H_list, stellar_Si_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(332, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Si_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_Si_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Si_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Si/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_SiH_{}.pdf'.format(imf), dpi=250)
#
global S_over_H_list, stellar_S_over_H_list, stellar_S_over_H_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(333, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, S_over_H_list, label='gas')
plt.plot(log_time_axis, stellar_S_over_H_list, label='stellar MW')
plt.plot(log_time_axis, stellar_S_over_H_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[S/H]')
plt.title('Element abundance evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7}, ncol=2)
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-5, 1)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_SH_{}.pdf'.format(imf), dpi=250)
###
solar_helium_abundance = 0.275
# Reference: Serenelli & Basu 2010, Determining the Initial Helium Abundance of the Sun, DOI: 10.1088/0004-637X/719/1/865
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(6, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Y_list, label='gas')
plt.plot(log_time_axis, stellar_Y_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Y_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [solar_helium_abundance, solar_helium_abundance], color='red',
ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('Y')
plt.title('Helium mass fraction evolution')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_Y_{}.pdf'.format(imf), dpi=250)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Y_time.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# log_time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(log_time_axis[i]))
(i) = (i + 1)
file.write("\n# gas_Y_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(Y_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Y_list\n")
i = 0
while i < length_of_time_axis:
if stellar_Y_list[i] is None:
file.write("0.001")
else:
file.write("{} ".format(stellar_Y_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Y_list_luminosity_weighted\n")
i = 0
while i < length_of_time_axis:
if stellar_Y_list_luminosity_weighted[i] is None:
file.write("0.001")
else:
file.write("{} ".format(stellar_Y_list_luminosity_weighted[i]))
(i) = (i + 1)
file.write("\n")
file.close()
#
global Mg_over_Fe_list, stellar_Mg_over_Fe_list, stellar_Mg_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(7, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Mg_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_Mg_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Mg_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Mg/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_MgFe_{}.pdf'.format(imf), dpi=250)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Mg_over_Fe_time.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# log_time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(log_time_axis[i]))
(i) = (i + 1)
file.write("\n# gas_Mg_over_Fe_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(Mg_over_Fe_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Mg_over_Fe_list\n")
i = 0
while i < length_of_time_axis:
if stellar_Mg_over_Fe_list[i] is None:
file.write("-6 ")
else:
file.write("{} ".format(stellar_Mg_over_Fe_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Mg_over_Fe_list_luminosity_weighted\n")
i = 0
while i < length_of_time_axis:
if stellar_Mg_over_Fe_list_luminosity_weighted[i] is None:
file.write("-6 ")
else:
file.write("{} ".format(stellar_Mg_over_Fe_list_luminosity_weighted[i]))
(i) = (i + 1)
file.write("\n")
file.close()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Mg_over_Fe_mass.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# gas_Mg_over_Fe\n")
file.write("{} ".format(Mg_over_Fe_list[-1]))
file.write("\n# stellar_Mg_over_Fe\n")
file.write("{} ".format(stellar_Mg_over_Fe_list[-1]))
file.write("\n# stellar_Mg_over_Fe_list_luminosity_weighted\n")
file.write("{} ".format(stellar_Mg_over_Fe_list_luminosity_weighted[-1]))
file.write("\n")
file.close()
#
global O_over_Fe_list, stellar_O_over_Fe_list, stellar_O_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(8, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, O_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_O_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_O_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[O/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_MgFe_{}.pdf'.format(imf), dpi=250)
#
global Ca_over_Fe_list, stellar_Ca_over_Fe_list, stellar_Ca_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(81, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Ca_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_Ca_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Ca_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Ca/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_CaFe_{}.pdf'.format(imf), dpi=250)
#
global Ne_over_Fe_list, stellar_Ne_over_Fe_list, stellar_Ne_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(811, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Ne_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_Ne_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Ne_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Ne/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_NeFe_{}.pdf'.format(imf), dpi=250)
#
global Si_over_Fe_list, stellar_Si_over_Fe_list, stellar_Si_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(812, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, Si_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_Si_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Si_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[Si/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_SiFe_{}.pdf'.format(imf), dpi=250)
#
global S_over_Fe_list, stellar_S_over_Fe_list, stellar_S_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(813, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, S_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_S_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_S_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[S/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_SFe_{}.pdf'.format(imf), dpi=250)
#
global C_over_Fe_list, stellar_C_over_Fe_list, stellar_C_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(82, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, C_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_C_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_C_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[C/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_CFe_{}.pdf'.format(imf), dpi=250)
#
global N_over_Fe_list, stellar_N_over_Fe_list, stellar_N_over_Fe_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(83, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, N_over_Fe_list, label='gas')
plt.plot(log_time_axis, stellar_N_over_Fe_list, label='stellar MW')
plt.plot(log_time_axis, stellar_N_over_Fe_list_luminosity_weighted, label='stellar LW')
plt.plot([log_time_axis[0], log_time_axis[-1]], [0, 0], color='red', ls='dashed', label='solar')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel('[N/Fe]')
plt.title('Element number ratio evolution')
# plt.xlim(6.4, 1.01 * log_time_axis[-1])
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_NFe_{}.pdf'.format(imf), dpi=250)
#
del Fe_over_H_list[0]
del stellar_Fe_over_H_list[0]
del stellar_Fe_over_H_list[0]
del stellar_Fe_over_H_list_luminosity_weighted[0]
del stellar_Fe_over_H_list_luminosity_weighted[0]
del Mg_over_Fe_list[0]
del stellar_Mg_over_Fe_list[0]
del stellar_Mg_over_Fe_list[0]
del stellar_Mg_over_Fe_list_luminosity_weighted[0]
del stellar_Mg_over_Fe_list_luminosity_weighted[0]
del O_over_Fe_list[0]
del stellar_O_over_Fe_list[0]
del stellar_O_over_Fe_list[0]
del stellar_O_over_Fe_list_luminosity_weighted[0]
del stellar_O_over_Fe_list_luminosity_weighted[0]
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(9, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(Fe_over_H_list, Mg_over_Fe_list, label='gas')
plt.plot(stellar_Fe_over_H_list, stellar_Mg_over_Fe_list, label='stellar MW')
plt.plot(stellar_Fe_over_H_list_luminosity_weighted, stellar_Mg_over_Fe_list_luminosity_weighted,
label='stellar LW')
plt.plot([-5, 1], [0, 0], color='red', ls='dashed', label='solar')
plt.plot([0, 0], [-1, 3.5], color='red', ls='dashed')
plt.xlabel('[Fe/H]')
plt.ylabel('[Mg/Fe]')
# plt.xlim(-5, 1)
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_MgFe-FeH_{}.pdf'.format(imf), dpi=250)
#
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(10, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(Fe_over_H_list, O_over_Fe_list, label='gas')
plt.plot(stellar_Fe_over_H_list, stellar_O_over_Fe_list, label='stellar MW')
plt.plot(stellar_Fe_over_H_list_luminosity_weighted, stellar_O_over_Fe_list_luminosity_weighted,
label='stellar LW')
plt.plot([-5, 1], [0, 0], color='red', ls='dashed', label='solar')
plt.plot([0, 0], [-1, 3.5], color='red', ls='dashed')
plt.xlabel('[Fe/H]')
plt.ylabel('[O/Fe]')
# plt.xlim(-5, 1)
# plt.ylim(-1, 3.5)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_OFe-FeH_{}.pdf'.format(imf), dpi=250)
#
global SNIa_number_per_century, SNII_number_per_century
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(11, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.loglog(time_axis, SNIa_number_per_century, label='SNIa', color="tab:orange",
ls='dotted') # Number per century
plt.loglog(time_axis, SNII_number_per_century, label='SNII', color="tab:orange") # Number per century
# plt.loglog(time_axis, SN_number_per_century, ls="dotted", label='total')
plt.xlabel(r'time [yr]')
plt.ylabel(r'# of SN per century')
plt.title('Supernova rate evolution')
# plt.xlim(10 ** 7, 14 * 10 ** 9)
# plt.ylim(1e-2, 1e6)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_SN_number.pdf'.format(imf), dpi=250)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/SN_number_evolution.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(time_axis[i]))
(i) = (i + 1)
file.write("\n# SNIa_number_per_century\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SNIa_number_per_century[i]))
(i) = (i + 1)
file.write("\n# SNII_number_per_century\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SNII_number_per_century[i]))
(i) = (i + 1)
file.write("\n# SN_number_per_century\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SN_number_per_century[i]))
(i) = (i + 1)
file.write("\n")
file.close()
# calculate the gravitational binding energy:
global expansion_factor_list, original_gas_mass
# consider the following to calculate the energy:
# galaxy_mass_without_gas_at_this_time,
# original_gas_mass,
# total_gas_mass_at_this_time,
# ejected_gas_mass_at_this_time,
# gas_mass = max(ejected_gas_mass_at_this_time, 1)
# galaxy mass--radii relation adopted from Dabringhausen 2008 eq.4
Dabringhausen_2008_a = 2.95
Dabringhausen_2008_b = 0.596
final_expansion_factor = expansion_factor_list[-1]
binding_energy_list = []
SN_energy_per_current_crossing_time_list = []
SN_energy_per_final_crossing_time_list = []
length_expansion_factor_list = len(expansion_factor_list)
global remnant_mass_list, stellar_mass_list
gravitational_constant = 6.674
finial_galaxy_inner_mass = remnant_mass_list[-1] + stellar_mass_list[-1]
final_galaxy_radii = 3 * (finial_galaxy_inner_mass / 10 ** 6) ** 0.6 # in parsec
final_crossing_time = 1 / (gravitational_constant * 10 ** (-11) * finial_galaxy_inner_mass * 2 * 10 ** 30 / (
final_galaxy_radii * 3 * 10 ** 16) ** 3) ** (0.5) / (60 * 60 * 24 * 365 * 10 ** 6) # in Myr
i = 0
while i < length_expansion_factor_list:
### binding energy ###
current_shrink_factor = final_expansion_factor / expansion_factor_list[i]
log_binding_energy = round(
math.log(3 / 5 * gravitational_constant * 1.989 ** 2 / 3.086, 10) + 40 + (2 - Dabringhausen_2008_b) *
math.log(original_gas_mass, 10) - math.log(Dabringhausen_2008_a, 10) +
6 * Dabringhausen_2008_b + math.log(current_shrink_factor, 10), 3)
# 40 = 30 (solar mass) * 2 - 11 (Gravitational constant) - 16 (pc to meter) + 7 (J to erg)
binding_energy = 10 ** log_binding_energy # [erg]
binding_energy_list.append(binding_energy)
### crossing time ###
current_galaxy_inner_mass = remnant_mass_list[i] + stellar_mass_list[i]
current_galaxy_radii = final_galaxy_radii / current_shrink_factor
crossing_time = 1 / (gravitational_constant * 10 ** (-11) * current_galaxy_inner_mass * 2 * 10 ** 30 / (
current_galaxy_radii * 3 * 10 ** 16) ** 3) ** (0.5) / (60 * 60 * 24 * 365 * 10 ** 6) # in Myr
SN_energy_per_current_crossing_time = SN_number_per_century[i] * crossing_time * 10 ** 4 * 10 ** 51
SN_energy_per_final_crossing_time = SN_number_per_century[i] * final_crossing_time * 10 ** 4 * 10 ** 51
SN_energy_per_current_crossing_time_list.append(SN_energy_per_current_crossing_time)
SN_energy_per_final_crossing_time_list.append(SN_energy_per_final_crossing_time)
(i) = (i + 1)
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(12, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.loglog(time_axis, SN_energy_per_current_crossing_time_list, label='in a instant crossing time')
plt.loglog(time_axis, SN_energy_per_final_crossing_time_list, label='in a final crossing time')
plt.loglog(time_axis, SNIa_energy_release_list, label='tot SNIa')
plt.loglog(time_axis, SNII_energy_release_list, label='tot SNII')
plt.loglog(time_axis, total_energy_release_list, ls="dotted", label='tot SNIa+II')
plt.loglog(time_axis, binding_energy_list, label='binding')
plt.loglog(time_axis, total_gas_kinetic_energy_list, label='gas kinetic')
plt.xlabel(r'time [yr]')
plt.ylabel(r'Energy')
plt.title('Energy produced by supernovae (within a crossing time)')
# plt.xlim(6, 1.01 * log_time_axis[-1])
# plt.ylim(8.5, 11.6)
plt.legend()
plt.tight_layout()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/energy_evolution.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(time_axis[i]))
(i) = (i + 1)
file.write("\n# SNIa_energy_release_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SNIa_energy_release_list[i]))
(i) = (i + 1)
file.write("\n# SNII_energy_release_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SNII_energy_release_list[i]))
(i) = (i + 1)
file.write("\n# SN_energy_per_current_crossing_time_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SN_energy_per_current_crossing_time_list[i]))
(i) = (i + 1)
file.write("\n# SN_energy_per_final_crossing_time_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(SN_energy_per_final_crossing_time_list[i]))
(i) = (i + 1)
file.write("\n# total_energy_release_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(total_energy_release_list[i]))
(i) = (i + 1)
file.write("\n# binding_energy_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(binding_energy_list[i]))
(i) = (i + 1)
file.write("\n# total_gas_kinetic_energy_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(total_gas_kinetic_energy_list[i]))
(i) = (i + 1)
file.write("\n")
file.close()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/energy_mass.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# final SN_energy_release\n")
file.write("{}\n".format(total_energy_release_list[-1]))
file.write("# final binding_energy\n")
file.write("{}\n".format(binding_energy_list[-1]))
file.write("# final gas_kinetic_energy\n")
file.write("{}\n".format(total_gas_kinetic_energy_list[-1]))
file.close()
#
global gas_Z_over_X_list, stellar_Z_over_X_list, stellar_Z_over_X_list_luminosity_weighted
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(13, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
# time_axis[0] = 1
# time_axis_G = [0]*length_of_time_axis
# for i in range(length_of_time_axis):
# time_axis_G[i] = time_axis[i]/10**9
# gas_Z_over_X_list[i]=math.log(gas_Z_over_X_list[i], 10)
plt.plot(log_time_axis, gas_Z_over_X_list, label='gas')
plt.plot(log_time_axis, stellar_Z_over_X_list, label='stellar MW')
plt.plot(log_time_axis, stellar_Z_over_X_list_luminosity_weighted, label='stellar LW')
plt.plot([6, 11], [0, 0], color='red', ls='dashed', label='solar')
# The [Z/X]s where the applied portinari98 stellar yield table will be changed for Z=0.0127, 0.008, 0.004, 0.0004.
plt.plot([6, 11], [-1.173, -1.173], color='red', ls='dotted', lw=0.5)
plt.plot([6, 11], [-0.523, -0.523], color='red', ls='dotted', lw=0.5)
plt.plot([6, 11], [-0.272, -0.272], color='red', ls='dotted', lw=0.5)
plt.xlabel(r'log(time [Gyr])')
plt.ylabel('[Z/X]')
plt.title('Metallicity evolution')
# plt.ylim(-2, 1)
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
# plt.legend(scatterpoints=1, numpoints=1, loc=0, prop={'size': 7.5}, ncol=2)
# plt.xlim(6.4, 1.01*time_axis[-1])
# plt.ylim(-0.4, 0.2)
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('galaxy_evolution_fig_Z_{}.pdf'.format(imf), dpi=250)
for i in range(length_of_time_axis):
time_axis[i] = math.log(time_axis[i], 10)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Z_over_X_time.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# log_time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(log_time_axis[i]))
(i) = (i + 1)
file.write("\n# gas_Z_over_X_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(gas_Z_over_X_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Z_over_X_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(stellar_Z_over_X_list[i]))
(i) = (i + 1)
file.write("\n# stellar_Z_over_X_list_luminosity_weighted\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(stellar_Z_over_X_list_luminosity_weighted[i]))
(i) = (i + 1)
file.write("\n")
file.close()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/Z_over_X_mass.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# gas_Z_over_X\n")
file.write("{} ".format(gas_Z_over_X_list[-1]))
file.write("\n# stellar_Z_over_X_list\n")
file.write("{} ".format(stellar_Z_over_X_list[-1]))
file.write("\n# stellar_Z_over_X_list_luminosity_weighted\n")
file.write("{} ".format(stellar_Z_over_X_list_luminosity_weighted[-1]))
file.write("\n")
file.close()
#
global BH_mass_list, NS_mass_list, WD_mass_list, total_gas_mass_list, ejected_gas_mass_list
for i in range(length_of_time_axis):
if remnant_mass_list[i] < 10 ** (-10):
remnant_mass_list[i] = 10 ** (-10)
remnant_mass_list[i] = math.log(remnant_mass_list[i], 10)
if total_gas_mass_list[i] < 10 ** (-10):
total_gas_mass_list[i] = 10 ** (-10)
total_gas_mass_list[i] = math.log(total_gas_mass_list[i], 10)
if stellar_mass_list[i] < 10 ** (-10):
stellar_mass_list[i] = 10 ** (-10)
stellar_mass_list[i] = math.log(stellar_mass_list[i], 10)
ejected_gas_mass_list[i] = math.log(ejected_gas_mass_list[i], 10)
if WD_mass_list[i] < 10 ** (-10):
WD_mass_list[i] = 10 ** (-10)
WD_mass_list[i] = math.log(WD_mass_list[i], 10)
NS_mass_list[i] = math.log(NS_mass_list[i], 10)
BH_mass_list[i] = math.log(BH_mass_list[i], 10)
# time_axis[0] = time_axis[1]
if plot_show is True or plot_save is True:
fig = plt.figure(14, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(time_axis, total_gas_mass_list, lw=2, label='all gas')
plt.plot(time_axis, ejected_gas_mass_list, lw=2, label='ejected gas')
plt.plot(time_axis, stellar_mass_list, lw=2, label='alive stars')
plt.plot(time_axis, remnant_mass_list, lw=2, label='all remnants')
plt.plot(time_axis, BH_mass_list, lw=2, label='black holes')
plt.plot(time_axis, NS_mass_list, lw=2, label='neutron stars')
plt.plot(time_axis, WD_mass_list, lw=2, label='white dwarfs')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'log$_{10}$(Mass [M$_\odot$])')
plt.title('Mass evolution')
# if imf == 'igimf':
# plt.title('IGIMF')
# elif imf == 'Kroupa':
# plt.title('Kroupa IMF')
plt.legend()
# plt.xlim(6.4, 1.01 * time_axis[-1])
# plt.xlim(6.4, 10.1)
# plt.ylim(6.4, 10.6)
plt.tight_layout()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/mass_evolution.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(time_axis[i]))
(i) = (i + 1)
file.write("\n# total_gas_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(total_gas_mass_list[i]))
(i) = (i + 1)
file.write("\n# ejected_gas_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(ejected_gas_mass_list[i]))
(i) = (i + 1)
file.write("\n# stellar_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(stellar_mass_list[i]))
(i) = (i + 1)
file.write("\n# remnant_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(remnant_mass_list[i]))
(i) = (i + 1)
file.write("\n# BH_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(BH_mass_list[i]))
(i) = (i + 1)
file.write("\n# NS_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(NS_mass_list[i]))
(i) = (i + 1)
file.write("\n# WD_mass_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(WD_mass_list[i]))
(i) = (i + 1)
file.write("\n")
file.close()
final_alive_stellar_mass = stellar_mass_list[-1]
final_remnant_stellar_mass = remnant_mass_list[-1]
final_alive_and_remnant_stellar_mass = math.log((10 ** final_alive_stellar_mass + 10 ** final_remnant_stellar_mass),
10)
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/mass_ratio.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# final alive stellar mass in log\n")
file.write("{}\n".format(final_alive_stellar_mass))
file.write("# final alive + remnant mass in log\n")
file.write("{}\n".format(final_alive_and_remnant_stellar_mass))
file.write("# (alive + remnant) / alive IN LOG\n")
file.write("{}\n".format(final_alive_and_remnant_stellar_mass - final_alive_stellar_mass))
file.close()
global total_star_formed
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/SN_number_mass.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# final SNIa_number per stellar mass formed\n")
file.write("{}\n".format(SNIa_number_list[-1] / total_star_formed))
# print("total SNIa number per solar mass of star formed:", SNIa_number_list[-1]/total_star_formed)
file.write("# final SNII_number per stellar mass formed\n")
file.write("{}\n".format(SNII_number_list[-1] / total_star_formed))
file.close()
global expansion_factor_instantaneous_list, expansion_factor_adiabat_list
if plot_show is True or plot_save is True:
fig = plt.figure(15, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(time_axis, expansion_factor_instantaneous_list, label='instantaneous')
plt.plot(time_axis, expansion_factor_adiabat_list, label='slow')
plt.plot(time_axis, expansion_factor_list, label='average')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'expansion_factor')
plt.legend()
plt.title('Galaxy size evolution')
# plt.xlim(6.4, 1.01 * time_axis[-1])
# plt.ylim(7.3, 12.2)
# plt.ylim(6, 12)
plt.tight_layout()
file = open('simulation_results_from_galaxy_evol/imf{}STF{}log_SFR{}SFEN{}Z_0{}/plots/expansion_factor.txt'.format(imf, STF, SFR, SFEN, log_Z_0), 'w')
file.write("# time_axis\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(time_axis[i]))
(i) = (i + 1)
file.write("\n# expansion_factor_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(expansion_factor_list[i]))
(i) = (i + 1)
file.write("\n# expansion_factor_instantaneous_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(expansion_factor_instantaneous_list[i]))
(i) = (i + 1)
file.write("\n# expansion_factor_adiabatic_list\n")
i = 0
while i < length_of_time_axis:
file.write("{} ".format(expansion_factor_adiabat_list[i]))
(i) = (i + 1)
file.write("\n")
file.close()
global ejected_gas_Mg_over_Fe_list, instant_ejected_gas_Mg_over_Fe_list
if plot_show is True or plot_save is True:
fig = plt.figure(16, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(time_axis, ejected_gas_Mg_over_Fe_list, label='total')
plt.plot(time_axis, instant_ejected_gas_Mg_over_Fe_list, label='instant')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'[Mg/Fe]')
# plt.xlim(6.4, 1.01 * time_axis[-1])
# plt.ylim(7.3, 12.2)
# plt.ylim(6, 12)
plt.legend()
plt.title('[Mg/Fe] of the ejected gas at different time')
plt.tight_layout()
global ejected_metal_mass_list
if plot_show is True or plot_save is True:
fig = plt.figure(17, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(time_axis, ejected_metal_mass_list, label='total')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected metal mass')
# plt.xlim(6.4, 1.01 * time_axis[-1])
# plt.ylim(7.3, 12.2)
# plt.ylim(6, 12)
plt.title('IMF averaged yield at different time')
plt.legend()
plt.tight_layout()
#
global ejected_O_mass_till_this_time_tot_list, ejected_O_mass_till_this_time_SNIa_list, ejected_O_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(21, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_O_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_O_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_O_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected O [M$_\odot$]')
plt.title('IMF averaged yield')
plt.legend()
plt.tight_layout()
global ejected_Mg_mass_till_this_time_tot_list, ejected_Mg_mass_till_this_time_SNIa_list, ejected_Mg_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(22, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_Mg_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_Mg_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_Mg_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected Mg [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
global ejected_Fe_mass_till_this_time_tot_list, ejected_Fe_mass_till_this_time_SNIa_list, ejected_Fe_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(23, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_Fe_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_Fe_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_Fe_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected Fe [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('Fe_production.pdf', dpi=250)
global ejected_Ca_mass_till_this_time_tot_list, ejected_Ca_mass_till_this_time_SNIa_list, ejected_Ca_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(24, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_Ca_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_Ca_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_Ca_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected Ca [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('Ca_production.pdf', dpi=250)
global ejected_S_mass_till_this_time_tot_list, ejected_S_mass_till_this_time_SNIa_list, ejected_S_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(25, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_S_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_S_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_S_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected S [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('S_production.pdf', dpi=250)
global ejected_Si_mass_till_this_time_tot_list, ejected_Si_mass_till_this_time_SNIa_list, ejected_Si_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(26, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_Si_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_Si_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_Si_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected Si [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('Si_production.pdf', dpi=250)
global ejected_Ne_mass_till_this_time_tot_list, ejected_Ne_mass_till_this_time_SNIa_list, ejected_Ne_mass_till_this_time_SNII_list
if plot_show is True or plot_save is True:
plt.rc('font', family='serif')
plt.rc('xtick', labelsize='x-small')
plt.rc('ytick', labelsize='x-small')
fig = plt.figure(27, figsize=(6, 5))
fig.add_subplot(1, 1, 1)
plt.plot(log_time_axis, ejected_Ne_mass_till_this_time_tot_list, label='tot')
plt.plot(log_time_axis, ejected_Ne_mass_till_this_time_SNIa_list, label='from SNIa')
plt.plot(log_time_axis, ejected_Ne_mass_till_this_time_SNII_list, label='from SNII')
plt.xlabel(r'log$_{10}$(time [yr])')
plt.ylabel(r'ejected Ne [M$_\odot$]')
plt.title('IMF averaged yield from different type of SN')
plt.legend()
plt.tight_layout()
if plot_save is True:
plt.savefig('Ne_production.pdf', dpi=250)
if plot_show is True:
plt.show()
return
def generate_SFH(distribution, Log_SFR, SFEN, sfr_tail, skewness, location):
if distribution == "skewnorm":
generate_sfh_skewnorm(Log_SFR, SFEN, sfr_tail, skewness, location)
elif distribution == "flat":
generate_sfh_flat(Log_SFR, SFEN)
elif distribution == "flat_tail":
generate_sfh_flat_tail(Log_SFR, SFEN)
elif distribution == "lognorm":
generate_sfh_lognorm(Log_SFR, SFEN)
else:
print('Warning: input unrecognized distribution name for galevo.generate_SFH')
return
def generate_sfh_flat(Log_SFR, SFEN):
# Flat distribution for star formation history
# took input: star formation rate, star formation event number
file = open('SFH.txt', 'w')
file.write("0\n")
j = 0
while j < SFEN:
file.write("{}\n".format(10 ** Log_SFR))
(j) = (j + 1)
j = 0
while j < 1301 - SFEN:
file.write("0\n")
(j) = (j + 1)
file.write("# The value in each line stand for the SFR [solar mass / yr]\n")
file.write("# in a star formation epoch (10 Myr)\n")
file.write("# start from time 0 for the first line.\n")
file.write("# Warning! Effective line number must be larger than 1.\n")
file.write("# Add a '0' in the next line if there is only one line.\n")
file.close()
return
def generate_sfh_flat_tail(Log_SFR, SFEN):
# Flat distribution for star formation history
# took input: star formation rate, star formation event number
file = open('SFH.txt', 'w')
file.write("0\n")
j = 0
while j < SFEN:
file.write("{}\n".format(10 ** Log_SFR))
(j) = (j + 1)
j = 0
while j < 1389 - SFEN:
file.write("0\n")
(j) = (j + 1)
j = 0
while j < 10:
file.write("{}\n".format(10 ** (Log_SFR-2)))
(j) = (j + 1)
file.write("# The value in each line stand for the SFR [solar mass / yr]\n")
file.write("# in a star formation epoch (10 Myr)\n")
file.write("# start from time 0 for the first line.\n")
file.write("# Warning! Effective line number must be larger than 1.\n")
file.write("# Add a '0' in the next line if there is only one line.\n")
file.close()
return
def generate_sfh_skewnorm(Log_SFR, SFEN, sfr_tail, skewness, location):
tot_sf_set = 10 ** Log_SFR * SFEN
tot_sf = 0
while tot_sf < tot_sf_set:
SFEN += 1
result_cal_tot_sf = cal_tot_sf(Log_SFR, SFEN, skewness, location)
(tot_sf) = (result_cal_tot_sf[0])
file = open('SFH.txt', 'w')
file.write("0\n")
sfr_for_this_epoch = 0
result_starburst_sf = 0
result_tail_sf = 0
j = 0
while j < SFEN:
sfr_for_this_epoch = result_cal_tot_sf[1] * result_cal_tot_sf[2][j]
file.write("{}\n".format(sfr_for_this_epoch))
if sfr_for_this_epoch > 10 ** Log_SFR / 2:
result_starburst_sf += sfr_for_this_epoch
else:
result_tail_sf += sfr_for_this_epoch
(j) = (j + 1)
sfr_for_the_tail_epoch = sfr_for_this_epoch / 2
if sfr_tail == 0:
j = 0
while j < 1301 - SFEN:
file.write("0\n")
(j) = (j + 1)
elif sfr_tail == 1:
j = 0
while j < 101:
file.write("{}\n".format(sfr_for_the_tail_epoch))
result_tail_sf += sfr_for_the_tail_epoch
(j) = (j + 1)
while j < 1301 - SFEN:
file.write("0\n")
(j) = (j + 1)
file.write("# The value in each line stand for the SFR [solar mass / yr]\n")
file.write("# in a star formation epoch (10 Myr)\n")
file.write("# start from time 0 for the first line.\n")
file.write("# Warning! Effective line number must be larger than 1.\n")
file.write("# Add a '0' in the next line if there is only one line.\n")
if sfr_tail == 1:
print("star formation tail (after the SFR is lower than half of the maximum value) contributes {}% "
"of the total star formation.".format(
round(result_tail_sf / (result_starburst_sf + result_tail_sf) * 100, 2)))
file.close()
return
def generate_sfh_lognorm(Log_SFR, SFEN):
tot_sf_set = 10 ** Log_SFR * SFEN
time_length_in_Gyr = 13
time_step_number = time_length_in_Gyr * 100
from scipy.stats import lognorm
s = 1
sc = SFEN / 2
time_list = np.linspace(0, time_step_number, time_step_number)
star_formation_rate = tot_sf_set * lognorm.pdf(time_list, s, scale=sc)
file = open('SFH.txt', 'w')
for i in range(time_step_number):
file.write("{}\n".format(star_formation_rate[i]))
file.write("# The value in each line stand for the SFR [solar mass / yr]\n")
file.write("# in a star formation epoch (10 Myr)\n")
file.write("# start from time 0 for the first line.\n")
file.write("# Warning! Effective line number must be larger than 1.\n")
file.write("# Add a '0' in the next line if there is only one line.\n")
file.close()
# plt.plot(time_list, star_formation_rate, label='lognorm SFH')
# plt.xlabel('time step')
# plt.ylabel(r'SFR [solar mass/year]')
# plt.show()
return
def cal_tot_sf(SFR, SFEN, skewness, location):
# Skew normal distribution for star formation history
# took input: maximum star formation rate, star formation event number
# from scipy.stats import f
from scipy.stats import skewnorm
x = np.linspace(skewnorm.ppf(0.01, skewness, location, 1), skewnorm.ppf(0.999999999, skewness, location, 1), SFEN)
y = skewnorm.pdf(x, skewness, location, 1)
# skewnorm.pdf(x, a, loc, scale) is the location and scale parameters,
# [identically equivalent to skewnorm.pdf(y, a) / scale with y = (x - loc) / scale]
# The scale is not used as the SFEN & SFR setup the scale through parameter tot_sf_set & mult.
mult = 10 ** SFR / max(y)
j = 0
tot_sf = 0
while j < SFEN:
sf = mult * y[j]
tot_sf += sf
(j) = (j + 1)
return tot_sf, mult, y
if __name__ == '__main__':
SFEN = "None"
### Generate a new SFH.txt file according to the following given parameters ###
# SFEN = 10 # the number of the 10 Myr star formation epoch (thus 10 stand for a star formation timescale of 100 Myr)
# Log_SFR = 2 # logarithmic characteristic star formation rate
# location = 0 # SFH shape parameter
# skewness = 10 # SFH shape parameter
# sfr_tail = 0 # SFH shape parameter
# generate_SFH("flat", Log_SFR, SFEN, sfr_tail, skewness, location)
# ## input "flat", "lognorm", or "skewnorm" to generate a boxy, lognormal, or skewnorm SFH, respectively.
####################################
# str_yield_table='WW95' or 'portinari98', specify the stellar evolution table
# imf='igimf' or 'Kroupa' or 'Salpeter'...(see line 460 above), specify galaxy IMF model.
# SFH_model='provided' or 'gas_mass_dependent' specify the star formation history.
# The 'provided' SFH is given in SFH.txt;
# The 'gas_mass_dependent' use SFH.txt to setup the initial condition
# then recalculate SFR at each timestep, resulting a SFH similar to SFH.txt but gas mass dependent.
# SNIa_yield_table='Thielemann1993' or 'Seitenzahl2013'
# solar_abu_table='Anders1989' or 'Asplund2009'
galaxy_evol(imf='igimf', STF=0.5, SFEN=SFEN, Z_0=0.00000001886, solar_mass_component="Anders1989_mass",
str_yield_table='portinari98', IMF_name='Kroupa', steller_mass_upper_bound=150,
time_resolution_in_Myr=1, mass_boundary_observe_low=1.5, mass_boundary_observe_up=8,
SFH_model='provided', SFE=0.013, SNIa_ON=True, SNIa_yield_table='Seitenzahl2013',
solar_abu_table='Anders1989',
high_time_resolution=None, plot_show=None, plot_save=None, outflow=None, check_igimf=True)
# Use plot_show=True on persenal computer to view the simualtion result immidiately after the computation
# Use plot_show=None if running on a computer cluster to avoid possible issues.
# In both cases, the simulation results are saved as txt files.
Computing file changes ...