//main routine for computing light emission/absorption/propagation properties through plasma bool sing; //whether to do the fast light or full evolution of simulation as the light ray propagates doub rr, //radius costh, //cos(polar angle) ph, //azimuthal angle cossq, //cos^2(polar angle) sinsq, //sin^2(polar angle) - to make the code nicer rsq, //rr*rr Del, //rsq-2.*rr+asq rhosq, //rsq+asq*cossq lrman, //weight of closest cell in interpolation over radial grid thman, //weight of closest cell in interpolation over theta grid for given radius phman, //weight of closest cell in interpolation over phi grid phfrac, //mapping of phi coordinate to a (continuous) cell number in phi direction for fluid simulation timfrac, //mapping of proper time coordinate to a (continuous) fluid simulation snapshot ID timman, //weight of the fluid simulation snapshot with the closest ID in interpolation over time temp; //temp doub rest[11], //single record in a fluid simulation file rho, //physical number density Ttot, //internal energy density tet, //proton temperature tpt; //electron temperature doub ly[4], //coordinate vector along the geodesic kBL[4], //tangent vector along the geodesic in Boyer-Lindquist (BL) coordinates e1BL[4], //perpendicular vector in Boyer-Lindquist coordinates parallel-transported along geodesic kupKS[4], //tangent vector in Kerr-Schild (KS) coordinates e1upKS[4], //perpendicular vector in Kerr-Schild coordinates kxx[4]={0.,0.,0.,0.}, //tangent vector in locally-flat co-moving reference frame (LFCRF) e1xx[4]={0.,0.,0.,0.}, //perpendicular vector in LFCRF e2xx[4]={0.,0.,0.,0.}, //second perpendicular vector in LFCRF uxx[4]={0.,0.,0.,0.}, //velocity vector in LFCRF - should be {1.,0.,0.,0.} iKS[4][4], //-,+,+,+ signature covariant (upper indices) Kerr-Schild metric iMKS[4][4], //modified Kerr-Schild (MKS) metric (code coordinates) MKStoKS[4][4], //(covariant) vector transformation from MKS to KS u[4], //4-velocity in MKS ulo[4], //covariant (low indices) 4-velocity in MKS uKS[4], //4-velocity in KS uloKS[4], //covariant (low indices) 4-velocity in KS Bi[4], //3-vector of magnetic field (Bi[0]==0) (NOT physical magnetic field) Bup[4], //covariant 4-vector of magnetic field in MKS BupKS[4], //covariant 4-vector of magnetic field in KS sc[4]; //auxiliary for vector normalization doub B[4]={0.,0.,0.,0.}; //magnetic field in LFCRF (physical magnetic field), NOT equal to Bi[4] doub yyloKS[4][4]={{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}; //transformation matrix between KS covariant vector and locally flat co-moving reference frame doub knorm, //normalization of spatial part of k vector (while k^\mu k_\mu=0) in LFCRF e1norm, //normalization of e1 vector spatial part in LFCRF ue1, //scalar product of u.e1 ku, //scalar product of u.k kbpar, //scalar product of k.B kbperp, //length of k x B = \sqrt(B^2-kbpar^2) Be1, //scalar product of e1.B Be2, //scalar product of e2.B Bn, //norm of (physical) magnetic field vector = magnetic field strength sin2k, //sine of double angle of B vector projected onto e1, e2 plane with respect to (-e1) vector - helps in radiative transfer cos2k, //correspondent cosine Bnu, //thermal source term in LFCRF fr, //full redshift/Doppler shift nufr, //frequency in LFCRF taking redshift into account nW, //effectively a ratio of observed to cyclotron frequency with some convenient factor jIc,aIc, //thermal emissivity and absoprtivity in total intensity jQc,aQc, //thermal emissivity and absoprtivity in linearly polarized intensity (\sqrt(U^2+Q^2)) jVc,aVc, //thermal emissivity and absoprtivity in circularly polarized intensity xjIc,xaIc, //approximation to thermal emissivity and absoprtivity in total intensity rVc,rQc, //Faraday rotation and conversion coefficients xIc,xQc,xVc, //dimensionless emissivities computed from the look-up tables XX, //convenient quantity over which the lookup is conducted for rotativities xrVc,xrQc, //dimensionless rotativities computed from the look-up tables (still approximate) coskb, //cosine of angle between k and B sinkb; //sine of angle between k and B (always above 0) int m, k, j, n, i, tn, //closest cell index (for fluid simulation) in theta direction rn, //closest cell index (for fluid simulation) in radial direction sn; //closest ID of fluid simulation snapshot int curr=*(int*)pas; //thread number passed by address to current thread if((curr>=nthreads)||(curr<0)){ //check the bounds of thread number printf("Error in thread number \n Exiting \n"); exit(-1); }; doub nu=ppy[curr].nu; //define frequency in current thread int indx=ppy[curr].indx; //number of points on current geodesic doub la=ppy[curr].lamx[0], //minimum affine parameter (zero) lb=ppy[curr].lamx[indx]+1e-14; //maximum affine parameter (~1 for most geodesics hitting the BH, ~2 for most geodesics leaving to infinity) doub lz=t, //affine parameter of interest = proper time lx; //affine parameter at the closest point on a geodesic int ia=0, //min index of a point on a geodesic ib=indx, //max index of a point on a geodesic ix; //index of the closest point on a geodesic //given the proper time find where on a geodesic we are if((lz<=lb) && (la<=lz)){ while(ib>ia+1){ ix=(ia+ib)>>1; lx=ppy[curr].lamx[ix]; if(lz100000.) || (rr<1.)) { printf("Radial coordinate on a geodesic rr=%f is out of bounds \n Exiting ",rr); exit(-1); }; doub lrz=log(rr); //log of radius, since simulation grid is approximately logarithmic int indr=ndd-1; //max index of the array of radial coordinates doub lrx, //log of radius of the closest radial cell of the fluid simulation lra=coord[0][0][0], //min log of radius lrb=coord[indr][0][0]; //max log of radius ia=0; //min index of radial coordinates array ib=indr; //max index of radial coordinates array //find the closest radial cells of the fluid simulation/its radial extension if((lrz<=lrb) && (lra<=lrz)){ while(ib>ia+1){ ix=(ia+ib)>>1; lrx=coord[ix][0][0]; if(lrzcritan){ costh=critan; }; if(costh<-critan){ costh=-critan; }; int indth=thlen-1; //maximum index of theta coordinates array doub costhx, //cos(theta) for given radial and theta coordinates tha, //closest to costh of interest cos(theta) on the grid thb; ia=0; //indices of on cos(theta) grid ib=indth; //find the closest theta cells of the fluid simulation/its radial extension while(ib>ia+1){ ix=(ia+ib)>>1; costhx=(1.-lrman)*theta[rn][ix]+lrman*theta[rn+1][ix]; if(costh=maxtim){ //for too large time offsets use maximum offset fluid simulation snapshot sn=0; sing=true; }; if(t<=mintim){ //for too small time offsets use maximum offset fluid simulation snapshot sn=2*fdiff; sing=true; }; //auxiliary quantities cossq=costh*costh; sinsq=1-cossq; rsq=rr*rr; rhosq=rsq+asq*cossq; Del=rsq-2.*rr+asq; temp=2.*rr/rhosq; //-,+,+,+ signature covariant KS metric matrix iKS[0][0]=temp-1.; iKS[0][1]=temp; iKS[0][2]=0.; iKS[0][3]=-a*temp*sinsq; iKS[1][0]=iKS[0][1]; iKS[1][1]=1.+temp; iKS[1][2]=0.; iKS[1][3]=-a*(1.+temp)*sinsq; iKS[2][0]=iKS[0][2]; iKS[2][1]=iKS[1][2]; iKS[2][2]=rhosq; iKS[2][3]=0.; iKS[3][0]=iKS[0][3]; iKS[3][1]=iKS[1][3]; iKS[3][2]=iKS[2][3]; iKS[3][3]=sinsq*(rhosq+asq*(1+temp)*sinsq); //determine physical quantites at a point with given coordinates if(rr<=rcut){ //inside the convergence radius do interpolation if(sing) //fast light approximation - no time axis for(m=0;m<11;m++) //3D space - multi-linear continuous interpolation over 8 points rest[m]=(1-lrman)*(1-thman)*(1-phman)*(*uu[sn])[k][tn][rn][m]+lrman*(1-thman)*(1-phman)*(*uu[sn])[k][tn][rn+1][m]+(1-lrman)*thman*(1-phman)*(*uu[sn])[k][tn+1][rn][m]+lrman*thman*(1-phman)*(*uu[sn])[k][tn+1][rn+1][m]+ (1-lrman)*(1-thman)*phman*(*uu[sn])[ak][tn][rn][m]+lrman*(1-thman)*phman*(*uu[sn])[ak][tn][rn+1][m]+(1-lrman)*thman*phman*(*uu[sn])[ak][tn+1][rn][m]+lrman*thman*phman*(*uu[sn])[ak][tn+1][rn+1][m]; else //proper simultaneous evolution of simulation and light propagation for(m=0;m<11;m++) //4D space - multi-linear continuous interpolation over 16 points rest[m]=(1-timman)*((1-lrman)*(1-thman)*(1-phman)*(*uu[sn])[k][tn][rn][m]+lrman*(1-thman)*(1-phman)*(*uu[sn])[k][tn][rn+1][m]+(1-lrman)*thman*(1-phman)*(*uu[sn])[k][tn+1][rn][m]+ lrman*thman*(1-phman)*(*uu[sn])[k][tn+1][rn+1][m]+(1-lrman)*(1-thman)*phman*(*uu[sn])[ak][tn][rn][m]+lrman*(1-thman)*phman*(*uu[sn])[ak][tn][rn+1][m]+(1-lrman)*thman*phman*(*uu[sn])[ak][tn+1][rn][m]+ lrman*thman*phman*(*uu[sn])[ak][tn+1][rn+1][m])+timman*((1-lrman)*(1-thman)*(1-phman)*(*uu[sn+1])[k][tn][rn][m]+lrman*(1-thman)*(1-phman)*(*uu[sn+1])[k][tn][rn+1][m]+ (1-lrman)*thman*(1-phman)*(*uu[sn+1])[k][tn+1][rn][m]+lrman*thman*(1-phman)*(*uu[sn+1])[k][tn+1][rn+1][m]+(1-lrman)*(1-thman)*phman*(*uu[sn+1])[ak][tn][rn][m]+lrman*(1-thman)*phman*(*uu[sn+1])[ak][tn][rn+1][m]+ (1-lrman)*thman*phman*(*uu[sn+1])[ak][tn+1][rn][m]+lrman*thman*phman*(*uu[sn+1])[ak][tn+1][rn+1][m]); rho=rest[0]*rhonor; //physical density Ttot=rest[1]*mp*cc*cc/3/kb/rest[0];//internal energy density //testing k values //if((4030)||((rr>=9)&& (magn>10.))) // boundary is in accordance with McKinney et al. (2012) Ttot=minT; if(isBred) //temperature reduction in high magnetization regions Ttot*=exp(-magn/10.); /////////////////////// if(Ttot>maxT) //if temperature is above allowed, then set it to maximum allowed Ttot=maxT; if(Ttotia+1){ ix=(ia+ib)>>1; Tx=ts[ix]; if(Tz