#include "pol_montecarlo.h" #include "netcdfcpp.h" #include #include #define ranf mtrand->drand // Remember all the length and time units are in mfp=lsa. const double lambda=0.6328; // micro const double dia=2.0; // micro const double n_water=1.33; const double n_sct=1.59; const double xx=pi*dia/lambda*n_water; // size parameter of the Mie sphere const double mr=n_sct/n_water, mi=0.0; // m=mr-i*mi is the refractive index const double L=4; // slab thickness in lsa const double HW=10; // the half width of the window in lsa const int NN=100; // NN grids on the backscattering window const int MAXSCT=500; // kill the photon after this number of scattering double M[NN][4][4]; const int photons=10000000*30; // 10 mins for 10000000. // convert parallel E1 and perpendicular E2 to Stokes vector static inline void EtoS(dcmplx E1, dcmplx E2, double S[4]) { dcmplx E12; S[0] = 1; S[1] = norm(E1) - norm(E2); E12 = conj(E1)*E2; S[2] = 2*E12.real(); S[3] = 2*E12.imag(); } // M(rho, phi=0) = So*Si*D // with D=[[1,0,0,0]; [0,3-cos4phi,sin4phi,0]; [0,sin4phi,3+cos4phi,0,]; [0,0,0,4]] static inline void mullerDeposit(double So[4], double Si[4], double phi, double weight, double M[4][4]) { double sin4phi=sin(4*phi), cos4phi=cos(4*phi); double D00=1, D11=3-cos4phi, D12=sin4phi, D21=sin4phi, D22=3+cos4phi, D33=4; for (int i=0; i<4; i++) { M[i][0] += So[i]*Si[0]*D00*weight; M[i][1] += So[i]*(Si[1]*D11 + Si[2]*D21)*weight; M[i][2] += So[i]*(Si[1]*D12 + Si[2]*D22)*weight; M[i][3] += So[i]*Si[3]*D33*weight; } } static int write_results(const char* fname) { NcFile nc (fname, NcFile::Replace); // Create and leave in define mode // Check if the file was opened if (! nc.is_valid()) { cerr << "can't create netCDF file " << fname << "\n"; return 0; } // Create dimensions NcDim* nn = nc.add_dim("NN", NN); NcDim* four = nc.add_dim("FOUR", 4); // Create variables and their attributes NcVar* c = nc.add_var("M", ncDouble, nn, four, four); c->add_att("long_name", "Muller matrix at phi=0"); // Global attributes nc.add_att("NN", NN); nc.add_att("HW", HW); nc.add_att("xx", xx); nc.add_att("mr", mr); nc.add_att("mi", mi); nc.add_att("L", L); nc.add_att("photons", photons); // Start writing dcata, implictly leaves define mode c->put(&M[0][0][0], c->edges()); // close of nc takes place in destructor return 1; } int main () { dcmplx Eix, Eiy; // incident E field double alpha, beta, Si[4]; // the incident Stokes vector dcmplx Ed1, Ed2, Eox, Eoy; // outgoing E field double td, deposit, Q[3][3], So[4]; dcmplx Ei1, Ei2, Eo1, Eo2; // incident and outgoing E with respect to the phi=0 plane double dt, x, y, rho, phi; int irho, nsct; double T=0, R=0, Lost=0; // total transmission and reflection mt_prng *mtrand=new mt_prng(); dcmplx m(mr, mi); scatterer sct(xx, m); photonPacket *ph = new photonPacket(&sct); for (int i = 1; i <= photons; i++) { alpha = ranf()*pi/2; beta = ranf()*pi; // Eix, Eiy are the parallel (x) and perpendicular (y) electric fields Eix = dcmplx(cos(alpha)*cos(beta), -cos(alpha)*sin(beta)); Eiy = dcmplx(sin(alpha)*cos(beta), sin(alpha)*sin(beta)); ph->launch (Eix, Eiy); if (i % 10000 == 0) fprintf(stderr, "%d\n", i); nsct = 0; while (1) { ph->move (); // use pointEstimator if (nsct > MAXSCT) break; if (ph->z > L) { T += ph->weight; break; } if (ph->z < 0) { R += ph->weight; break; } dt = (ph->t-ph->told)/(ph->z-ph->zold)*(0.-ph->zold); x = ph->xold + ph->P[2][0]*dt; y = ph->yold + ph->P[2][1]*dt; rho = sqrt(x*x + y*y); irho = (int)floor(rho/HW*NN); if (irho >= NN) irho = NN - 1; // crossing the z=0 boundary ph->pointestimator(&td, &deposit, Q, &Ed1, &Ed2, 0, 0, 0, -1); // compute Eox and Eoy from Ed Eox = Ed1*Q[0][0] + Ed2*Q[1][0]; Eoy = Ed1*Q[0][1] + Ed2*Q[1][1]; // We need to rotate both (Eix, Eiy) and (Eox, Eoy) such that the electric field is with respect to the phi=0 plane in the gloabl coordinate system phi = atan2(y, x); Ei1 = Eix*cos(phi) + Eiy*sin(phi); Ei2 = -Eix*sin(phi) + Eiy*cos(phi); Eo1 = Eox*cos(phi) + Eoy*sin(phi); Eo2 = -Eox*sin(phi) + Eoy*cos(phi); // // IMPORTANT: outgoing stokes vector is defined in the local coordinate system // EtoS(Ei1, Ei2, Si); EtoS(-Eo1, Eo2, So); // accumulate Muller matrix. mullerDeposit(So, Si, phi, deposit, M[irho]); ph->scatter (); nsct ++; } } printf("T, R, Lost=%f %f %f\n", T, R, Lost); write_results("rmuller.nc"); delete ph; }