Source code for redback.interaction_processes

# This is mostly from mosfit/transforms but rewritten to be modular

import numpy as np
from scipy.interpolate import interp1d
from redback.constants import *

[docs]class Diffusion(object):
[docs] def __init__(self, time, dense_times, luminosity, kappa, kappa_gamma, mej, vej, **kwargs): """ :param time: source frame time in days :param dense_times: dense time array in days :param dense_luminosity: luminosity :param kappa: opacity :param kappa_gamma: gamma-ray opacity :param mej: ejecta mass :param vej: ejecta velocity Adds new attributes for tau_diffusion and new luminosity accounting for the interaction process at the time values """ self.kappa = kappa self.kappa_gamma = kappa_gamma self.luminosity = luminosity self.time = time self.dense_times = dense_times self.m_ejecta = mej self.v_ejecta = vej self.reference = 'https://ui.adsabs.harvard.edu/abs/1982ApJ...253..785A/abstract' self.tau_d = [] self.new_luminosity = [] self.tau_d, self.new_luminosity = self.convert_input_luminosity()
def convert_input_luminosity(self): timesteps = 100 minimum_log_spacing = -3 diffusion_constant = 2.0 * solar_mass / (13.7 * speed_of_light * km_cgs) trapping_constant = 3.0 * solar_mass / (4*np.pi * km_cgs ** 2) tau_diff = np.sqrt(diffusion_constant * self.kappa * self.m_ejecta / self.v_ejecta) / day_to_s trap_coeff = (trapping_constant * self.kappa_gamma * self.m_ejecta / (self.v_ejecta ** 2)) / day_to_s ** 2 min_te = np.min(self.dense_times) tb = max(0.0, min_te) luminosity_interpolator = interp1d(self.dense_times, self.luminosity, copy=False, assume_sorted=True) uniq_times = np.unique(self.time[(self.time >= tb) & (self.time <= self.dense_times[-1])]) lu = len(uniq_times) num = int(round(timesteps / 2.0)) lsp = np.logspace(np.log10(tau_diff /self.dense_times[-1]) + minimum_log_spacing, 0, num) xm = np.unique(np.concatenate((lsp, 1 - lsp))) int_times = np.clip(tb + (uniq_times.reshape(lu, 1) - tb) * xm, tb, self.dense_times[-1]) int_te2s = int_times[:, -1] ** 2 int_lums = luminosity_interpolator(int_times) int_args = int_lums * int_times * np.exp((int_times ** 2 - int_te2s.reshape(lu, 1)) / tau_diff**2) int_args[np.isnan(int_args)] = 0. uniq_lums = np.trapz(int_args, int_times, axis=1) uniq_lums *= -2.0 * np.expm1(-trap_coeff / int_te2s) / tau_diff**2 new_lums = uniq_lums[np.searchsorted(uniq_times, self.time)] return tau_diff, new_lums
[docs]class AsphericalDiffusion(object):
[docs] def __init__(self, time, dense_times, luminosity, kappa, kappa_gamma, mej, vej, area_projection, area_reference, **kwargs): """ :param time: source frame time in days :param dense_times: dense time array in days :param luminosity: luminosity :param kappa: opacity :param kappa_gamma: gamma-ray opacity :param mej: ejecta mass :param vej: ejecta velocity :param area_projection: projected area of cocoon/polar ejecta :param area_reference: remaining reference area i.e., the equitorial ejecta Adds new attributes for tau_diffusion and new luminosity accounting for the interaction process """ self.kappa = kappa self.kappa_gamma = kappa_gamma self.luminosity = luminosity self.time = time self.dense_times = dense_times self.m_ejecta = mej self.v_ejecta = vej self.area_projection = area_projection self.area_reference = area_reference self.reference = 'https://ui.adsabs.harvard.edu/abs/2020ApJ...897..150D/abstract' self.tau_d = [] self.new_luminosity = [] self.tau_d, self.new_luminosity = self.convert_input_luminosity()
def convert_input_luminosity(self): timesteps = 100 minimum_log_spacing = -3 diffusion_constant = 2.0 * solar_mass / (13.7 * speed_of_light * km_cgs) trapping_constant = 3.0 * solar_mass / (4*np.pi * km_cgs ** 2) tau_diff = np.sqrt(diffusion_constant * self.kappa * self.m_ejecta / self.v_ejecta) / day_to_s trap_coeff = (trapping_constant * self.kappa_gamma * self.m_ejecta / (self.v_ejecta ** 2)) / day_to_s ** 2 min_te = min(self.dense_times) tb = max(0.0, min_te) luminosity_interpolator = interp1d(self.dense_times, self.luminosity, copy=False,assume_sorted=True) uniq_times = np.unique(self.time[(self.time >= tb) & (self.time <= self.dense_times[-1])]) lu = len(uniq_times) num = int(round(timesteps / 2.0)) lsp = np.logspace(np.log10(tau_diff /self.dense_times[-1]) + minimum_log_spacing, 0, num) xm = np.unique(np.concatenate((lsp, 1 - lsp))) int_times = np.clip(tb + (uniq_times.reshape(lu, 1) - tb) * xm, tb, self.dense_times[-1]) int_te2s = int_times[:, -1] ** 2 int_lums = luminosity_interpolator(int_times) int_args = int_lums * int_times * np.exp((int_times ** 2 - int_te2s.reshape(lu, 1)) / tau_diff**2) int_args[np.isnan(int_args)] = 0.0 uniq_lums = np.trapz(int_args, int_times, axis=1) uniq_lums *= -2.0 * np.expm1(-trap_coeff / int_te2s) / tau_diff**2 uniq_lums *= (1 + 1.4 * (2 + uniq_times/tau_diff/0.59) / (1 + np.exp(uniq_times/tau_diff/0.59)) * (self.area_projection/self.area_reference - 1)) new_lums = uniq_lums[np.searchsorted(uniq_times, self.time)] return tau_diff, new_lums
[docs]class CSMDiffusion(object):
[docs] def __init__(self, time, dense_times, luminosity, kappa, r_photosphere, mass_csm_threshold, csm_mass, **kwargs): """ :param time: source frame time in days :param dense_times: dense time array in days :param luminosity: luminosity :param kappa: opacity :param csm_mass: csm mass in solar masses :param mej: ejecta mass in solar masses :param r0: radius of csm shell in AU :param eta: csm density profile exponent :param rho: csm density profile amplitude Adds new attribute for luminosity accounting for the interaction process """ self.time = time self.dense_times = dense_times self.luminosity = luminosity self.kappa = kappa self.r_photosphere = r_photosphere self.mass_csm_threshold = mass_csm_threshold self.csm_mass = csm_mass * solar_mass self.reference = 'https://ui.adsabs.harvard.edu/abs/2013ApJ...773...76C/abstract' self.new_luminosity = [] self.new_luminosity = self.convert_input_luminosity()
def convert_input_luminosity(self): timesteps = 3000 minimum_log_spacing = -3 # Derived parameters # photosphere radius r_photosphere = self.r_photosphere # mass of the optically thick CSM (tau > 2/3). mass_csm_threshold = self.mass_csm_threshold beta = 4. * np.pi ** 3. / 9. t0 = self.kappa * (mass_csm_threshold) / (beta * speed_of_light * r_photosphere) / day_to_s min_te = min(self.dense_times) tb = max(0.0, min_te) luminosity_interpolator = interp1d(self.dense_times, self.luminosity, copy=False,assume_sorted=True) uniq_times = np.unique(self.time[(self.time >= tb) & (self.time <= self.dense_times[-1])]) lu = len(uniq_times) num = int(round(timesteps / 2.0)) lsp = np.logspace(np.log10(t0 /self.dense_times[-1]) + minimum_log_spacing, 0, num) xm = np.unique(np.concatenate((lsp, 1 - lsp))) int_times = tb + (uniq_times.reshape(lu, 1) - tb) * xm int_tes = int_times[:, -1] int_lums = luminosity_interpolator(int_times) int_args = int_lums * np.exp((int_times) / t0) int_args[np.isnan(int_args)] = 0.0 uniq_lums = np.trapz(int_args, int_times, axis=1) uniq_lums *= np.exp(-int_tes/t0)/t0 new_lums = uniq_lums[np.searchsorted(uniq_times, self.time)] return new_lums
[docs]class Viscous(object):
[docs] def __init__(self, time, dense_times, luminosity, t_viscous, **kwargs): """ :param time: source frame time in days :param dense_times: dense time array in days :param luminosity: luminosity :param t_viscous: viscous timescale Adds new attribute for luminosity accounting for the interaction process """ self.luminosity = luminosity self.time = time self.dense_times = dense_times self.tvisc = t_viscous self.reference = '' self.new_luminosity = [] self.new_luminosity = self.convert_input_luminosity()
def convert_input_luminosity(self): timesteps = 1000 minimum_log_spacing = -3 min_te = min(self.dense_times) tb = max(0.0, min_te) luminosity_interpolator = interp1d(self.dense_times, self.luminosity, copy=False,assume_sorted=True) uniq_times = np.unique(self.time[(self.time >= tb) & (self.time <= self.dense_times[-1])]) lu = len(uniq_times) num = int(round(timesteps / 2.0)) lsp = np.logspace(np.log10(self.tvisc /self.dense_times[-1]) +minimum_log_spacing, 0, num) xm = np.unique(np.concatenate((lsp, 1 - lsp))) int_times = np.clip(tb + (uniq_times.reshape(lu, 1) - tb) * xm, tb, self.dense_times[-1]) int_tes = int_times[:, -1] int_lums = luminosity_interpolator(int_times) int_args = int_lums * np.exp((int_times - int_tes.reshape(lu, 1)) / self.tvisc) int_args[np.isnan(int_args)] = 0.0 uniq_lums = np.trapz(int_args, int_times, axis=1)/self.tvisc new_lums = uniq_lums[np.searchsorted(uniq_times, self.time)] return new_lums