def line_emission(r_packet, emission_line_id, time_explosion, numba_plasma): """ Sets the frequency of the RPacket properly given the emission channel Parameters ---------- r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket emission_line_id : int time_explosion : float numba_plasma : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaPlasma """ r_packet.last_line_interaction_out_id = emission_line_id if emission_line_id != r_packet.next_line_id: pass inverse_doppler_factor = get_inverse_doppler_factor( r_packet.r, r_packet.mu, time_explosion) r_packet.nu = (numba_plasma.line_list_nu[emission_line_id] * inverse_doppler_factor) r_packet.next_line_id = emission_line_id + 1 nu_line = numba_plasma.line_list_nu[emission_line_id] if montecarlo_configuration.full_relativity: r_packet.mu = angle_aberration_CMF_to_LF(r_packet, time_explosion, r_packet.mu)
def thomson_scatter(r_packet, time_explosion): """ Thomson scattering — no longer line scattering \n1) get the doppler factor at that position with the old angle \n2) convert the current energy and nu into the comoving frame with the old mu \n3) Scatter and draw new mu - update mu \n4) Transform the comoving energy and nu back using the new mu Parameters ---------- r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket time_explosion : float time since explosion in seconds """ old_doppler_factor = get_doppler_factor(r_packet.r, r_packet.mu, time_explosion) comov_nu = r_packet.nu * old_doppler_factor comov_energy = r_packet.energy * old_doppler_factor r_packet.mu = get_random_mu() inverse_new_doppler_factor = get_inverse_doppler_factor( r_packet.r, r_packet.mu, time_explosion) r_packet.nu = comov_nu * inverse_new_doppler_factor r_packet.energy = comov_energy * inverse_new_doppler_factor if montecarlo_configuration.full_relativity: r_packet.mu = angle_aberration_CMF_to_LF(r_packet, time_explosion, r_packet.mu) temp_doppler_factor = get_doppler_factor(r_packet.r, r_packet.mu, time_explosion)
def test_angle_transformation_invariance(mu, r, inv_t_exp): packet = r_packet.RPacket(r, mu, 0.4, 0.9) mc.full_relativity = True mu1 = angle_aberration_CMF_to_LF(packet, 1 / inv_t_exp, mu) mu_obtained = angle_aberration_LF_to_CMF(packet, 1 / inv_t_exp, mu1) mc.full_relativity = False assert_almost_equal(mu_obtained, mu)
def test_both_angle_aberrations_inverse(mu, r, time_explosion): """ The angle aberration functions should be the functional inverse of one another. """ nu = 0.4 energy = 0.9 packet = r_packet.RPacket(r, mu, nu, energy) packet.r = r obtained_mu = angle_aberration_CMF_to_LF(packet, time_explosion, mu) inverse_obtained_mu = angle_aberration_LF_to_CMF(packet, time_explosion, obtained_mu) assert_almost_equal(inverse_obtained_mu, mu)
def free_free_emission(r_packet, time_explosion, numba_plasma): """ Free-Free emission - set the frequency from electron-ion interaction Parameters ---------- r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket time_explosion : float numba_plasma : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaPlasma """ inverse_doppler_factor = get_inverse_doppler_factor( r_packet.r, r_packet.mu, time_explosion) comov_nu = sample_nu_free_free(numba_plasma, r_packet.current_shell_id) r_packet.nu = comov_nu * inverse_doppler_factor current_line_id = get_current_line_id(comov_nu, numba_plasma.line_list_nu) r_packet.next_line_id = current_line_id if montecarlo_configuration.full_relativity: r_packet.mu = angle_aberration_CMF_to_LF(r_packet, time_explosion, r_packet.mu)
def trace_vpacket_volley(r_packet, vpacket_collection, numba_model, numba_plasma): """ Shoot a volley of vpackets (the vpacket collection specifies how many) from the current position of the rpacket. Parameters ---------- r_packet : [type] [description] vpacket_collection : [type] [description] numba_model : [type] [description] numba_plasma : [type] [description] """ if (r_packet.nu < vpacket_collection.v_packet_spawn_start_frequency) or ( r_packet.nu > vpacket_collection.v_packet_spawn_end_frequency): return no_of_vpackets = vpacket_collection.number_of_vpackets if no_of_vpackets == 0: return ### TODO theoretical check for r_packet nu within vpackets bins - is done somewhere else I think if r_packet.r > numba_model.r_inner[0]: # not on inner_boundary r_inner_over_r = numba_model.r_inner[0] / r_packet.r mu_min = -math.sqrt(1 - r_inner_over_r * r_inner_over_r) v_packet_on_inner_boundary = False if montecarlo_configuration.full_relativity: mu_min = angle_aberration_LF_to_CMF(r_packet, numba_model.time_explosion, mu_min) else: v_packet_on_inner_boundary = True mu_min = 0.0 mu_bin = (1.0 - mu_min) / no_of_vpackets r_packet_doppler_factor = get_doppler_factor(r_packet.r, r_packet.mu, numba_model.time_explosion) for i in range(no_of_vpackets): v_packet_mu = mu_min + i * mu_bin + np.random.random() * mu_bin if v_packet_on_inner_boundary: # The weights are described in K&S 2014 weight = 2 * v_packet_mu / no_of_vpackets else: weight = (1 - mu_min) / (2 * no_of_vpackets) # C code: next line, angle_aberration_CMF_to_LF( & virt_packet, storage); if montecarlo_configuration.full_relativity: v_packet_mu = angle_aberration_CMF_to_LF( r_packet, numba_model.time_explosion, v_packet_mu) v_packet_doppler_factor = get_doppler_factor( r_packet.r, v_packet_mu, numba_model.time_explosion) # transform between r_packet mu and v_packet_mu doppler_factor_ratio = r_packet_doppler_factor / v_packet_doppler_factor v_packet_nu = r_packet.nu * doppler_factor_ratio v_packet_energy = r_packet.energy * weight * doppler_factor_ratio v_packet = VPacket( r_packet.r, v_packet_mu, v_packet_nu, v_packet_energy, r_packet.current_shell_id, r_packet.next_line_id, i, ) tau_vpacket = trace_vpacket(v_packet, numba_model, numba_plasma) v_packet.energy *= math.exp(-tau_vpacket) vpacket_collection.set_properties( v_packet.nu, v_packet.energy, r_packet.last_interaction_in_nu, r_packet.last_interaction_type, r_packet.last_line_interaction_in_id, r_packet.last_line_interaction_out_id, )