#define ALT struct ice { double la; // absorption length double ls; // scattering length double le; // effective scattering length double g; // double wv; // light wavelength double np; // phase refractive index double ng; // group refractive index double c; // speed of light in vacuum double cm; // speed of light in medium double na; // average propagation refractive index double coschr, sinchr; // cos and sin of the cherenkov angle int size; // size of kurt table double dh, hmin, hmax; // step, min and max depth double *abs, *sca; // arrays of absorption and scattering values double *abs_sum, *sca_sum; // arrays of absorption and scattering depth-integrated values bool kurt; // whether kurt table is used void init(){ // initialize ice parameters if(wv<0.3) wv=0.3; else if(wv>0.6) wv=0.6; double wva=wv*1.e3; kurt=false; double A, B, D, E, a, k; double Ae, Be, De, Ee, ae, ke; bool flag=true; ifstream inFile; inFile.open("icemodel.par", ifstream::in); if(flag=!inFile.fail()){ if(flag) flag=(inFile >> a >> ae); if(flag) flag=(inFile >> k >> ke); if(flag) flag=(inFile >> A >> Ae); if(flag) flag=(inFile >> B >> Be); if(flag) flag=(inFile >> D >> De); if(flag) flag=(inFile >> E >> Ee); if(!flag) cerr << "File icemodel.par found, but is corrupt, falling back to bulk ice" << endl; inFile.close(); if(!flag) return; } else{ cerr << "Using bulk ice model at l=" << wva << "nm: np=" << np << " ng=" << ng << " sca=" << le << " abs=" << la << endl; return; } vector dp, be, ba, td; inFile.open("icemodel.dat", ifstream::in); if(!inFile.fail()){ size=0; double dpa, bea, baa, tda; while(inFile >> dpa >> bea >> baa >> tda){ dp.push_back(dpa); be.push_back(bea); ba.push_back(baa); td.push_back(tda); size++; } if(size<2){ cerr << "File icemodel.dat found, but is corrupt, falling back to bulk ice" << endl; return; } inFile.close(); } else return; double wv0=400; double l_a=pow(wva/wv0, -a); double l_k=pow(wva, -k); double ABl=A*exp(-B/wva); abs = new double[size]; sca = new double[size]; double abs_a=0, sca_a=0; dh=dp[1]-dp[0]; if(dh<=0){ cerr << "Ice table does not use increasing depth spacing, falling back to bulk ice" << endl; return; } for(int i=0; i0) if(fabs(dp[i]-dp[i-1]-dh)>dh*1.e-10){ cerr << "Ice table does not use uniform depth spacing, falling back to bulk ice" << endl; return; } sca[i]=be[i]*l_a; abs[i]=(D*ba[i]+E)*l_k+ABl*(1+0.012*td[i]); if(sca[i]<=0 || abs[i]<=0){ cerr << "Invalid value of ice parameter, falling back to bulk ice" << endl; return; } sca_a+=sca[i]; abs_a+=abs[i]; } sca_a=size/sca_a; abs_a=size/abs_a; hmin=dp[0]-dh/2; hmax=dp[size-1]+dh/2; abs_sum = new double[size]; sca_sum = new double[size]; double abs_aux=0, sca_aux=0; for(int i=0; i=size) i=size-1; double tot=0; #ifdef ALT double ai=((hmin+(i+1)*dh)-z)*abs[i]; double dif=abs_sum[i]+(x*nz-ai)/dh; int j=i; if(nz<0){ for(; j>0; j--) if(abs_sum[j-1]dif) break; } if(i==j) tot=x/abs[i]; else tot=((hmin+(j+1)*dh)-(abs_sum[j]-dif)*dh/abs[j]-z)/nz; return tot; tot=0; #else if(nz>0){ while(true){ if(i==size-1){ tot+=x/abs[i]; break; } double d=(hmin+(i+1)*dh-z)/nz; if(x=size) i=size-1; double tot=0; #ifdef ALT double y=z+nz*a; int j=(int) floor((y-hmin)/dh); if(j<0) j=0; else if(j>=size) j=size-1; if(i==j) tot=a*abs[i]; else tot=((abs_sum[j]-abs_sum[i])*dh-((hmin+(j+1)*dh)-y)*abs[j]+((hmin+(i+1)*dh)-z)*abs[i])/nz; return tot; tot=0; #else if(nz>0){ while(true){ if(i==size-1){ tot+=a*abs[i]; break; } double d=(hmin+(i+1)*dh-z)/nz; if(a=size) i=size-1; double tot=0; #ifdef ALT double ai=((hmin+(i+1)*dh)-z)*sca[i]; double dif=sca_sum[i]+(x*nz-ai)/dh; int j=i; if(nz<0){ for(; j>0; j--) if(sca_sum[j-1]dif) break; } if(i==j) tot=x/sca[i]; else tot=((hmin+(j+1)*dh)-(sca_sum[j]-dif)*dh/sca[j]-z)/nz; return tot; tot=0; #else if(nz>0){ while(true){ if(i==size-1){ tot+=x/sca[i]; break; } double d=(hmin+(i+1)*dh-z)/nz; if(x