void move_packet (rpacket_t * packet, storage_model_t * storage, double distance) { double doppler_factor = rpacket_doppler_factor (packet, storage); if (distance > 0.0) { double r = rpacket_get_r (packet); double new_r = sqrt (r * r + distance * distance + 2.0 * r * distance * rpacket_get_mu (packet)); rpacket_set_mu (packet, (rpacket_get_mu (packet) * r + distance) / new_r); rpacket_set_r (packet, new_r); if (rpacket_get_virtual_packet (packet) <= 0) { double comov_energy = rpacket_get_energy (packet) * doppler_factor; double comov_nu = rpacket_get_nu (packet) * doppler_factor; #ifdef WITHOPENMP #pragma omp atomic #endif storage->js[rpacket_get_current_shell_id (packet)] += comov_energy * distance; #ifdef WITHOPENMP #pragma omp atomic #endif storage->nubars[rpacket_get_current_shell_id (packet)] += comov_energy * distance * comov_nu; } } }
void compute_distance2boundary (rpacket_t * packet, const storage_model_t * storage) { double r = rpacket_get_r (packet); double mu = rpacket_get_mu (packet); double r_outer = storage->r_outer[rpacket_get_current_shell_id (packet)]; double r_inner = storage->r_inner[rpacket_get_current_shell_id (packet)]; double check, distance; if (mu > 0.0) { // direction outward rpacket_set_next_shell_id (packet, 1); distance = sqrt (r_outer * r_outer + ((mu * mu - 1.0) * r * r)) - (r * mu); } else { // going inward if ( (check = r_inner * r_inner + (r * r * (mu * mu - 1.0)) )>= 0.0) { // hit inner boundary rpacket_set_next_shell_id (packet, -1); distance = - r * mu - sqrt (check); } else { // miss inner boundary rpacket_set_next_shell_id (packet, 1); distance = sqrt (r_outer * r_outer + ((mu * mu - 1.0) * r * r)) - (r * mu); } } rpacket_set_d_boundary (packet, distance); }
void compute_distance2continuum(rpacket_t * packet, storage_model_t * storage) { double chi_freefree, chi_electron, chi_continuum, d_continuum; if (storage->cont_status == CONTINUUM_ON) { calculate_chi_bf(packet, storage); double chi_boundfree = rpacket_get_chi_boundfree(packet); rpacket_set_chi_freefree(packet, 0.0); chi_freefree = rpacket_get_chi_freefree(packet); // MR ?? this is always zero chi_electron = storage->electron_densities[rpacket_get_current_shell_id(packet)] * storage->sigma_thomson * rpacket_doppler_factor (packet, storage); chi_continuum = chi_boundfree + chi_freefree + chi_electron; d_continuum = rpacket_get_tau_event(packet) / chi_continuum; } else { // FIXME MR: an assignment to chi_freefree seems to be missing here chi_electron = storage->electron_densities[rpacket_get_current_shell_id(packet)] * storage->sigma_thomson; chi_continuum = chi_electron; d_continuum = storage->inverse_electron_densities[rpacket_get_current_shell_id (packet)] * storage->inverse_sigma_thomson * rpacket_get_tau_event (packet); } if (rpacket_get_virtual_packet(packet) > 0) { //Set all continuum distances to MISS_DISTANCE in case of an virtual_packet rpacket_set_d_continuum(packet, MISS_DISTANCE); rpacket_set_chi_boundfree(packet, 0.0); rpacket_set_chi_electron(packet, chi_electron); rpacket_set_chi_freefree(packet, 0.0); rpacket_set_chi_continuum(packet, chi_continuum); } else { // fprintf(stderr, "--------\n"); // fprintf(stderr, "nu = %e \n", rpacket_get_nu(packet)); // fprintf(stderr, "chi_electron = %e\n", chi_electron); // fprintf(stderr, "chi_boundfree = %e\n", calculate_chi_bf(packet, storage)); // fprintf(stderr, "chi_line = %e \n", rpacket_get_tau_event(packet) / rpacket_get_d_line(packet)); // fprintf(stderr, "--------\n"); rpacket_set_chi_freefree(packet, chi_freefree); rpacket_set_chi_electron(packet, chi_electron); rpacket_set_chi_continuum(packet, chi_continuum); rpacket_set_d_continuum(packet, d_continuum); } }
void move_packet_across_shell_boundary (rpacket_t * packet, storage_model_t * storage, double distance, rk_state *mt_state) { move_packet (packet, storage, distance); if (rpacket_get_virtual_packet (packet) > 0) { double delta_tau_event = rpacket_get_chi_continuum(packet) * distance; rpacket_set_tau_event (packet, rpacket_get_tau_event (packet) + delta_tau_event); } else { rpacket_reset_tau_event (packet, mt_state); } if ((rpacket_get_current_shell_id (packet) < storage->no_of_shells - 1 && rpacket_get_next_shell_id (packet) == 1) || (rpacket_get_current_shell_id (packet) > 0 && rpacket_get_next_shell_id (packet) == -1)) { rpacket_set_current_shell_id (packet, rpacket_get_current_shell_id (packet) + rpacket_get_next_shell_id (packet)); } else if (rpacket_get_next_shell_id (packet) == 1) { rpacket_set_status (packet, TARDIS_PACKET_STATUS_EMITTED); } else if ((storage->reflective_inner_boundary == 0) || (rk_double (mt_state) > storage->inner_boundary_albedo)) { rpacket_set_status (packet, TARDIS_PACKET_STATUS_REABSORBED); } else { double doppler_factor = rpacket_doppler_factor (packet, storage); double comov_nu = rpacket_get_nu (packet) * doppler_factor; double comov_energy = rpacket_get_energy (packet) * doppler_factor; rpacket_set_mu (packet, rk_double (mt_state)); double inverse_doppler_factor = 1.0 / rpacket_doppler_factor (packet, storage); rpacket_set_nu (packet, comov_nu * inverse_doppler_factor); rpacket_set_energy (packet, comov_energy * inverse_doppler_factor); if (rpacket_get_virtual_packet_flag (packet) > 0) { montecarlo_one_packet (storage, packet, -2, mt_state); } } }
void calculate_chi_bf(rpacket_t * packet, storage_model_t * storage) { double doppler_factor = rpacket_doppler_factor (packet, storage); double comov_nu = rpacket_get_nu (packet) * doppler_factor; int64_t no_of_continuum_edges = storage->no_of_edges; int64_t current_continuum_id; line_search(storage->continuum_list_nu, comov_nu, no_of_continuum_edges, ¤t_continuum_id); rpacket_set_current_continuum_id(packet, current_continuum_id); int64_t shell_id = rpacket_get_current_shell_id(packet); double T = storage->t_electrons[shell_id]; double boltzmann_factor = exp(-(H * comov_nu) / (KB*T)); double bf_helper = 0; for(int64_t i = current_continuum_id; i < no_of_continuum_edges; i++) { // get the levelpopulation for the level ijk in the current shell: double l_pop = storage->l_pop[shell_id * no_of_continuum_edges + i]; // get the levelpopulation ratio \frac{n_{0,j+1,k}}{n_{i,j,k}} \frac{n_{i,j,k}}{n_{0,j+1,k}}^{*}: double l_pop_r = storage->l_pop_r[shell_id * no_of_continuum_edges + i]; bf_helper += l_pop * bf_cross_section(storage, i, comov_nu) * (1 - l_pop_r * boltzmann_factor); // FIXME MR: Is this thread-safe? It doesn't look like it to me ... storage->chi_bf_tmp_partial[i] = bf_helper; } rpacket_set_chi_boundfree(packet, bf_helper * doppler_factor); }
void move_packet_across_shell_boundary(rpacket_t *packet, storage_model_t *storage, double distance) { double comov_energy, doppler_factor, comov_nu, inverse_doppler_factor; move_packet(packet, storage, distance); if (rpacket_get_virtual_packet(packet) > 0) { double delta_tau_event = distance * storage->electron_densities[rpacket_get_current_shell_id(packet)] * storage->sigma_thomson; rpacket_set_tau_event(packet, rpacket_get_tau_event(packet) + delta_tau_event); } else { rpacket_reset_tau_event(packet); } if ((rpacket_get_current_shell_id(packet) < storage->no_of_shells - 1 && rpacket_get_next_shell_id(packet) == 1) || (rpacket_get_current_shell_id(packet) > 0 && rpacket_get_next_shell_id(packet) == -1)) { rpacket_set_current_shell_id(packet, rpacket_get_current_shell_id(packet) + rpacket_get_next_shell_id(packet)); rpacket_set_recently_crossed_boundary(packet, rpacket_get_next_shell_id(packet)); } else if (rpacket_get_next_shell_id(packet) == 1) { rpacket_set_status(packet, TARDIS_PACKET_STATUS_EMITTED); } else if ((storage->reflective_inner_boundary == 0) || (rk_double(&mt_state) > storage->inner_boundary_albedo)) { rpacket_set_status(packet, TARDIS_PACKET_STATUS_REABSORBED); } else { doppler_factor = rpacket_doppler_factor(packet, storage); comov_nu = rpacket_get_nu(packet) * doppler_factor; comov_energy = rpacket_get_energy(packet) * doppler_factor; rpacket_set_mu(packet, rk_double(&mt_state)); inverse_doppler_factor = 1.0 / rpacket_doppler_factor(packet, storage); rpacket_set_nu(packet, comov_nu * inverse_doppler_factor); rpacket_set_energy(packet, comov_energy * inverse_doppler_factor); rpacket_set_recently_crossed_boundary(packet, 1); if (rpacket_get_virtual_packet_flag(packet) > 0) { montecarlo_one_packet(storage, packet, -2); } } }
inline double compute_distance2electron(rpacket_t *packet, storage_model_t *storage) { if (rpacket_get_virtual_packet(packet) > 0) { return MISS_DISTANCE; } double inverse_ne = storage->inverse_electron_densities[rpacket_get_current_shell_id(packet)] * storage->inverse_sigma_thomson; return rpacket_get_tau_event(packet) * inverse_ne; }
inline double move_packet(rpacket_t *packet, storage_model_t *storage, double distance) { double new_r, doppler_factor, comov_energy, comov_nu; doppler_factor = rpacket_doppler_factor(packet, storage); if (distance > 0.0) { double r = rpacket_get_r(packet); new_r = sqrt(r * r + distance * distance + 2.0 * r * distance * rpacket_get_mu(packet)); rpacket_set_mu(packet, (rpacket_get_mu(packet) * r + distance) / new_r); rpacket_set_r(packet, new_r); if (rpacket_get_virtual_packet(packet) <= 0) { comov_energy = rpacket_get_energy(packet) * doppler_factor; comov_nu = rpacket_get_nu(packet) * doppler_factor; storage->js[rpacket_get_current_shell_id(packet)] += comov_energy * distance; storage->nubars[rpacket_get_current_shell_id(packet)] += comov_energy * distance * comov_nu; } } return doppler_factor; }
inline double compute_distance2boundary(rpacket_t *packet, storage_model_t *storage) { double r = rpacket_get_r(packet); double mu = rpacket_get_mu(packet); double r_outer = storage->r_outer[rpacket_get_current_shell_id(packet)]; double r_inner = storage->r_inner[rpacket_get_current_shell_id(packet)]; double d_outer = sqrt(r_outer * r_outer + ((mu * mu - 1.0) * r * r)) - (r * mu); double d_inner; double result; if (rpacket_get_recently_crossed_boundary(packet) == 1) { rpacket_set_next_shell_id(packet, 1); return d_outer; } else { double check = r_inner * r_inner + (r * r * (mu * mu - 1.0)); if (check < 0.0) { rpacket_set_next_shell_id(packet, 1); return d_outer; } else { d_inner = mu < 0.0 ? -r * mu - sqrt(check) : MISS_DISTANCE; } } if (d_inner < d_outer) { rpacket_set_next_shell_id(packet, -1); return d_inner; } else { rpacket_set_next_shell_id(packet, 1); return d_outer; } }
inline int64_t macro_atom(rpacket_t *packet, storage_model_t *storage) { int emit, i = 0; double p, event_random; int activate_level = storage->line2macro_level_upper[rpacket_get_next_line_id(packet) - 1]; while (emit != -1) { event_random = rk_double(&mt_state); i = storage->macro_block_references[activate_level] - 1; p = 0.0; do { p += storage->transition_probabilities[rpacket_get_current_shell_id(packet) * storage->transition_probabilities_nd + (++i)]; } while (p <= event_random); emit = storage->transition_type[i]; activate_level = storage->destination_level_id[i]; } return storage->transition_line_id[i]; }
extern inline tardis_error_t compute_distance2line(rpacket_t *packet, storage_model_t *storage, double *result) { tardis_error_t ret_val = TARDIS_ERROR_OK; if (rpacket_get_last_line(packet)) { *result = MISS_DISTANCE; } else { double r = rpacket_get_r(packet); double mu = rpacket_get_mu(packet); double nu = rpacket_get_nu(packet); double nu_line = rpacket_get_nu_line(packet); double t_exp = storage->time_explosion; double inverse_t_exp = storage->inverse_time_explosion; double last_line = storage->line_list_nu[rpacket_get_next_line_id(packet) - 1]; double next_line = storage->line_list_nu[rpacket_get_next_line_id(packet) + 1]; int64_t cur_zone_id = rpacket_get_current_shell_id(packet); double comov_nu, doppler_factor; doppler_factor = 1.0 - mu * r * inverse_t_exp * INVERSE_C; comov_nu = nu * doppler_factor; if (comov_nu < nu_line) { fprintf(stderr, "ERROR: Comoving nu less than nu_line!\n"); fprintf(stderr, "comov_nu = %f\n", comov_nu); fprintf(stderr, "nu_line = %f\n", nu_line); fprintf(stderr, "(comov_nu - nu_line) / nu_line = %f\n", (comov_nu - nu_line) / nu_line); fprintf(stderr, "last_line = %f\n", last_line); fprintf(stderr, "next_line = %f\n", next_line); fprintf(stderr, "r = %f\n", r); fprintf(stderr, "mu = %f\n", mu); fprintf(stderr, "nu = %f\n", nu); fprintf(stderr, "doppler_factor = %f\n", doppler_factor); fprintf(stderr, "cur_zone_id = %d\n", cur_zone_id); ret_val = TARDIS_ERROR_COMOV_NU_LESS_THAN_NU_LINE; } else { *result = ((comov_nu - nu_line) / nu) * C * t_exp; } } return ret_val; }
int64_t macro_atom (const rpacket_t * packet, const storage_model_t * storage, rk_state *mt_state) { int emit = 0, i = 0, offset = -1; uint64_t activate_level = storage->line2macro_level_upper[rpacket_get_next_line_id (packet)]; while (emit != -1) { double event_random = rk_double (mt_state); i = storage->macro_block_references[activate_level] - 1; double p = 0.0; offset = storage->transition_probabilities_nd * rpacket_get_current_shell_id (packet); do { ++i; p += storage->transition_probabilities[offset + i]; } while (p <= event_random); emit = storage->transition_type[i]; activate_level = storage->destination_level_id[i]; } return storage->transition_line_id[i]; }
void montecarlo_line_scatter (rpacket_t * packet, storage_model_t * storage, double distance, rk_state *mt_state) { uint64_t next_line_id = rpacket_get_next_line_id (packet); uint64_t line2d_idx = next_line_id + storage->no_of_lines * rpacket_get_current_shell_id (packet); if (rpacket_get_virtual_packet (packet) == 0) { increment_j_blue_estimator (packet, storage, distance, line2d_idx); increment_Edotlu_estimator (packet, storage, line2d_idx); } double tau_line = storage->line_lists_tau_sobolevs[line2d_idx]; double tau_continuum = rpacket_get_chi_continuum(packet) * distance; double tau_combined = tau_line + tau_continuum; //rpacket_set_next_line_id (packet, rpacket_get_next_line_id (packet) + 1); if (next_line_id + 1 == storage->no_of_lines) { rpacket_set_last_line (packet, true); } if (rpacket_get_virtual_packet (packet) > 0) { rpacket_set_tau_event (packet, rpacket_get_tau_event (packet) + tau_line); rpacket_set_next_line_id (packet, next_line_id + 1); } else if (rpacket_get_tau_event (packet) < tau_combined) { move_packet (packet, storage, distance); double old_doppler_factor = rpacket_doppler_factor (packet, storage); rpacket_set_mu (packet, 2.0 * rk_double (mt_state) - 1.0); double inverse_doppler_factor = 1.0 / rpacket_doppler_factor (packet, storage); double comov_energy = rpacket_get_energy (packet) * old_doppler_factor; rpacket_set_energy (packet, comov_energy * inverse_doppler_factor); storage->last_interaction_in_nu[rpacket_get_id (packet)] = rpacket_get_nu (packet); storage->last_line_interaction_in_id[rpacket_get_id (packet)] = next_line_id; storage->last_line_interaction_shell_id[rpacket_get_id (packet)] = rpacket_get_current_shell_id (packet); storage->last_interaction_type[rpacket_get_id (packet)] = 2; int64_t emission_line_id = 0; if (storage->line_interaction_id == 0) { emission_line_id = next_line_id; } else if (storage->line_interaction_id >= 1) { emission_line_id = macro_atom (packet, storage, mt_state); } storage->last_line_interaction_out_id[rpacket_get_id (packet)] = emission_line_id; rpacket_set_nu (packet, storage->line_list_nu[emission_line_id] * inverse_doppler_factor); rpacket_set_nu_line (packet, storage->line_list_nu[emission_line_id]); rpacket_set_next_line_id (packet, emission_line_id + 1); rpacket_reset_tau_event (packet, mt_state); if (rpacket_get_virtual_packet_flag (packet) > 0) { bool virtual_close_line = false; if (!rpacket_get_last_line (packet) && fabs (storage->line_list_nu[rpacket_get_next_line_id (packet)] - rpacket_get_nu_line (packet)) < (rpacket_get_nu_line (packet)* 1e-7)) { virtual_close_line = true; } // QUESTIONABLE!!! bool old_close_line = rpacket_get_close_line (packet); rpacket_set_close_line (packet, virtual_close_line); montecarlo_one_packet (storage, packet, 1, mt_state); rpacket_set_close_line (packet, old_close_line); virtual_close_line = false; } } else { rpacket_set_tau_event (packet, rpacket_get_tau_event (packet) - tau_line); rpacket_set_next_line_id (packet, next_line_id + 1); } if (!rpacket_get_last_line (packet) && fabs (storage->line_list_nu[rpacket_get_next_line_id (packet)] - rpacket_get_nu_line (packet)) < (rpacket_get_nu_line (packet)* 1e-7)) { rpacket_set_close_line (packet, true); } }
tardis_error_t compute_distance2line (rpacket_t * packet, const storage_model_t * storage) { if (!rpacket_get_last_line (packet)) { double r = rpacket_get_r (packet); double mu = rpacket_get_mu (packet); double nu = rpacket_get_nu (packet); double nu_line = rpacket_get_nu_line (packet); double distance, nu_diff; double t_exp = storage->time_explosion; double inverse_t_exp = storage->inverse_time_explosion; int64_t cur_zone_id = rpacket_get_current_shell_id (packet); double doppler_factor = 1.0 - mu * r * inverse_t_exp * INVERSE_C; double comov_nu = nu * doppler_factor; if ( (nu_diff = comov_nu - nu_line) >= 0) { distance = (nu_diff / nu) * C * t_exp; rpacket_set_d_line (packet, distance); return TARDIS_ERROR_OK; } else { if (rpacket_get_next_line_id (packet) == storage->no_of_lines - 1) { fprintf (stderr, "last_line = %f\n", storage-> line_list_nu[rpacket_get_next_line_id (packet) - 1]); fprintf (stderr, "Last line in line list reached!"); } else if (rpacket_get_next_line_id (packet) == 0) { fprintf (stderr, "First line in line list!"); fprintf (stderr, "next_line = %f\n", storage-> line_list_nu[rpacket_get_next_line_id (packet) + 1]); } else { fprintf (stderr, "last_line = %f\n", storage-> line_list_nu[rpacket_get_next_line_id (packet) - 1]); fprintf (stderr, "next_line = %f\n", storage-> line_list_nu[rpacket_get_next_line_id (packet) + 1]); } fprintf (stderr, "ERROR: Comoving nu less than nu_line!\n"); fprintf (stderr, "comov_nu = %f\n", comov_nu); fprintf (stderr, "nu_line = %f\n", nu_line); fprintf (stderr, "(comov_nu - nu_line) / nu_line = %f\n", (comov_nu - nu_line) / nu_line); fprintf (stderr, "r = %f\n", r); fprintf (stderr, "mu = %f\n", mu); fprintf (stderr, "nu = %f\n", nu); fprintf (stderr, "doppler_factor = %f\n", doppler_factor); fprintf (stderr, "cur_zone_id = %" PRIi64 "\n", cur_zone_id); return TARDIS_ERROR_COMOV_NU_LESS_THAN_NU_LINE; } } else { rpacket_set_d_line (packet, MISS_DISTANCE); return TARDIS_ERROR_OK; } }
void montecarlo_line_scatter(rpacket_t *packet, storage_model_t *storage, double distance) { double comov_energy = 0.0; int64_t emission_line_id = 0; double old_doppler_factor = 0.0; double inverse_doppler_factor = 0.0; double tau_line = 0.0; double tau_electron = 0.0; double tau_combined = 0.0; bool virtual_close_line = false; int64_t j_blue_idx = -1; if (rpacket_get_virtual_packet(packet) == 0) { j_blue_idx = rpacket_get_current_shell_id(packet) * storage->line_lists_j_blues_nd + rpacket_get_next_line_id(packet); increment_j_blue_estimator(packet, storage, distance, j_blue_idx); } tau_line = storage->line_lists_tau_sobolevs[rpacket_get_current_shell_id(packet) * storage->line_lists_tau_sobolevs_nd + rpacket_get_next_line_id(packet)]; tau_electron = storage->sigma_thomson * storage->electron_densities[rpacket_get_current_shell_id(packet)] * distance; tau_combined = tau_line + tau_electron; rpacket_set_next_line_id(packet, rpacket_get_next_line_id(packet) + 1); if (rpacket_get_next_line_id(packet) == storage->no_of_lines) { rpacket_set_last_line(packet, true); } if (rpacket_get_virtual_packet(packet) > 0) { rpacket_set_tau_event(packet, rpacket_get_tau_event(packet) + tau_line); } else if (rpacket_get_tau_event(packet) < tau_combined) { old_doppler_factor = move_packet(packet, storage, distance); rpacket_set_mu(packet, 2.0 * rk_double(&mt_state) - 1.0); inverse_doppler_factor = 1.0 / rpacket_doppler_factor(packet, storage); comov_energy = rpacket_get_energy(packet) * old_doppler_factor; rpacket_set_energy(packet, comov_energy * inverse_doppler_factor); storage->last_line_interaction_in_id[storage->current_packet_id] = rpacket_get_next_line_id(packet) - 1; storage->last_line_interaction_shell_id[storage->current_packet_id] = rpacket_get_current_shell_id(packet); storage->last_interaction_type[storage->current_packet_id] = 2; if (storage->line_interaction_id == 0) { emission_line_id = rpacket_get_next_line_id(packet) - 1; } else if (storage->line_interaction_id >= 1) { emission_line_id = macro_atom(packet, storage); } storage->last_line_interaction_out_id[storage->current_packet_id] = emission_line_id; rpacket_set_nu(packet, storage->line_list_nu[emission_line_id] * inverse_doppler_factor); rpacket_set_nu_line(packet, storage->line_list_nu[emission_line_id]); rpacket_set_next_line_id(packet, emission_line_id + 1); rpacket_reset_tau_event(packet); rpacket_set_recently_crossed_boundary(packet, 0); if (rpacket_get_virtual_packet_flag(packet) > 0) { virtual_close_line = false; if (!rpacket_get_last_line(packet) && fabs(storage->line_list_nu[rpacket_get_next_line_id(packet)] - rpacket_get_nu_line(packet)) / rpacket_get_nu_line(packet) < 1e-7) { virtual_close_line = true; } // QUESTIONABLE!!! bool old_close_line = rpacket_get_close_line(packet); rpacket_set_close_line(packet, virtual_close_line); montecarlo_one_packet(storage, packet, 1); rpacket_set_close_line(packet, old_close_line); virtual_close_line = false; } } else { rpacket_set_tau_event(packet, rpacket_get_tau_event(packet) - tau_line); } if (!rpacket_get_last_line(packet) && fabs(storage->line_list_nu[rpacket_get_next_line_id(packet)] - rpacket_get_nu_line(packet)) / rpacket_get_nu_line(packet) < 1e-7) { rpacket_set_close_line(packet, true); } }
bool test_rpacket_get_current_shell_id(unsigned int value) { rpacket_t rp; rpacket_set_current_shell_id(&rp, value); return value==rpacket_get_current_shell_id(&rp); }