int main(int argc, char *argv[]) { char HFile[NCHARMAX],tabledir_aux[NCHARMAX],Tstr[NCHARMAX]; int first_time=0; float pmin,pmax; double tau_ini, x_medium; double pos3d[3]; double s_nH,sx_cont,s_nd; double sq_mu,sq_mu2,sq_b,sq_a,sq_arg; double dust_fac = ext_zstar/zstar,P_H; long ip,i,j,k; const gsl_rng_type * T; time_t t0,t1,t2,t4,tc1,tc2; int NScatRec = 1e4; long ilow,ihigh; double x_1,x_0,H1,H0,xl,Hl,xlow,xhigh,rvp,vpl,vp0l,vp1l,ran0l,ran1l,vp0h,vp1h,ran0h,ran1h,vplow,vphigh; float tot_tab,used_tab; // double Vth=sqrt(2*KB*Temp/MP); int upcone; c = 299792.482; // km s-1 Inv_c = 1./c; Kth=Vth/(c*100000.0); gsl_rng *r; gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc (T); if(argc < 3) { printf(" Input parameter missing. \n "); printf(" Usage: > LyaRt [ParFile] [SEED] \n Exiting..."); exit(0); } /* Paramter file is read, it defines most of the variables found in allvars.h */ strcpy(ParFile,argv[1]); Seed0 = atoi(argv[2]); default_parameters(); dprints(OutShort); dprints(OutLong); read_parameters(ParFile); dprints(OutShort); dprints(OutLong); // The following are definitions specific to particular geometries. if (strcmp(GeomName,"Wind2")==0 || strcmp(GeomName,"Wind3")==0) { dr = (RSphere-R_inner) / (NCells-1); NCellSphere = R_inner/dr + 1.0; NCells += NCellSphere; } if (strcmp(GeomName,"Wind4")==0) { NCellSphere = 100; dr = R_Static / (NCellSphere-1); NCells = (long) ((RSphere - R_inner)/dr + 1.0); NCells += NCellSphere+1; if (NCells > 1e4) printf("WARNING: NCells = %ld value too high\n",NCells); } if (strcmp(GeomName,"ThinShell2")==0) { NCellSphere = 500; dr1 = R_inner / (NCellSphere-1); dr2 = (RSphere-R_inner)/(NCells-1); NCells+= NCellSphere; } // --- P = (photon*) malloc(NPhotons * sizeof(photon)); CellArr = (cell*) malloc(NCells * sizeof(cell)); define_geometry(GeomName,CellArr); gsl_rng_set(r,Seed0); //Initializing the random generator with seed Seed0? //Finding range of emission probability in cells pmin = CellArr[0].p_lya; pmax = pmin; for (i=1;i<NCells;i++) { if(CellArr[i].p_lya < pmin) pmin = CellArr[i].p_lya; if(CellArr[i].p_lya > pmax) pmax = CellArr[i].p_lya; } strcpy(tabledir_aux,tabledir); strcat(tabledir_aux,sxfile); strcpy(HFile,tabledir_aux); if (Temp >= 0) sprintf(Tstr,"%.2f",Temp); else sprintf(Tstr,"%.1f",Temp); if (Temp > 0 && Temp < 1) sprintf(Tstr,"%.3f",Temp); strcat(HFile,Tstr); printf(" Storing tabulated data... \n"); HList = (double*) malloc(NTAB2*sizeof(double)*2); DipList = (double*) malloc(NTAB1*2*sizeof(double)); HGList = (float*) malloc(NTAB2*2*sizeof(float)); #ifndef HAPPROX get_H(HFile,HList); printf("GET_H read\n"); #endif get_dipolar(DipList); printf("GET_DIPOLAR read\n"); get_HG(HGList); printf("GET_HG read\n"); // Print parameters read print_parameters(CellArr); #ifdef TEST_RII printf("TESTING REDISTRIBUTION FUNCTION for x0 = %f\n",x_test); #endif //Loop over NPhotons printf(" Loop over %ld photons started...\n",NPhotons); cx = 0.; cy = 0.; cz = 0.; nu0 = 2.47e15; gtype = (strcmp(GeomName,"HomSlab")==0) ? 0 : 1; if (strcmp(GeomName,"HomSphere")==0) gtype = 2; dprinti(gtype); fflush(stdout); nout = 0; #ifdef TCONST TPar = sx_const * pow(CellArr[0].T,-0.5); #endif XArr = (float *) malloc(NPhotons*sizeof(float)); X0Arr = (float *) malloc(NPhotons*sizeof(float)); InterArr = (int *) malloc(NPhotons*sizeof(int)); NscatArr = (int *) malloc(NPhotons*sizeof(int)); #ifdef GETPOSDIR PosArr = (float *) malloc(NPhotons*3*sizeof(float)); AngleArr = (float *) malloc(NPhotons*2*sizeof(float)); PosArrLong = (float *) malloc(NPhotons*NScatRec*3*sizeof(float)); #endif for (i = 0; i< NPhotons; i++) { XArr[i] = 0; X0Arr[i] = 0; InterArr[i] = -1; NscatArr[i] = -1; #ifdef GETPOSDIR PosArr[3*i] = 0; PosArr[3*i+1] = 0; PosArr[3*i+2] = 0; AngleArr[2*i] = 0; AngleArr[2*i+1] = 0; for (j = 0;j<NScatRec;j++) { PosArrLong[0+ 3*i + 3*NPhotons*j] = 0; PosArrLong[1+ 3*i + 3*NPhotons*j] = 0; PosArrLong[2+ 3*i + 3*NPhotons*j] = 0; } #endif } if (b == 0.) { a_par = 4.693e-4 * sqrt(1./CellArr[idc].T); vth = 12.85 * sqrt(CellArr[idc].T); } else { a_par = 4.693e-4 * sqrt(1./CellArr[idc].T); // a_par = 4.693e-4 * (12.85/b); // a_par = 4.7e-4 * (12.85/b); // vth = ; vth = 12.85 * sqrt(CellArr[idc].T); } if (VarXCrit==1) { x_medium = xp0 - vmax/vth; tau_ini = sx_const * ColDens * pow(CellArr[idc].T,-0.5) * voigt(HList,x_medium); if (tau_ini < 1e4) xcrit = 3; if (tau_ini >1e4 && tau_ini < 1e6) xcrit = 6; if (tau_ini > 1e6) xcrit = 10; //printf("1 xcrit: %f \n",xcrit); } (void) time(&t0); for (ip=0;ip < NPhotons;ip++) { nscat = 0; if( ip > 999 & ip % 1000 == 0) { printf("Photon %ld\n",ip); if( first_time==0 ) { first_time=1; printf("Estimated time to finish: %f [min] \n",1000*op_time * (NPhotons - ip) ); } } // Initialise photon's frequency, direction and position. xi0 = gsl_rng_uniform (r); xi1 = gsl_rng_uniform (r); xi2 = gsl_rng_uniform (r); xi3 = gsl_rng_uniform (r); xi4 = gsl_rng_uniform (r); xi5 = gsl_rng_uniform (r); init_photon(P,ip, xi0, xi1, xi2); dnd = (vth*nu0)/c; flag_zero = 0; (void) time(&t1); i = 0; xi1 = gsl_rng_uniform (r); xi2 = gsl_rng_uniform (r); xi3 = gsl_rng_uniform (r); idc_old = 0; while(idc != -1) { t_0 = - log(gsl_rng_uniform (r)); EscCond = 0; P[ip].ni = sin(th0)*cos(ph0); P[ip].nj = sin(th0)*sin(ph0); P[ip].nk = cos(th0); while(t_0 > 0.) { // Shortcut to compute crossing of empty cells, where no optical depth (t_0) is *used*. empty_cells(P,ip); H_x = voigt(HList, P[ip].xp); if(isnan(H_x)) printf("H_x is nan\n"); // H_x = 0.; // H_x disables H scattering. #ifdef TCONST s_nH = TPar * H_x*CellArr[idc].nH; #else s_nH = sx_const * pow(CellArr[idc].T,-0.5)*H_x*CellArr[idc].nH; #endif #ifdef TAUGUIDERDONI s_nd = Ext_Ratio * pow(CellArr[idc].z/zstar,spar) * CellArr[idc].nH/NHConst; #else s_nd = ext_zstar * CellArr[idc].z * CellArr[idc].nH; #endif s_sum = s_nH + s_nd; s = t_0 / s_sum; radius = sqrt( SQR(P[ip].x) + SQR(P[ip].y)+ SQR(P[ip].z)); // The position of the photon after consuming its optical depth is computed here: s_ = crossing_cells(P,gtype,ip); rx0 = P[ip].x; ry0 = P[ip].y; rz0 = P[ip].z; ni = P[ip].ni; nj = P[ip].nj; nk = P[ip].nk; } if (EscCond == 1) { #ifndef TEST_RII idc = -1; #else idc = 0; #endif if (idc == -1) { escape: x = P[ip].xp + (P[ip].ni*vbulk_x + P[ip].nj*vbulk_y + P[ip].nk*vbulk_z)/vth; // x = c*(g*nup - nu0)/(vth*nu0) - g*(nup/nu0)*(ni*vbulk_x + nj*vbulk_y + nk*vbulk_z)/vth; // dprintd(x); // printf("Photon has escaped in %ld scatterings\n",nscat); // ................................ inter = 4; (void) time(&t2); op_time = (float) (t2-t1)/60.; // printf("Total calculation took %f minutes.\n",op_time); if (strcmp(OutMode,"Long")==0) { printf("\n"); record_data_long(nscat,ip,x,P[ip].x,P[ip].y,P[ip].z,r0,upar,uper1,uper2,H_x,P[ip].xp,inter); } else { // record_data_short(nscat,ip,x,rxf,ryf,rzf,radius,H_x,inter,op_time,flag_zero); XArr[ip] = x; X0Arr[ip]=xp0; InterArr[ip] = inter; NscatArr[ip] = nscat; #ifdef GETPOSDIR PosArr[3*ip] = P[ip].x; PosArr[3*ip+1] = P[ip].y; PosArr[3*ip+2] = P[ip].z; AngleArr[2*ip] = P[ip].th; AngleArr[2*ip+1]= P[ip].ph; // record_data_pos(nscat,ip,x,ph0,th0,rxf,ryf,rzf,inter,op_time,flag_zero); //#else // record_data_short(nscat,ip,x,ph0,th0,radius,inter,op_time,flag_zero); #endif } nout++; goto end; break; } } else { rx0 = rxf; ry0 = ryf; rz0 = rzf; } P_H = s_nH / s_sum; xi1 = gsl_rng_uniform (r); if (strcmp(IncDust,"Yes")==0) inter = (xi1 <= P_H)? 1 : 2 ; else inter = 1; switch(inter) // inter = 1 means interacting with hydrogen, inter = 2 means dust. { case 1: #ifdef USEREJECTION upar = -999.0; i = 0; do { xi0 = gsl_rng_uniform (r); xi1 = gsl_rng_uniform (r); xi2 = gsl_rng_uniform (r); upar = vp_rejection(xp,a_par,xi0,xi1,xi2); i++; } while(upar == -999.0); // if (i > 100000) // printf("VP_REJECTION TOOK %d tries to get upar = %f, x = %f, nscatter = %d\n" \ ,i,upar,xp,nscat); #endif xi0 = gsl_rng_uniform (r); xi1 = gsl_rng_uniform (r); xi2 = gsl_rng_uniform (r); xi3 = gsl_rng_uniform (r); xi3 = (xi3 == 0.0) ? gsl_rng_uniform (r) : xi3; xi4 = gsl_rng_uniform (r); xi5 = gsl_rng_uniform (r); xi6 = gsl_rng_uniform (r); xi7 = gsl_rng_uniform (r); scattering_hydrogen(P,ip); break; case 2: xi1 = gsl_rng_uniform (r); xi2 = gsl_rng_uniform (r); xi3 = gsl_rng_uniform (r); dust_interaction(P,ip); if (end_syg ==1) goto end; break; } // dprinti(nscat); /* if (nscat == 1000000 || nscat == 10000000 ) { printf("********************************************\n"); printf("Number of scatterings so far: %ld\n",nscat); printf("Photon's location %f %f %f\n",rxf,ryf,rzf); dprintf(x); dprintf(xp); dprintf(th0); dprintf(ph0); } */ #ifdef WRITEALL if (ip < 1000) { x = P[ip].xp + (P[ip].ni*vbulk_x + P[ip].nj*vbulk_y + P[ip].nk*vbulk_z)/vth; record_data_long(nscat,ip,x,P[ip].x,P[ip].y,P[ip].z,r0,upar,uper1,uper2,H_x,\ P[ip].xp,inter); } #endif if (gtype ==1) { if (r0 < 0.99*R_inner) { printf("scatter %d of photon %d occurs within empty zone. Something is not ok\n",nscat,ip); printf("rx/r_inner %f ry/r_inner %f rz/r_inner %f radius/r_inner %f\nidc %d\n",\ P[ip].x/R_inner,P[ip].y/R_inner,P[ip].z/R_inner,r0/R_inner,idc); } } nscat++; } end: // printf("done\n"); if (strcmp(Set_Tolerance,"yes") == 0) { // if ((ip >= np_min && nout >= nout_max) || \ // (ip >= np_max)) if ((ip >= np_min && nout >= nout_max) || \ (ip >= np_max) ) // (ip >= np_max && nout >= (int) nout_max/5) || \ { printf("Max number of absorbed photons or limit on the number of photons reached, exiting...\n"); #ifdef GETPOSDIR printf("Writing data\n"); record_data_pos(ip); printf("File %s written\n",OutShort); free(PosArr); free(AngleArr); #else record_data_short(); #endif free(HList); free(DipList); free(HGList); free(CellArr); exit(0); } } #ifdef TIMELIMIT (void) time(&t4); t4 = (float) (t4-t0)/60.; if (t4 > MAXTIME) { printf("MAXTIME reached, forcing output and exit\n"); #ifdef GETPOSDIR record_data_pos(ip); printf("File %s written\n",OutShort); free(PosArr); free(AngleArr); #else record_data_short(); #endif exit(0); } #endif //printf("%ld %f\n",ip,xp); }
void dust_interaction(photon *P, int ip) { double xilow,xihigh; long i; double cosph0 , sinph0 , costh0 , sinth0 ; double Arg1_uper , Arg2_uper , uper1 , uper2 ; double n1_i , n1_j , n1_k , n2_i , n2_j , n2_k , v_i , v_j , v_k , utot ; double alpha , cosalpha , sinalpha , Inv_sinalpha ; double v_pi , v_pj , v_pk , vpn ; float g; double k_p_par , k_p_per; double mulow , muhigh , cosmu , sinmu , mu , cosmu2 , sinmu2 , mu2; double ko1 , ko2 , ko3 , nko0 ; double th_ , costh_ , sinth_ ; double k_po_par , k_po_per , k_o_par , k_o_per , Inv_kpoper , v_po_i , v_po_j , v_po_k , ko_x , ko_y , ko_z , n_ko , v_ko; interd = (xi1 <= Albedo) ? 1 : 0; if (interd == 1) //scattering { // creamos estas viariables para no repetir el mismo calculo muchas veces cosph0 = cos(ph0); sinph0 = sin(ph0); costh0 = cos(th0); sinth0 = sin(th0); // Estos son los angulos de la velocidad del grano de polvo ( eq. 5.37 y eq. 5.38 ) Arg1_uper = sqrt(SQR(xcrit) - log(xi3)); Arg2_uper = 2*Pi*xi4; uper1 = Arg1_uper * cos(Arg2_uper); // esta es la velocidad perpendicular 1 (eq. 5.37) uper2 = Arg1_uper * sin(Arg2_uper); // esta es la velocidad perpendicular 2 (eq. 5.38) // Estos son unos vectores muy convenientes para algo. // parte paralela ?? n1_i = sinph0; n1_j = -cosph0; n1_k = 0; // parte transversal ?? n2_i = cosph0 * costh0 ; n2_j = sinph0 * costh0; n2_k = -sinth0; // creo que esto es la velocidad del photon en el sistema de referencia del laboratio v_i = upar*sinth0*cosph0 + uper1 * n1_i + uper2 *n2_i ; v_j = upar*sinth0*sinph0 + uper1 * n1_j + uper2 *n2_j ; v_k = upar*costh0 + uper1 * n1_k + uper2 *n2_k; // Tal vez esto se deberia llamar vtot, pero que le vamos a hacer. Es el modulo de v. utot = sqrt(SQR(v_i) + SQR(v_j) + SQR(v_k)); if (utot == 0.) { dprintd(utot); exit(0); } // Este alpha es el angulo entre la componente paralela del movimiento del grano de polvo la vel del photon. (eq. 5.54) alpha = acos(upar/utot); cosalpha = upar/utot; sinalpha = sqrt(1 - SQR(cosalpha)); Inv_sinalpha = 1./sinalpha; // Aqui se normaliza v ... se podria hacer antes ... v_i = v_i/utot; v_j = v_j/utot; v_k = v_k/utot; // Sera esto algo asi como la velocidad proyectada??? v_pi = Inv_sinalpha* (sinth0*cosph0 - cosalpha*v_i); v_pj = Inv_sinalpha* (sinth0*sinph0 - cosalpha*v_j); v_pk = Inv_sinalpha* (costh0 - cosalpha*v_k); // Este es el modulo de la velocidad esa, que vete tu a saber que es, y se normaliza vpn = sqrt( SQR(v_pi) + SQR(v_pj) + SQR(v_pk)); v_pi = v_pi/vpn; v_pj = v_pj/vpn; v_pk = v_pk/vpn; //Esto si que no tengo ni idea de que es, pero no le hace daño a nadie... o eso espero :( g = 1./(sqrt(1 - SQR(utot*vth/c))); //Estas cosas son importantes, todas las lineas de antes es para poder calcularlo. k_p_par = (c*cosalpha - utot*vth)/(1 - (upar*vth*Inv_c)); k_p_per = (c*sinalpha)/((1 - (upar*vth*Inv_c))); // Ahora vamos a obtener el coseno del angulo en el que sale disparado el photon en el frame del grano de polvo i = 0; while (xi2 >= HGList[i] && i < nHG) { xilow = HGList[i]; mulow = HGList[i + NTAB2]; i++; } xihigh = HGList[i]; muhigh = HGList[i+NTAB2]; cosmu = (muhigh-mulow)/(xihigh-xilow) * (xi2- xihigh) + muhigh; if (i == nHG) cosmu = mulow; // Este es el angulo polar en el sistema de referencia del atomo de hidrogeno mu = acos(cosmu); sinmu = sin(mu); // Este es el angulo azimutal en el sistema de referencia del atomo de hidrogeno mu2 = 2*Pi*xi6; cosmu2 = cos(mu2); sinmu2 = sin(mu2); // Esto me supera, la verdad. Es posible que sea la direccion del photon en el sistema del grano de polvo. ko1 = Inv_c*(cosmu * k_p_par + sinmu*(k_p_per)*cosmu2); ko2 = Inv_c*(cosmu * k_p_per - sinmu*(k_p_par)*cosmu2); ko3 = sinmu * sinmu2; // Se calcula el modulo y se normaliza nko0 = sqrt( SQR(ko1) + SQR(ko2) + SQR(ko3)); ko1 = ko1/nko0; ko2 = ko2/nko0; ko3 = ko3/nko0; // Este angulo hace llorar al ninio jesus... th_ = acos(ko1); costh_ = cos(th_); sinth_ = sin(th_); // Estoy empezando a pensar que tal vez la 'p' en el nombre se refiere a un sistema de referencia k_po_par = ko1; k_po_per = sqrt(SQR(ko2) + SQR(ko3)); // Aqui hace magia... k_o_par = (c*costh_ + utot*vth)/(1 + (utot*costh_*vth)*Inv_c); k_o_per = (c*sinth_)/((1 + (utot*costh_*vth)*Inv_c)); // Alvaro es un mago Inv_kpoper = 1./k_po_per; v_po_i = Inv_kpoper * (ko2*v_pi + ko3*(v_pk*v_j - v_k*v_pj)); v_po_j = Inv_kpoper * (ko2*v_pj - ko3*(v_pk*v_i - v_k*v_pi)); v_po_k = Inv_kpoper * (ko2*v_pk + ko3*(v_pj*v_i - v_j*v_pi)); // Estas son las coordenadas finales de la V del photon en el Lab Sys ko_x = Inv_c * (k_o_par * v_i + k_o_per *v_po_i); ko_y = Inv_c * (k_o_par * v_j + k_o_per *v_po_j); ko_z = Inv_c * (k_o_par * v_k + k_o_per *v_po_k); // Calcula el modulo y normaliza n_ko = sqrt( SQR(ko_x) + SQR(ko_y) + SQR(ko_z)); ko_x = ko_x/n_ko; ko_y = ko_y/n_ko; ko_z = ko_z/n_ko; // Pruedo prometer y prometo que no se que es esto, pero parace ser para el cambio en frecuencia, que aquí no se aplica. v_ko = utot * (v_i*ko_x + v_j*ko_y + v_k*ko_z); // Finalmente obtenemos los angulos en el sistema de referencia del laboratorio. th0 = acos(ko_z); ph0 = atan2(ko_y,ko_x); ph0 = (ph0 < 0) ? (ph0 + 2*Pi) : ph0; // si ph0 es menor que 0 le suma 2Pi??? // Le asignamos los angulos que hemos sacado del cajon de los angulos buenos al photon. P[ip].th = th0; P[ip].ph = ph0; end_syg = 0; // Un aplauso para Alvaro por favor. } else { absorbed: P[ip].xp += (ni*vbulk_x + nj*vbulk_y + nk*vbulk_z)/vth; // printf("Photon has been absorbed by dust after %ld scatters.\n",nscat); inter = 3; // (void) time(&t2); // op_time = (float) (t2-t1)/60.; // printf("Total calculation took %f minutes.\n",op_time); if (strcmp(OutMode,"Long")==0) { record_data_long(nscat,ip,x,rxf,ryf,rzf,radius,upar,uper1,uper2,H_x,\ xp,inter); dprintl(nscat); printf("\n"); } // record_data_short(nscat,ip,x,rxf,ryf,rzf,radius,H_x,inter,flag_zero,op_time); // record_data_short(nscat,ip,x,ph0,th0,radius,inter,op_time,flag_zero); XArr[ip] = P[ip].xp; X0Arr[ip]=xp0; InterArr[ip] = inter; NscatArr[ip] = nscat; #ifdef GETPOSDIR PosArr[3*ip] = P[ip].x;//rxf; PosArr[3*ip+1] = P[ip].y;//ryf; PosArr[3*ip+2] = P[ip].z;//rzf; AngleArr[2*ip] = th0; AngleArr[2*ip+1]= ph0; // record_data_pos(nscat,ip,x,ph0,th0,rxf,ryf,rzf,inter,op_time,flag_zero); //#else // record_data_short(nscat,ip,x,ph0,th0,radius,inter,op_time,flag_zero); #endif /* #ifdef GETPOSDIR record_data_pos(nscat,ip,x,ph0,th0,rxf,ryf,rzf,inter,op_time,flag_zero); #else record_data_short(nscat,ip,x,ph0,th0,radius,inter,op_time,flag_zero); #endif */ idc = -1; P[ip].idc = idc; end_syg = 1; } }