ray.cc
1 #include "vector.hh"
2 #include "TF1.h"
3 
4 #include "Constants.h"
5 #include "Settings.h"
6 #include "earthmodel.hh"
7 #include "icemodel.hh"
8 #include "signal.hh"
9 #include "vector.hh"
10 #include "position.hh"
11 #include "anita.hh"
12 #include "ray.hh"
13 #include <cmath>
14 #include "icemc_random.h"
15 
16 using std::endl;
17 
18 Ray::Ray() {
19  sum_slopeyness=0.;
20  xaxis=Vector(1.,0.,0.);
21  yaxis=Vector(0.,1.,0.);
22  zaxis=Vector(0.,0.,1.);
23  slopeyx=0.;
24  slopeyy=0.;
25  slopeyz=0.; // these are a measure of how much the surface is sloped in the x,y and z directions
26 }
27  void Ray::PrintAnglesofIncidence() {
28 
29  cout << "angle of incidence (firn-air) is " << nrf_iceside[3].Angle(nsurf_rfexit)*DEGRAD << "\n";
30  cout << "angle of incidence (ice-firn) is " << nrf_iceside[4].Angle(nsurf_rfexit)*DEGRAD << "\n";
31 }
32  void Ray::Initialize() {
33 
34  for (int i=0;i<3;i++) {
35  n_exit2bn[i]=Vector(0.,0.,0.); // normal vector in direction of exit point to balloon - 5 iterations, 3 directions for eac
36  nrf_iceside[i]=Vector(0.,0.,0.); // direction of rf [tries][3d]
37  rfexit_db[i]=Vector(0.,0.,0.);
38  rfexit[i]=Vector(0.,0.,0.); // position where the rf exits the ice- 5 iterations, 3 dimensions eac
39 
40  for (int j=0;j<Anita::NPHI_MAX;j++) {
41  for (int k=0;k<Anita::NLAYERS_MAX;k++) {
42  n_exit2bn_eachboresight[i][k][j]=Vector(0.,0.,0.); // normal vector in direction of exit point to each antenna boresight - 5 iterations
43  nrf_iceside_eachboresight[i][k][j]=Vector(0.,0.,0.); // direction of rf [tries][3d]
44 
45  rfexit_eachboresight[i][k][j]=Vector(0.,0.,0.);
46  }
47  }
48 
49  }
50  nsurf_rfexit=Vector(0.,0.,0.); // normal of the surface at the place where the rf leaves
51  nsurf_rfexit_db=Vector(0.,0.,0.);
52 
53 }
54 void Ray::GetRFExit(Settings *settings1,Anita *anita1,int whichray,Position posnu,Position posnu_down,Position r_bn,Position r_boresights[Anita::NLAYERS_MAX][Anita::NPHI_MAX],int whichtry,IceModel *antarctica) {
55 
56 
57 
58  if (whichray==0)
59  WhereDoesItLeave(posnu,nrf_iceside[2*whichtry],antarctica, // inputs
60  rfexit[whichtry]); // output
61 
62 
63  //******wufan******
64  if (whichray==1) // reflected rays
65  WhereDoesItLeave(posnu_down,nrf_iceside[2*whichtry],antarctica,rfexit[whichtry]); //from mirror point position and the direction of signals to the ice
66  //to find the exit point at the surface of the Earth.wufan
67 
68  n_exit2bn[whichtry] = (r_bn - rfexit[whichtry]).Unit();
69 
70  if (settings1->BORESIGHTS) { // now find rfexit and n_exit2bn for each boresight, still first iteration
71  //cout << "first iteration.\n";
72  for(int ilayer=0;ilayer<settings1->NLAYERS;ilayer++) {
73  for(int ifold=0;ifold<anita1->NRX_PHI[ilayer];ifold++) {
74  WhereDoesItLeave(posnu,nrf_iceside_eachboresight[2*whichtry][ilayer][ifold],antarctica,
75  rfexit_eachboresight[whichtry][ilayer][ifold]);
76  n_exit2bn_eachboresight[whichtry][ilayer][ifold] = (r_boresights[ilayer][ifold] - rfexit_eachboresight[whichtry][ilayer][ifold]).Unit();
77  }
78  }
79  } // end if we are doing this for each boresight
80 
81  if (settings1->SLAC) {
82  // ray comes out a little earlier because of the slope of the surface.
83  // use law of cosines the get how much "distance" should be cut short
84 
85  double x=sin(settings1->SLACSLOPE*RADDEG)*(settings1->SLACICELENGTH/2.+rfexit[0].Distance(rfexit[whichtry]))/sin(PI/2.+acos(nrf_iceside[2*whichtry].Dot(nsurf_rfexit)));
86 
87  rfexit[whichtry]-=x*nrf_iceside[2*whichtry];
88 
89  if (settings1->BORESIGHTS) {
90  for(int ilayer=0;ilayer<settings1->NLAYERS;ilayer++) {
91  for(int ifold=0;ifold<anita1->NRX_PHI[ilayer];ifold++) {
92 
93  x=sin(settings1->SLACSLOPE*RADDEG)*(settings1->SLACICELENGTH/2.+rfexit_eachboresight[0][ilayer][ifold].Distance(rfexit_eachboresight[whichtry][ilayer][ifold]))/sin(PI/2.+acos(nrf_iceside_eachboresight[2*whichtry][ilayer][ifold].Dot(nsurf_rfexit)));
94 
95  rfexit_eachboresight[whichtry][ilayer][ifold]-=x*nrf_iceside_eachboresight[2*whichtry][ilayer][ifold];
96 
97  n_exit2bn_eachboresight[whichtry][ilayer][ifold] = (r_boresights[ilayer][ifold] - rfexit_eachboresight[whichtry][ilayer][ifold]).Unit();
98  } // end loop over antennas on a layer
99  } // end loop over layers of the payload
100  } // end if we're keeping track of all antenna boresights
101  } // end if we're modeling the slac run
102 }
103 
104 //###########
105 // Ray::WhereDoesItLeave() is defined in ray.hh since it is a statis member function // MS 2/1/2017
106 
107 
108 int Ray::RandomizeSurface(Settings *settings1,Position rfexit_temp,Vector posnu,IceModel *antarctica,double &slopeyangle,int whichtry) {
109 
110  double howmuch=settings1->SLOPEYSIZE;
111  Position nsurf_rfexit_temp;
112 
113  // rotate the surface normal according to the local slope.
114  if (!settings1->SLAC)
115  nsurf_rfexit_temp = antarctica->GetSurfaceNormal(rfexit_temp); // find the normal to the surface taking into account the tilt from the differential heights between neighboring bins
116  else if (settings1->SLAC) { // if we are simulating the slac test, rotate the surface by 10 degrees away from the south pole
117  Vector zaxis(0.,0.,1.);
118  nsurf_rfexit_temp=(rfexit_temp.Unit()).Rotate(-settings1->SLACSLOPE*RADDEG,posnu.Cross(zaxis));
119  }
120 
121  Position nsurf_rfexit_temp_copy=nsurf_rfexit_temp;
122  // tilt local surface based on slopeyness.
123  if (settings1->SLOPEY) {
124 
125  TRandom * rng = getRNG(RNG_SLOPEY);
126  // randomizing surface direction
127 
128  // 0.10=5.4, 0.2=7.4 deg mean
129 
130  // 02/06/07: 0.012=0.84, 0.10=6.78,3.76 deg mean
131 
132  double slopeyness=0;
133  if (whichtry==0) { // only reset the surface slopeyness for the first try an then repeat the same for each subsequent try
134  slopeyx=howmuch*rng->Gaus();
135  slopeyy=howmuch*rng->Gaus();
136  slopeyz=howmuch*rng->Gaus();
137  }
138  Vector ntemp2 = nsurf_rfexit_temp + slopeyx * xaxis
139  + slopeyy * yaxis
140  + slopeyz * zaxis;
141 
142 
143  ntemp2 = ntemp2 / ntemp2.Mag();
144 
145  double rtemp= ntemp2*nsurf_rfexit_temp;
146 
147  if (rtemp<=1) {
148  slopeyness=acos(rtemp);
149  sum_slopeyness+=slopeyness;
150  nsurf_rfexit_temp = ntemp2;
151  }//if
152  else
153  slopeyness=-999;
154 
155  if (settings1->DEBUG) {
156  rtemp=nsurf_rfexit_temp.Mag();
157  if (fabs(rtemp-1.0)>=0.01) {
158  cout << "error: nx,ny,nz_surf="<<nsurf_rfexit_temp<<endl;
159  return 0;
160  }//if
161  }//if
162 
163 
164  // to avoid FP errors, fudge the rare case of going out the poles
165  if (fabs(nsurf_rfexit_temp[2])>=0.99999) { // a hack
166  nsurf_rfexit_temp = Vector(sqrt(1.-0.99999*0.99999-nsurf_rfexit_temp[1]*nsurf_rfexit_temp[1]), nsurf_rfexit_temp[1], 0.99999);
167  }//if
168  }
169  slopeyangle=DEGRAD*acos(nsurf_rfexit_temp*nsurf_rfexit_temp_copy);
170  nsurf_rfexit=nsurf_rfexit_temp;
171  return 1;
172 
173 }//RandomizeSurface
174 
175  // int Ray::GetSurfaceNormal(IceModel *antarctica,Vector posnu,Position *rfexit) {
176  int Ray::GetSurfaceNormal(Settings *settings1,IceModel *antarctica,Vector posnu,double &slopeyangle,int whichtry) {
177 
178  Position rfexit_temp;
179 
180  rfexit_temp=rfexit[whichtry];
181 
182 
183  if (!RandomizeSurface(settings1,rfexit_temp,posnu,antarctica,slopeyangle,whichtry)) {
184 
185  return 0; //can happen only in debug mode
186  }
187 
188 
189 
190 
191 
192 
193  return 1;
194 }
195 
196 
197 int Ray::TraceRay(Settings *settings1,Anita *anita1,int iter,double n_depth) { // iter is which iteration (1 or 2)
198 
199 
200  // use snell's law to get the first guess at the
201  // direction of the rf as it leaves ice surface.
202  // 0th guess was simply radially outward from interaction position
203  // this now takes into account balloon position and surface normal.
204 
205  if (settings1->FIRN) {
206 
207 
208  if (!GetRayIceSide(n_exit2bn[iter-1],nsurf_rfexit,Signal::N_AIR,NFIRN,
209  nrf_iceside[2*iter-1])) { // nrf_iceside[1] is the rf direction in the firn
210 
211  return 0; // reject if TIR.
212  }
213  // This could be throwing away events that the final guess would have kept
214  // Need to look into this and update in the future
215 
216  // use snell's law again to get direction of rf ray emitted from
217  // interaction point. Physically, it is a continuous bending
218  // through the firn but it turns out it obeys Snell's law (Seckel)
219 
220  if (!GetRayIceSide(nrf_iceside[2*iter-1],nsurf_rfexit,NFIRN,n_depth,
221  nrf_iceside[2*iter])) { // nrf_iceside[2] is the rf direction in the ice
222 
223  return 0; // note to self: need to check whether rays are totally internally reflected within ice
224  }
225 
226 
227 
228 
229  // find where the refracted ray leaves.
230  // rejected if the rf leaves beyond the boundary of the
231  // continent. Should never happen.
232 
233  if (settings1->BORESIGHTS) {
234 
235  for(int ilayer=0;ilayer<settings1->NLAYERS;ilayer++) {
236  for(int ifold=0;ifold<anita1->NRX_PHI[ilayer];ifold++) {
237 
238  if (!GetRayIceSide(n_exit2bn_eachboresight[iter-1][ilayer][ifold],nsurf_rfexit,Signal::N_AIR,NFIRN,
239  nrf_iceside_eachboresight[2*iter-1][ilayer][ifold])) // nrf_iceside[1] is the rf direction in the firn
240  return 0; // reject if TIR.
241 
242 
243  // std::cout << "ITER " << iter-1 << " " << (n_exit2bn_eachboresight[iter-1][ilayer][ifold]) << std::endl;
244 
245  // This could be throwing away events that the final guess would have kept
246  // Need to look into this and update in the future
247 
248  // use snell's law again to get direction of rf ray emitted from
249  // interaction point. Physically, it is a continuous bending
250  // through the firn but it turns out it obeys Snell's law (Seckel)
251 
252 
253  if (!GetRayIceSide(nrf_iceside_eachboresight[2*iter-1][ilayer][ifold],nsurf_rfexit,NFIRN,n_depth,
254  nrf_iceside_eachboresight[2*iter][ilayer][ifold])) // nrf_iceside[2] is the rf direction in the ice
255  return 0; // note to self: need to check whether rays are totally internally reflected within ice
256 
257  // find where the refracted ray leaves.
258  // rejected if the rf leaves beyond the boundary of the
259  // continent. Should never happen.
260 
261 
262  } // end phi foldings
263  } // end layers
264  } // end if doing this for all boresights
265  } // end if we are modeling the firn
266 
267  else { // no firn
268 
269  if (!GetRayIceSide(n_exit2bn[iter-1],nsurf_rfexit,Signal::N_AIR,Signal::NICE,
270  nrf_iceside[2*iter-1])) // nrf_iceside[1] is the rf direction in the ice
271  return 0; // reject if TIR.
272  nrf_iceside[2*iter]=nrf_iceside[2*iter-1]; // no firn so the next element is the same
273 
274  if (settings1->BORESIGHTS) {
275 
276  for(int ilayer=0;ilayer<settings1->NLAYERS;ilayer++) {
277  for(int ifold=0;ifold<anita1->NRX_PHI[ilayer];ifold++) {
278 
279  if (!GetRayIceSide(n_exit2bn_eachboresight[iter-1][ilayer][ifold],nsurf_rfexit,Signal::N_AIR,Signal::NICE,
280  nrf_iceside_eachboresight[2*iter-1][ilayer][ifold])) // nrf_iceside[1] is the rf direction in the ice
281  return 0; // reject if TIR.
282  nrf_iceside_eachboresight[2*iter][ilayer][ifold]=nrf_iceside_eachboresight[2*iter-1][ilayer][ifold]; // no firn so the next element is the same
283 
284 
285  } // number of foldings in phi
286  } // number of layers
287  } // end if doing this for all boresights
288 
289 
290 
291  } // end if we are not modeling the firn
292 
293 
294 
295  return 1;
296 }
297  int Ray::GetRayIceSide(const Vector &n_exit2bn,
298  const Vector &nsurf_rfexit,
299  double nexit,
300  double nenter,
301  Vector &nrf2_iceside) {
302 
303  // this function performs snell's law in three dimensions
304 
305  double costh=0;
306 
307  double NRATIO=nexit/nenter;
308 
309  // cout << " INPUT " << n_exit2bn << " " << nsurf_rfexit << " " << nexit << " " << nenter << endl;
310 
311  costh=(n_exit2bn*nsurf_rfexit)/(n_exit2bn.Mag() * nsurf_rfexit.Mag()); // cos(theta) of the transmission angle
312 
313  if (costh<0) {
314  // cout << "returning 0. inu is " << inu << "\n";
315  return 0;
316 
317  }
318  double sinth=sqrt(1 - costh*costh);
319 
320  // double sinth_i=nexit*sinth/nenter;
321 
322  // double angle=asin(sinth)-asin(sinth_i);
323 
324 
325  // cout << "sinth, sinth_i are " << sinth << " " << sinth_i << "\n";
326  // cout << "th, th_i are " << asin(sinth)*DEGRAD << " " << asin(sinth_i)*DEGRAD << "\n";
327  // cout << "angle is " << angle*DEGRAD << "\n";
328 
329  // nrf2_iceside=n_exit2rx.Rotate(angle,n_exit2rx.Cross(nsurf_rfexit));
330 
331 
332  double factor=NRATIO*costh-sqrt(1-(NRATIO*sinth*NRATIO*sinth));
333 
334 
335  nrf2_iceside = -factor*nsurf_rfexit + NRATIO*n_exit2bn;
336  nrf2_iceside = nrf2_iceside.Unit(); // normalize
337 
338 
339 
340 
341 
342  return 1;
343 }//GetRayIceSide
344 
double Distance(const Position &second) const
Returns chord distance (direct distance between two vectors)
Definition: position.cc:37
Reads in and stores input settings for the run.
Definition: Settings.h:37
This class is a 3-vector that represents a position on the Earth&#39;s surface.
Definition: position.hh:26
Contains everything about positions within payload and signals it sees for each event, in both the trigger and signal paths.
Definition: anita.hh:32
static const int NLAYERS_MAX
max number of layers (in smex design, it&#39;s 4)
Definition: anita.hh:59
This class represents a three-vector. Operators are overloaded to provide for the familiar operations...
Definition: vector.hh:27
static const int NPHI_MAX
max number of antennas around in phi (in smex, 16)
Definition: anita.hh:61
int NRX_PHI[NLAYERS_MAX]
number of antennas around in each layer. (radians)
Definition: anita.hh:69
Ice thicknesses and water depth.
Definition: icemodel.hh:103