#include "iteration_functions.h" #define NSC_MAX 1000 extern double albedobase; /*==================================================================*/ /*Function prototypes*/ /*==================================================================*/ void comptonization(double E_lab, double* k_lab, double* Efield_lab, double* Magfield_lab, double* E_new_lab, double* k_new_lab, double* Efield_lab_new, double* Magfield_lab_new); double distance_bottom(double z0, double kz); double distance_top(double z0, double kz, double H); /*==================================================================*/ /*Datatypes defined in the header globals.h*/ /*==================================================================*/ //double obsmindeg; //double obsmaxdeg; //double* array_angles; //double* array_ubounds; //double** array_gb; //double** ptr_2colfile; const gsl_root_fsolver_type* T_phi; gsl_root_fsolver* s_phi; //const gsl_root_fsolver_type* T_disk; //gsl_root_fsolver* s_disk; const gsl_root_fsolver_type* T_maxw; gsl_root_fsolver* s_maxw; /*==================================================================*/ int slab_mc(int nphot, int seed) { int ii; int jj; int n_sc; int n_zero_sc; int nph_esc; int Fval_max; int FlagLocation; int photon_diffusion[NSC_MAX]; int status; double E_lab; double E_new_lab; double k_lab[3]; double k_new_lab[3]; double Efield_lab[3]; double Efield_lab_new[3]; double Magfield_lab[3]; double Magfield_lab_new[3]; double pos[3]; double cos_theta; double sin_theta; double phi; double NeDisk; double r_units; double Hphot; double L_top; double tau; //double eps; double l_int; double csi; double Pdeg; T_disk = gsl_root_fsolver_bisection; s_disk = gsl_root_fsolver_alloc(T_disk); T_phi = gsl_root_fsolver_bisection; s_phi = gsl_root_fsolver_alloc(T_phi); /*This is for sampling beta from subrelativistics maxwellian*/ T_maxw = gsl_root_fsolver_bisection; s_maxw = gsl_root_fsolver_alloc(T_maxw); nstepangles = 40; obsmindeg = 0.; obsmaxdeg = 90.; ptr_gb = read_array( stringconcat(getenv("MC_INSTDIR"), "/electron_distributions/maxwellian/temp_random.txt")); matrix_gb = stringconcat(getenv("MC_INSTDIR"), "/electron_distributions/maxwellian/gammabeta_lab.fits"); array_gb = read_matrix(matrix_gb); double array_ene[NSTEP_ENE]; make_array_energy(array_ene, 0.01, 20, NSTEP_ENE); double** array_counts; array_counts = dmatrix(0, NSTEP_ENE - 1, 0, nstepangles - 1); double** reduce_array_counts; reduce_array_counts = dmatrix(0, NSTEP_ENE - 1, 0, nstepangles - 1); for (ii = 0; ii < NSTEP_ENE - 1; ii++) { for (jj = 0; jj < nstepangles; jj++) { array_counts[ii][jj] = 0; reduce_array_counts[ii][jj] = 0; } } /*=======================================================================*/ Hphot = 0.5; r_units = NS_MASS * R_SCW_SUN; NeDisk = disktau / (SIGMA_T * r_units * Hphot); /*=======================================================================*/ if (DiskPolarizationFlag == FROMFILE) { radiation_field_t* radiation_field = (radiation_field_t*)malloc(sizeof(radiation_field_t)); read_resultsfile(polarinput, radiation_field, MC_SLAB); setup_gsl_objects(radiation_field, MC_SLAB); } Pdeg=0; nph_esc = 0; cos_theta = 0; for (ii = 0; ii < NSC_MAX; ii++) { photon_diffusion[ii] = 0; } /*===================================================================*/ array_angles = (double*)malloc((nstepangles) * sizeof(double)); array_ubounds = (double*)malloc((nstepangles + 1) * sizeof(double)); make_array_angles(array_angles, array_ubounds); stokes_parameters struct_stokes[POLAR_NBOUNDS - 1]; allocate_stokes_pointer(struct_stokes); stokes_parameters struct_stokes_average[POLAR_NBOUNDS - 1]; allocate_stokes_pointer(struct_stokes_average); n_zero_sc=0; /*=============================================================*/ /*Here starts loop over photon */ /*=============================================================*/ for (ii = 0; ii < nphot; ii++) { //======================================================================== */ // New unpolarized photon */ // ===================================================================== */ if (rank == 0 && ii % 5000 == 0) { printf("======================\n"); printf("Photon %d\n", ii); } n_sc = 0; E_lab = bb_spec(ktbb); E_new_lab = 0; pos[0] = 0; pos[1] = 0; if (seed == 1) { pos[2] = Hphot / 2; cos_theta = 2 * clock_random() - 1; } else if (seed == 2) { pos[2] = clock_random() * Hphot; cos_theta = 2 * clock_random() - 1; } else { pos[2] = 0; if (DiskPolarizationFlag == FROMFILE) { csi = clock_random(); status = gsl_spline_eval_e(Spline_sample_Iu, csi, xacc_1d, &cos_theta); if (status) { printf("Error\n"); printf("File %s\n", __FILE__); } printf("sampling %lf\n", cos_theta); } else { cos_theta = clock_random(); } } sin_theta = sqrt(1 - cos_theta * cos_theta); phi = 2 * PI * clock_random(); k_lab[0] = sin_theta * cos(phi); k_lab[1] = sin_theta * sin(phi); k_lab[2] = cos_theta; if (DiskPolarizationFlag == FROMFILE) { electricfield_fromfile(k_lab, Efield_lab, Magfield_lab, &Pdeg); } else { unpolarized_seedphot(k_lab, Efield_lab, Magfield_lab); } /*====================================================================*/ FlagLocation = 1; while (FlagLocation) { if (k_lab[2] >= 0) { L_top = distance_top(pos[2], k_lab[2], Hphot); } else { L_top = distance_bottom(pos[2], k_lab[2]); } /*====================================================================*/ /*Compute the optical depth from top or base of the atmosphere*/ /*=====================================================================*/ tau = NeDisk * SIGMA_T * r_units * L_top; eps = -log(clock_random()); if (tau > eps) { l_int = eps / (NeDisk * SIGMA_T * r_units); pos[0] = pos[0] + k_lab[0] * l_int; pos[1] = pos[1] + k_lab[1] * l_int; pos[2] = pos[2] + k_lab[2] * l_int; //printf("Photon %d before scattering %d Pdeg = %5.4f\n", ii, n_sc, Pdeg); comptonization(E_lab, k_lab, Efield_lab, Magfield_lab, &E_new_lab, k_new_lab, Efield_lab_new, Magfield_lab_new); //printf("After scattering Pdeg = %5.4f\n\n", Pdeg); n_sc++; E_lab = E_new_lab; for (jj=0; jj<3; jj++) { k_lab[jj] = k_new_lab[jj]; Efield_lab[jj] = Efield_lab_new[jj]; Magfield_lab[jj] = Magfield_lab_new[jj]; } } else /*Photon potentially escaping from the slab */ { if (k_lab[2] > 0) { // printf("Photon %d escaping after %d scattering\n", ii, n_sc); if (n_sc==0) n_zero_sc++; compute_stokes(E_lab, k_lab, Efield_lab, struct_stokes, array_ubounds, 0); photon_diffusion[n_sc]++; collect_photons(E_new_lab, k_lab, array_ene, array_counts, 0); nph_esc++; FlagLocation = 0; } else { csi = clock_random(); /*Photon absorbed and newly re-emitted with probability A=albedobase*/ if (csi <= albedobase) { // printf("Photon %d reflected\n", ii); cos_theta = clock_random(); sin_theta = sqrt(1 - cos_theta * cos_theta); phi = 2 * PI * clock_random(); k_lab[0] = sin_theta * cos(phi); k_lab[1] = sin_theta * sin(phi); k_lab[2] = cos_theta; pos[0] = 0; pos[1] = 0; pos[2] = 0; unpolarized_seedphot(k_lab, Efield_lab, Magfield_lab); E_lab = bb_spec(ktbb); } /*Photon absorbed*/ else { FlagLocation = 0; break; } } // Close the else with condition k_lab[2] < 0 } // End of confition if (tau > eps)... else... } // end of while (FlagLocation) } /*==================================================================*/ for (ii = 0; ii < POLAR_NBOUNDS - 1; ii++) { MPI_Reduce(struct_stokes[ii].array_Is, struct_stokes_average[ii].array_Is, nstepangles, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(struct_stokes[ii].array_Qs, struct_stokes_average[ii].array_Qs, nstepangles, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(struct_stokes[ii].array_Us, struct_stokes_average[ii].array_Us, nstepangles, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); MPI_Reduce(struct_stokes[ii].counter, struct_stokes_average[ii].counter, nstepangles, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); } for (ii = 0; ii < NSTEP_ENE; ii++) { for (jj = 0; jj < nstepangles; jj++) { MPI_Reduce(&array_counts[ii][jj], &reduce_array_counts[ii][jj], 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); } } // Get the number of processes MPI_Comm_size(MPI_COMM_WORLD, &nproc); /*==================================================================*/ if (rank == 0) { compute_stokes(1, k_lab, Efield_lab, struct_stokes_average, array_ubounds, 1); printf("Percentage of escaping photons from the top layer %4.3f\n", 1. * nph_esc / nphot); printf("Percentage of escaping non scattered photons from the top layer %4.3f\n", (double) n_zero_sc/ nphot); /*============================================================*/ dat_diffusion = fopen(diffusion, "w"); fprintf(dat_diffusion, "!Percentage of escaping photons %4.3f\n", 1. * nph_esc / nphot); Fval_max=-10; for (ii = 0; ii < 300; ii++) { if (photon_diffusion[ii] > Fval_max) { Fval_max = photon_diffusion[ii]; } } for (ii = 0; ii < 300; ii++) { fprintf(dat_diffusion, " %d %3.2f\n", ii, (double)photon_diffusion[ii]/Fval_max); } fclose(dat_diffusion); } collect_photons(0, k_lab, array_ene, reduce_array_counts, 1); dat_energy_polar = fopen(polarfile, "w"); write_polardata(struct_stokes_average, ene_bound, dat_energy_polar); fclose(dat_energy_polar); gsl_root_fsolver_free(s_phi); gsl_root_fsolver_free(s_disk); return 0; } // End of function void comptonization(double E_lab, double* k_lab, double* Efield_lab, double* Magfield_lab, double* E_new_lab, double* k_new_lab, double* Efield_lab_new, double* Magfield_lab_new) { int jj; int status; int PolarFlag; double Pdeg; double phik; double E_erf; double E_new_erf; double csi; double costheta_erf; double sintheta_erf; double beta_el; double k_erf[3]; double k_new_erf[3]; double el_vel_vect[3]; double ElectField_new_erf[3]; double ElectField_old_erf[3]; double MagField_Erf[3]; PolarFlag=0; Pdeg=0; //================================================================== */ // Find the K' components in the ERF */ // If also polarization is computed, transform also the electric */ // field vector to ERF */ //================================================================== */ beta_el = sample_electron(E_lab, k_lab, kte, ACCRETION_DISK, el_vel_vect); versor_boost(k_lab, el_vel_vect, k_erf, 1); elmag_lorentztransform(Efield_lab, Magfield_lab, el_vel_vect, ElectField_old_erf, MagField_Erf, 1); E_erf = energy_lorentz_boost(E_lab, el_vel_vect, k_lab, 1); csi = clock_random(); costheta_erf = (-1 + pow(-2 + 4 * csi + sqrt(5 - 16 * csi + 16 * pow(csi, 2)), 2 / 3.)) / pow(-2 + 4 * csi + sqrt(5 - 16 * csi + 16 * pow(csi, 2)), 1 / 3.); sintheta_erf = sqrt(1 - costheta_erf * costheta_erf); // ================================================================== // Find the new energy photon in the erf after scattering //================================================================== E_new_erf = new_energy_erf(E_erf, costheta_erf); phik = sample_azim_angle(E_erf, E_new_erf, costheta_erf, 1); //================================================================== */ /*Find the components of the photon versor after scattering*/ /*Use Equation(2) from Peplow, 1999*/ /*Nuclear Science and Engineering, 131, 132*/ //================================================================== */ for (jj = 0; jj < 3; jj++) { k_new_erf[jj] = k_erf[jj] * costheta_erf + ElectField_old_erf[jj] * cos(phik) * sintheta_erf + MagField_Erf[jj] * sin(phik) * sintheta_erf; } //================================================================== */ // Check the probability for depolarization*/ // and compute the new electric field vector //================================================================== */ PolarFlag=1; status = depolarization_probability(E_erf, E_new_erf, costheta_erf, phik, &Pdeg, &PolarFlag); if (status == 1) { exit(1); } electfield_as_new(k_new_erf, ElectField_old_erf, ElectField_new_erf, PolarFlag); vect_prod(k_new_erf, ElectField_new_erf, MagField_Erf); // =========================================================================== */ // Back convert from (K1)' in ERF to lab*/ // =========================================================================== */ versor_boost(k_new_erf, el_vel_vect, k_new_lab, 2); // ================================================================== */ // Back-transform electric field versor to the lab frame */ // ================================================================== */ elmag_lorentztransform(ElectField_new_erf, MagField_Erf, el_vel_vect, Efield_lab_new, Magfield_lab_new, 2); // ================================================================== */ // Back convert electron energy from ERF to lab */ // ================================================================== */ *E_new_lab = energy_lorentz_boost(E_new_erf, el_vel_vect, k_new_erf, 2); if (isnan(*E_new_lab) || *E_new_lab < 0) { printf("Error in photon energy in lab frame after scattering: value %5.4f\n", *E_new_lab); exit(1); } } /*======================================================================*/ double distance_top(double z_pos, double kz, double H) { double t; t = (H - z_pos) / kz; return t; } /*======================================================================*/ double distance_bottom(double z_pos, double kz) { double t; t = -z_pos / kz; return t; }