Ejemplo n.º 1
0
def trace_packet(r_packet, numba_model, numba_plasma, estimators):
    """
    Traces the RPacket through the ejecta and stops when an interaction happens (heart of the calculation)

    Parameters
    ----------
    r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket
    numba_model : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaModel
    numba_plasma : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaPlasma
    estimators : tardis.montecarlo.montecarlo_numba.numba_interface.Estimators

    Returns
    -------
    """

    r_inner = numba_model.r_inner[r_packet.current_shell_id]
    r_outer = numba_model.r_outer[r_packet.current_shell_id]

    (
        distance_boundary,
        delta_shell,
    ) = calculate_distance_boundary(r_packet.r, r_packet.mu, r_inner, r_outer)

    # defining start for line interaction
    start_line_id = r_packet.next_line_id

    # defining taus
    tau_event = -np.log(np.random.random())
    tau_trace_line_combined = 0.0

    # e scattering initialization

    cur_electron_density = numba_plasma.electron_density[
        r_packet.current_shell_id]
    distance_electron = calculate_distance_electron(cur_electron_density,
                                                    tau_event)

    # Calculating doppler factor
    doppler_factor = get_doppler_factor(r_packet.r, r_packet.mu,
                                        numba_model.time_explosion)
    comov_nu = r_packet.nu * doppler_factor

    cur_line_id = start_line_id  # initializing varibale for Numba
    # - do not remove
    last_line_id = len(numba_plasma.line_list_nu) - 1

    for cur_line_id in range(start_line_id, len(numba_plasma.line_list_nu)):

        # Going through the lines
        nu_line = numba_plasma.line_list_nu[cur_line_id]
        nu_line_last_interaction = numba_plasma.line_list_nu[cur_line_id - 1]

        # Getting the tau for the next line
        tau_trace_line = numba_plasma.tau_sobolev[cur_line_id,
                                                  r_packet.current_shell_id]

        # Adding it to the tau_trace_line_combined
        tau_trace_line_combined += tau_trace_line

        # Calculating the distance until the current photons co-moving nu
        # redshifts to the line frequency
        is_last_line = cur_line_id == last_line_id

        distance_trace = calculate_distance_line(
            r_packet,
            comov_nu,
            is_last_line,
            nu_line,
            numba_model.time_explosion,
        )

        # calculating the tau electron of how far the trace has progressed
        tau_trace_electron = calculate_tau_electron(cur_electron_density,
                                                    distance_trace)

        # calculating the trace
        tau_trace_combined = tau_trace_line_combined + tau_trace_electron

        if ((distance_boundary <= distance_trace) and
            (distance_boundary <= distance_electron)
            ) and distance_trace != 0.0:
            interaction_type = InteractionType.BOUNDARY  # BOUNDARY
            r_packet.next_line_id = cur_line_id
            distance = distance_boundary
            break

        if ((distance_electron < distance_trace) and
            (distance_electron < distance_boundary)) and distance_trace != 0.0:
            interaction_type = InteractionType.ESCATTERING
            # print('scattering')
            distance = distance_electron
            r_packet.next_line_id = cur_line_id
            break

        # Updating the J_b_lu and E_dot_lu
        # This means we are still looking for line interaction and have not
        # been kicked out of the path by boundary or electron interaction

        update_line_estimators(
            estimators,
            r_packet,
            cur_line_id,
            distance_trace,
            numba_model.time_explosion,
        )

        if (tau_trace_combined > tau_event
                and not montecarlo_configuration.disable_line_scattering):
            interaction_type = InteractionType.LINE  # Line
            r_packet.last_interaction_in_nu = r_packet.nu
            r_packet.last_line_interaction_in_id = cur_line_id
            r_packet.next_line_id = cur_line_id
            distance = distance_trace
            break

        if not is_last_line:
            test_for_close_line(r_packet, cur_line_id + 1, nu_line,
                                numba_plasma)

        # Recalculating distance_electron using tau_event -
        # tau_trace_line_combined
        distance_electron = calculate_distance_electron(
            cur_electron_density, tau_event - tau_trace_line_combined)

    else:  # Executed when no break occurs in the for loop
        # We are beyond the line list now and the only next thing is to see
        # if we are interacting with the boundary or electron scattering
        if cur_line_id == (len(numba_plasma.line_list_nu) - 1):
            # Treatment for last line
            cur_line_id += 1
        if distance_electron < distance_boundary:
            distance = distance_electron
            interaction_type = InteractionType.ESCATTERING
            # print('scattering')
        else:
            distance = distance_boundary
            interaction_type = InteractionType.BOUNDARY

    # r_packet.next_line_id = cur_line_id

    return distance, interaction_type, delta_shell
Ejemplo n.º 2
0
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,
            v_packet_mu,
            r_packet.r,
            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,
        )
Ejemplo n.º 3
0
def single_packet_loop(
    r_packet,
    numba_model,
    numba_plasma,
    estimators,
    vpacket_collection,
    rpacket_tracker,
):
    """
    Parameters
    ----------
    r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket
    numba_model : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaModel
    numba_plasma : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaPlasma
    estimators : tardis.montecarlo.montecarlo_numba.numba_interface.Estimators
    vpacket_collection : tardis.montecarlo.montecarlo_numba.numba_interface.VPacketCollection
    rpacket_collection : tardis.montecarlo.montecarlo_numba.numba_interface.RPacketCollection

    Returns
    -------
    None
        This function does not return anything but changes the r_packet object
        and if virtual packets are requested - also updates the vpacket_collection
    """
    line_interaction_type = montecarlo_configuration.line_interaction_type

    if montecarlo_configuration.full_relativity:
        set_packet_props_full_relativity(r_packet, numba_model)
    else:
        set_packet_props_partial_relativity(r_packet, numba_model)
    r_packet.initialize_line_id(numba_plasma, numba_model)

    trace_vpacket_volley(
        r_packet, vpacket_collection, numba_model, numba_plasma
    )

    if montecarlo_configuration.RPACKET_TRACKING:
        rpacket_tracker.track(r_packet)

    # this part of the code is temporary and will be better incorporated
    while r_packet.status == PacketStatus.IN_PROCESS:
        # Compute continuum quantities
        # trace packet (takes opacities)
        doppler_factor = get_doppler_factor(
            r_packet.r, r_packet.mu, numba_model.time_explosion
        )
        comov_nu = r_packet.nu * doppler_factor
        chi_e = chi_electron_calculator(
            numba_plasma, comov_nu, r_packet.current_shell_id
        )
        if montecarlo_configuration.CONTINUUM_PROCESSES_ENABLED:
            (
                chi_bf_tot,
                chi_bf_contributions,
                current_continua,
                x_sect_bfs,
                chi_ff,
            ) = chi_continuum_calculator(
                numba_plasma, comov_nu, r_packet.current_shell_id
            )
            chi_continuum = chi_e + chi_bf_tot + chi_ff
            escat_prob = chi_e / chi_continuum  # probability of e-scatter
            distance, interaction_type, delta_shell = trace_packet_continuum(
                r_packet,
                numba_model,
                numba_plasma,
                estimators,
                chi_continuum,
                escat_prob,
            )
            update_bound_free_estimators(
                comov_nu,
                r_packet.energy * doppler_factor,
                r_packet.current_shell_id,
                distance,
                estimators,
                numba_plasma.t_electrons[r_packet.current_shell_id],
                x_sect_bfs,
                current_continua,
                numba_plasma.bf_threshold_list_nu,
            )
        else:
            escat_prob = 1.0
            chi_continuum = chi_e
            distance, interaction_type, delta_shell = trace_packet_continuum(
                r_packet,
                numba_model,
                numba_plasma,
                estimators,
                chi_continuum,
                escat_prob,
            )

        # If continuum processes: update continuum estimators

        if interaction_type == InteractionType.BOUNDARY:
            move_r_packet(
                r_packet, distance, numba_model.time_explosion, estimators
            )
            move_packet_across_shell_boundary(
                r_packet, delta_shell, len(numba_model.r_inner)
            )

        elif interaction_type == InteractionType.LINE:
            r_packet.last_interaction_type = 2
            move_r_packet(
                r_packet, distance, numba_model.time_explosion, estimators
            )
            line_scatter(
                r_packet,
                numba_model.time_explosion,
                line_interaction_type,
                numba_plasma,
            )
            trace_vpacket_volley(
                r_packet, vpacket_collection, numba_model, numba_plasma
            )

        elif interaction_type == InteractionType.ESCATTERING:
            r_packet.last_interaction_type = 1

            move_r_packet(
                r_packet, distance, numba_model.time_explosion, estimators
            )
            thomson_scatter(r_packet, numba_model.time_explosion)

            trace_vpacket_volley(
                r_packet, vpacket_collection, numba_model, numba_plasma
            )
        elif (
            montecarlo_configuration.CONTINUUM_PROCESSES_ENABLED
            and interaction_type == InteractionType.CONTINUUM_PROCESS
        ):
            r_packet.last_interaction_type = InteractionType.CONTINUUM_PROCESS
            move_r_packet(
                r_packet, distance, numba_model.time_explosion, estimators
            )
            continuum_event(
                r_packet,
                numba_model.time_explosion,
                numba_plasma,
                chi_bf_tot,
                chi_ff,
                chi_bf_contributions,
                current_continua,
            )

            trace_vpacket_volley(
                r_packet, vpacket_collection, numba_model, numba_plasma
            )
        else:
            pass
        if montecarlo_configuration.RPACKET_TRACKING:
            rpacket_tracker.track(r_packet)
def trace_packet_continuum(r_packet, numba_model, numba_plasma, estimators,
                           chi_continuum, escat_prob):
    """
    Traces the RPacket through the ejecta and stops when an interaction happens (heart of the calculation)

    Parameters
    ----------
    r_packet : tardis.montecarlo.montecarlo_numba.r_packet.RPacket
    numba_model : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaModel
    numba_plasma : tardis.montecarlo.montecarlo_numba.numba_interface.NumbaPlasma
    estimators : tardis.montecarlo.montecarlo_numba.numba_interface.Estimators

    Returns
    -------
    """

    r_inner = numba_model.r_inner[r_packet.current_shell_id]
    r_outer = numba_model.r_outer[r_packet.current_shell_id]

    (
        distance_boundary,
        delta_shell,
    ) = calculate_distance_boundary(r_packet.r, r_packet.mu, r_inner, r_outer)

    # defining start for line interaction
    start_line_id = r_packet.next_line_id

    # defining taus
    tau_event = -np.log(np.random.random())
    tau_trace_line_combined = 0.0

    # Calculating doppler factor
    doppler_factor = get_doppler_factor(r_packet.r, r_packet.mu,
                                        numba_model.time_explosion)
    comov_nu = r_packet.nu * doppler_factor

    distance_continuum = tau_event / chi_continuum
    cur_line_id = start_line_id  # initializing varibale for Numba
    # - do not remove
    last_line_id = len(numba_plasma.line_list_nu) - 1
    for cur_line_id in range(start_line_id, len(numba_plasma.line_list_nu)):

        # Going through the lines
        nu_line = numba_plasma.line_list_nu[cur_line_id]

        # Getting the tau for the next line
        tau_trace_line = numba_plasma.tau_sobolev[cur_line_id,
                                                  r_packet.current_shell_id]

        # Adding it to the tau_trace_line_combined
        tau_trace_line_combined += tau_trace_line

        # Calculating the distance until the current photons co-moving nu
        # redshifts to the line frequency
        is_last_line = cur_line_id == last_line_id

        distance_trace = calculate_distance_line(
            r_packet,
            comov_nu,
            is_last_line,
            nu_line,
            numba_model.time_explosion,
        )

        # calculating the tau continuum of how far the trace has progressed
        tau_trace_continuum = chi_continuum * distance_trace

        # calculating the trace
        tau_trace_combined = tau_trace_line_combined + tau_trace_continuum

        distance = min(distance_trace, distance_boundary, distance_continuum)

        if distance_trace != 0:

            if distance == distance_boundary:
                interaction_type = InteractionType.BOUNDARY  # BOUNDARY
                r_packet.next_line_id = cur_line_id
                break
            elif distance == distance_continuum:
                if not montecarlo_configuration.CONTINUUM_PROCESSES_ENABLED:
                    interaction_type = InteractionType.ESCATTERING
                else:
                    zrand = np.random.random()
                    if zrand < escat_prob:
                        interaction_type = InteractionType.ESCATTERING
                    else:
                        interaction_type = InteractionType.CONTINUUM_PROCESS
                r_packet.next_line_id = cur_line_id
                break

        # Updating the J_b_lu and E_dot_lu
        # This means we are still looking for line interaction and have not
        # been kicked out of the path by boundary or electron interaction

        update_line_estimators(
            estimators,
            r_packet,
            cur_line_id,
            distance_trace,
            numba_model.time_explosion,
        )

        if (tau_trace_combined > tau_event
                and not montecarlo_configuration.disable_line_scattering):
            interaction_type = InteractionType.LINE  # Line
            r_packet.last_interaction_in_nu = r_packet.nu
            r_packet.last_line_interaction_in_id = cur_line_id
            r_packet.next_line_id = cur_line_id
            distance = distance_trace
            break

        # Recalculating distance_continuum using tau_event -
        # tau_trace_line_combined
        # I don't think this needs to be updated
        # since tau_event is already the result of the integral
        # from the initial line
        distance_continuum = (tau_event -
                              tau_trace_line_combined) / (chi_continuum)

    else:  # Executed when no break occurs in the for loop
        # We are beyond the line list now and the only next thing is to see
        # if we are interacting with the boundary or electron scattering
        if cur_line_id == (len(numba_plasma.line_list_nu) - 1):
            # Treatment for last line
            cur_line_id += 1
        if distance_continuum < distance_boundary:
            distance = distance_continuum
            if not montecarlo_configuration.CONTINUUM_PROCESSES_ENABLED:
                interaction_type = InteractionType.ESCATTERING
            else:
                zrand = np.random.random()
                if zrand < escat_prob:
                    interaction_type = InteractionType.ESCATTERING
                else:
                    interaction_type = InteractionType.CONTINUUM_PROCESS
        else:
            distance = distance_boundary
            interaction_type = InteractionType.BOUNDARY

    return distance, interaction_type, delta_shell