/RTFunctions.cc
Go to the documentation of this file.
1 #include "RTFunctions.h"
2 
3 #include <utl/config.h>
4 
5 #include <utl/Photon.h>
6 #include <utl/Point.h>
7 #include <utl/Vector.h>
8 #include <utl/CoordinateSystemPtr.h>
9 #include <utl/RandomEngine.h>
10 #include <utl/MathConstants.h>
11 #include <utl/AugerException.h>
12 #include <utl/ErrorLogger.h>
13 #include <utl/AugerUnits.h>
14 
15 #include <CLHEP/Random/Randomize.h>
16 
17 #include <iostream>
18 #include <vector>
19 #include <utility>
20 
21 
22 using namespace utl;
23 using namespace std;
24 
25 using CLHEP::RandFlat;
26 using CLHEP::RandGauss;
27 
28 namespace TelescopeSimulatorKG2 {
29 
30  namespace RTFunctions {
31 
32  void
33  Reflection(const utl::Photon& photonIn,
34  const Vector& normal,
35  utl::Photon& photonOut)
36  {
37  //This asumes that normal is normalized check?
38  photonOut = photonIn;
39  const Vector& nIn = photonIn.GetDirection();
40  const double dot = nIn * normal; // projection
41  photonOut.SetDirection(nIn - 2. * dot * normal); // -> new direction
42  }
43 
44  //a phenomenological description of the absorption by the dust layer on the outside of the filter
45  //the weight of the photon is reduced by the absorption factor set in TelescopeSimulatorKG2.xml.in
46  //for 10% absorption, set FilterDustAbsorptionOutside = 0.1
47  //if not specified, the default value is 0.0
48  void
49  Absorption(const utl::Photon& photonIn,
50  const double filterAbsorptionFactor,
51  utl::Photon& photonOut)
52  {
53  const double weightIn = photonIn.GetWeight();
54  const double weightOut = weightIn * ( 1.0 - filterAbsorptionFactor);
55  photonOut = photonIn;
56  photonOut.SetWeight(weightOut);
57  }
58 
59  //a phenomenological description of the absorption by the dust layer on the mirror, default: no absorption
60  //the weight of the photon is reduced by an elevation-dependent absorption factor set in TelescopeSimulatorKG2.xml.in
61  //for e.g. 3% absorption at the top of the mirror, set MirrorAbsorptionTop = 0.03
62  //for e.g. 9% absorption at the bottom of the mirror, set MirrorAbsorptionBot = 0.03
63  void
64  Absorption(const utl::Photon& photonIn,
65  const double mirrorAbsorptionFactorTop,
66  const double mirrorAbsorptionFactorBot,
67  const double verticalPosOnMirror,
68  utl::Photon& photonOut,
69  const double mirrorSize)
70  {
71  //con't linear interpolation between absorption factors at the top and bottom of the mirror
72  double mirrorInterpolWeight = (verticalPosOnMirror + mirrorSize) / (2 * mirrorSize); //1 for top of the mirror, 0 for bottom
73  double absorptionFactor = (mirrorInterpolWeight * mirrorAbsorptionFactorTop) + ((1 - mirrorInterpolWeight) * mirrorAbsorptionFactorBot);
74  const double weightIn = photonIn.GetWeight();
75  const double weightOut = weightIn * (1.0 - absorptionFactor);
76  photonOut = photonIn;
77  photonOut.SetWeight(weightOut);
78  }
79 
80  double
81  Plane(const utl::Point& point,
82  const utl::Vector& normal,
83  const utl::Photon& photonIn,
84  utl::Photon& photonOut)
85  {
86  photonOut = photonIn;
87  const Vector& nIn = photonIn.GetDirection();
88  const Point& pIn = photonIn.GetPosition();
89 
90  double b = normal * nIn;
91  double a = (point - pIn) * normal;
92 
93  if (b==0)
94  return (0);
95 
96  a /= b;
97 
98  photonOut.SetPosition(pIn + a * nIn);
99  return (a);
100  }
101 
102 
103  int
104  Refraction(const double n12,
105  const utl::Photon& photonIn,
106  const Vector& normal,
107  PhotonList& photonsOut)
108  {
109 
110  const Vector& nIn = photonIn.GetDirection();
111 
112 
113  // Snell's law ------------------------------------
114  const double cosTheta_in = nIn * normal; // projection on normal
115 
116  Vector projOnSurface = nIn - cosTheta_in * normal; // projected direction on surface
117 
118  projOnSurface *= n12; // take refraction into account -> outgoing
119 
120  double sin2theta_out = projOnSurface.GetMag2();
121 
122  // the reflected photon
123  Photon photonReflected(photonIn);
124  photonReflected.SetDirection(nIn - 2. * cosTheta_in * normal); // -> new direction
125 
126 
127  if (sin2theta_out >= 1) { // TOTAL INTERNAL REFLECTION
128  photonsOut.push_back(photonReflected);
129  return 1;
130  }
131 
132  // check direction of incidence
133  double cosTheta_out;
134  if (cosTheta_in > 0)
135  cosTheta_out = +sqrt(1. - sin2theta_out);
136  else
137  cosTheta_out = -sqrt(1. - sin2theta_out); // ray coming out of media ! should not happen
138 
139 
140  // Fresnel's law ----------------------------------
141 
142  // T = t^2 transmisivity
143  // R = r^2 reflectivity
144  // R_unpolarized = 1/2 * (R_perp + R_par)
145  // T_unpolarized = 1/2 * (T_perp + T_par)
146  //
147  // because R and T gives the ratio of the energy flux per unit area (intensity),
148  // one has to take into acount the difference between theta1 and theta2 !
149  // 1. = R + [n2/n1 * cos(theta2)/cos(theta1)] * T
150 
151  double fact = 1.;
152  if (cosTheta_in)
153  fact = 1. / n12 * cosTheta_out / cosTheta_in;
154 
155  const double T_par = pow(2. * n12 * cosTheta_in / (n12 * cosTheta_out + cosTheta_in), 2);
156  const double T_perp = pow(2. * n12 * cosTheta_in / (n12 * cosTheta_in + cosTheta_out), 2);
157  const double T = fact * .5 * (T_par + T_perp); // unpolarized light
158 
159  const double weightIn = photonIn.GetWeight();
160 
161  Photon photonRefracted(photonIn);
162  photonRefracted.SetDirection(projOnSurface + cosTheta_out*normal);
163  photonRefracted.SetWeight(weightIn * T);
164  photonsOut.push_back(photonRefracted);
165 
166  photonReflected.SetWeight(weightIn * (1 - T));
167  photonsOut.push_back(photonReflected);
168 
169  return 2;
170  }
171 
172 
173 
174  /* calculate the point and the normal vector on a sphere, where
175  the photon photonIn hits it.
176 
177  -----
178  origin: center of sphere
179  radius: radius
180  photonIn: incoming photon
181  photonOut: photon hitting the sphere
182  normal: surface normal on sphere at photonOut.GetPosition()
183  *****
184  */
185 
186  bool
187  Sphere(const Point& origin,
188  const double radius,
189  const utl::Photon& photonIn,
190  IntersectionList& intersection)
191  {
192  intersection.clear();
193 
194  const Vector& nIn = photonIn.GetDirection();
195  const Point& pIn = photonIn.GetPosition();
196 
197  const Vector pointToOrigin = pIn - origin;
198  const double dist2 = pointToOrigin.GetMag2();
199 
200  const double projection = pointToOrigin * nIn; // project nIn on radial Vector pointToOrigin
201  double delta = projection*projection + radius*radius - dist2;
202 
203  if (delta < 0)
204  return false; // no solution
205 
206  if (delta == 0) {
207  Photon photonOut(photonIn);
208  photonOut.SetPosition(pIn - projection * nIn);
209  Vector normal = origin - photonOut.GetPosition();
210  normal.Normalize();
211  intersection.push_back(pair<Photon,Vector>(photonOut, normal));
212  }
213  else {
214 
215  delta = sqrt(delta);
216 
217  const double move1 = -projection - delta;
218  const double move2 = -projection + delta;
219 
220  Photon photonOut1(photonIn);
221  photonOut1.SetPosition(pIn + min(move1, move2) * nIn);
222  Vector normal1 = origin - photonOut1.GetPosition();
223  normal1.Normalize();
224  intersection.push_back(pair<Photon,Vector>(photonOut1, normal1));
225 
226  Photon photonOut2(photonIn);
227  photonOut2.SetPosition(pIn + max(move1, move2) * nIn);
228  Vector normal2 = origin - photonOut2.GetPosition();
229  normal2.Normalize();
230  intersection.push_back(pair<Photon,Vector>(photonOut2, normal2));
231  }
232 
233  return true;
234  }
235 
236 
237 
238  Vector
239  TorusNormal(const utl::Point& origin,
240  const utl::Vector& inwards,
241  const utl::Point& point,
242  const double torusRadius,
243  const double tubeRadius)
244  {
245  const double R = torusRadius;
246  const double r = tubeRadius;
247  const Vector p = point - origin;
248  // p = (x,y,z), inwards = (0,0,-1)
249  // (df/dx,df/dy,df/dz) = 4 * p * (p*p + R*R - r*r) - 8 * R*R * (x,y,0)
250  const Vector n = 4 * p * (p * p + R * R - r * r) - 8 * R * R * (p - inwards * (inwards * p));
251  // normalize and point into the torus (out of the telescope)
252  return -n / n.GetMag();
253  }
254 
255 
256 
257 
258  //bool
259  void
260  Torus(const utl::Point& origin,
261  const utl::Vector& inwards,
262  const double torusRadius,
263  const double tubeRadius,
264  const utl::Photon& photonIn,
265  IntersectionList& intersections)
266  {
267  intersections.clear();
268 
269 
270  /* formulas calculated analog to pdf by Max Wagner mwagner@digipen.edu
271  * but with torus equation
272  * R*R - 2 * R * sqrt(x*x + y*y) + x*x + y*y + z*z - r*r = 0
273  * eliminating the square root leads to:
274  * f(x,y,z) = pow(R*R - r*r + x*x + y*y + z*z , 2) - 4 * R*R * (x*x + y*y) = 0
275  * intersections with photon (x,y,z) = p + t * d
276  * leads to the quartic equation
277  * a4 * t*t*t*t + a3 * t*t*t + a2 * t*t + a1 * t + a0 = 0
278  * solved below
279  */
280 
281  const double R = torusRadius;
282  const double r = tubeRadius;
283 
284  const Vector& d = photonIn.GetDirection();
285  const Point& inPos = photonIn.GetPosition();
286  const Vector p = inPos - origin;
287 
288  const double pd = p * d;
289  const double dd = 1.; // = d*d, and d is Normalized
290  const double pp = p * p;
291 
292  const double dz = d * inwards; // z-component of d
293  const double dx2dy2 = 1. - dz * dz;
294  const double pz = p * inwards; // z-component of p
295  const double px2py2 = p.GetMag2() - pz * pz;
296 
297  const double r2 = r * r;
298  const double R2 = R * R;
299  const double pprrRR = pp - r2 + R2;
300 
301  const double a4 = 1; // = dd * dd;
302  const double a3 = 4 * dd * pd; // dd = 1
303  const double a2 = 4 * pd * pd + 2 * dd * pprrRR - 4 * R2 * dx2dy2;
304  const double a1 = 4 * pd * pprrRR - 8 * R2 * (pd - dz * pz);
305  const double a0 = pprrRR * pprrRR - 4 * R2 * px2py2;
306 
307  vector<double> roots;
308  Quartic(a0, a1, a2, a3, a4, roots);
309 
310  for (vector<double>::const_iterator iRoot = roots.begin();
311  iRoot != roots.end();
312  ++iRoot) {
313  const Point pInt = inPos + (*iRoot) * d;
314  Photon photonOut(photonIn);
315  photonOut.SetPosition(pInt);
316  intersections.push_back(pair<Photon,Vector>(photonOut, TorusNormal(origin, inwards, pInt, torusRadius, tubeRadius)));
317  }
318 
319  } // ----------------
320 
321 
322  void
323  Cubic(const double a0,
324  const double a1,
325  const double a2,
326  const double a3,
327  vector<double>& roots)
328  {
329  if (a3 == 0) { // only check the extreme case
330  // x^2 + a1/a2 * x + a0/a2 = 0
331  const double Phalve = a1 / (2 * a2);
332  const double Phalve2_Q = Phalve * Phalve - a0 / a2;
333  if (Phalve2_Q < 0)
334  return;
335  const double sqrtPhalve2_Q = sqrt(Phalve2_Q);
336  roots.push_back(-Phalve + sqrtPhalve2_Q);
337  if (Phalve2_Q > 0)
338  roots.push_back(-Phalve - sqrtPhalve2_Q);
339  return;
340  }
341 
342  //if (a2==0) {
343  // quadratic eq after substiting u = x^2
344  //exit(1);
345  //}
346 
347 
348  // depressed cubic
349  // v^3 + P v + Q = 0
350 
351 
352  const double P = (3 * a3 * a1 - a2 * a2) / (3 * a3 * a3);
353  const double Q = (2 * a2 * a2 * a2 - 9 * a3 * a2 * a1 + 27 * a3 * a3 * a0) / (27 * a3 * a3 * a3);
354 
355 
356  const double trans = - a2 / (3 * a3);
357 
358  if (fabs(P) < 1e-11) {
359 
360  roots.push_back(trans - cbrt(Q));
361 
362  } else if (fabs(Q) < 1e-11) {
363 
364  // one solution is v=0, take it and do nothing
365  roots.push_back(trans);
366 
367  } else {
368 
369  const double PPP4QQ27 = 4 * P * P * P + 27 * Q * Q;
370  if (fabs(PPP4QQ27) < 1e-11) {
371 
372  roots.push_back(trans + 3 * Q / P);
373  roots.push_back(trans - 3 * Q / (2 * P));
374 
375  } else {
376 
377  // Cardano's method
378 
379  const double PPP27 = P * P * P / 27;
380  const double QQ4PPP27 = Q * Q / 4 + PPP27;
381 
382  if ( QQ4PPP27 >= 0) {
383 
384  const double sqrtQQ4PPP27 = sqrt(QQ4PPP27);
385 
386  roots.push_back(trans + cbrt(-Q / 2 + sqrtQQ4PPP27) + cbrt(-Q / 2 - sqrtQQ4PPP27));
387 
388  } else {
389 
390  if (PPP27 >= 0) {
391  cout << " THIS CANNOT HAPPEN " << endl;
392  exit(1);
393  }
394 
395  const double sqrt_PPP27 = sqrt( -PPP27 ); // length
396  const double mag = cbrt(sqrt_PPP27);
397 
398  const double sqrt_QQ4PPP27 = sqrt(-QQ4PPP27);
399  const double phi = atan2(sqrt_QQ4PPP27, -Q / 2);
400 
401  // cout << " THIS CANNOT HAPPEND PHI=" << phi << " sqrt_PPP27=" << sqrt_PPP27 << " sqrt_QQ4PPP27=" << sqrt_QQ4PPP27 << " -Q/2=" << -Q/2 << endl;
402 
403 
404  roots.push_back(trans + 2 * mag * cos(phi / 3));
405  roots.push_back(trans + 2 * mag * cos(phi / 3 + kPi * 2 / 3));
406  roots.push_back(trans + 2 * mag * cos(phi / 3 - kPi * 2 / 3));
407 
408  }
409  }
410  }
411  }
412 
413 
414  void
415  Quartic(const double a0,
416  const double a1,
417  const double a2,
418  const double a3,
419  const double a4,
420  vector<double>& roots)
421  {
422  /* solve quartic function according to: http://en.wikipedia.org/wiki/Quartic_function
423  using
424 
425  a4 is A
426  a3 is B
427  a2 is C
428  a1 is D
429  a0 is E
430 
431  convert to depressed quartic with x = u - a3/(4*a4)
432 
433  const double alpha = -3./8. * a3*a3 / (a4*a4) + a2 / a4;
434  const double beta = a3*a3*a3 / (8 * a4*a4*a4) - a3*a2 / (2 * a4*a4) + a1/a4;
435  const double gamma = -3 * a3*a3*a3*a3 / (256 * a4*a4*a4*a4) + a2*a3*a3 / (16 * a4*a4*a4) - a3*a1 / (4 * a4*a4) + a0 / a4;
436 
437 
438  where: x = u - a3 / (4*a4)
439  u^4 + alpha u^2 + beta u + gamma = 0
440 
441  [[ a4 = 1 leads to simplified coefficients ]]
442 
443  */
444 
445  if (a4 == 0) {
446  Cubic(a0, a1, a2, a3, roots);
447  return;
448  }
449 
450  const double alpha = -3. / 8. * a3 * a3 / (a4 * a4) + a2 / a4;
451  const double beta = a3 * a3 * a3 / (8 * a4 * a4 * a4) - a3 * a2 / (2 * a4 * a4) + a1 / a4;
452  const double gamma = -3 * a3 * a3 * a3 * a3 / (256 * a4 * a4 * a4 * a4) + a2 * a3 * a3 / (16 * a4 * a4 * a4) - a3 * a1 / (4 * a4 * a4) + a0 / a4;
453 
454  const double subst = - a3 / (4 * a4);
455 
456  if (fabs(beta) < 1.e-11) {
457 
458  // boils down to quadratic equation, after: t = u^2
459  //
460  // t^2 + alpha t + gamma = 0
461  //
462  // with x: = sqrt(t) - a3 / (4a4)
463  //
464 
465  const double tmp = alpha * alpha / 4 - gamma;
466 
467  if (tmp < 0)
468  return;
469 
470  const double sTmp = sqrt(tmp);
471  const double tmp2 = -alpha / 2 + sTmp;
472  const double tmp3 = -alpha / 2 - sTmp;
473 
474  if (tmp2 >= 0) {
475 
476  const double sTmp2 = sqrt(tmp2);
477  const double x1 = subst + sTmp2;
478  roots.push_back(x1);
479 
480  if (sTmp2 > 0) {
481  const double x2 = subst - sTmp2;
482  roots.push_back(x2);
483  }
484  }
485 
486  if (tmp3 >= 0 && sTmp != 0) {
487 
488  const double sTmp3 = sqrt(tmp3);
489  const double x3 = subst + sTmp3;
490  roots.push_back(x3);
491 
492  if (sTmp3 > 0) {
493  const double x4 = subst - sTmp3;
494  roots.push_back(x4);
495  }
496  }
497 
498  return;
499 
500  } // if beta==0
501 
502 
503  // solve the cubic equation in y
504  const double b0 = alpha * alpha * alpha / 2. - alpha * gamma / 2. - beta * beta / 8.;
505  const double b1 = 2 * alpha * alpha - gamma;
506  const double b2 = alpha * 5./2;
507  const double b3 = 1.;
508 
509  vector<double> rootsC;
510  Cubic(b0, b1, b2, b3, rootsC);
511 
512  if (rootsC.size() == 0)
513  return;
514 
515  const double y = rootsC[0]; // any solution is fine, take first one
516  const double alpha2y = alpha + 2 * y;
517 
518  if (alpha2y <- 1) {
519  cout << "THIS SHOULD NOT HAPPEN!!!!!!!!!!!!" << endl;
520  exit(5);
521  }
522 
523  const double W = alpha2y < 0 ? 0 : sqrt(alpha2y);
524 
525 
526  const double tmp1 = -(3 * alpha + 2 * y + 2 * beta / W);
527  const double tmp2 = -(3 * alpha + 2 * y - 2 * beta / W);
528 
529  if (tmp1 < 0 && tmp2 < 0)
530  return;
531 
532 
533  if (tmp1 >= 0) {
534 
535  const double sTmp1 = sqrt(tmp1);
536 
537  const double x1 = subst + (W - sTmp1 ) / 2.;
538  roots.push_back(x1);
539 
540  if (sTmp1 > 0) {
541  const double x2 = subst + (W + sTmp1) / 2.;
542  roots.push_back(x2);
543  }
544  }
545 
546  if (tmp2 >= 0) {
547 
548  const double sTmp2 = sqrt(tmp2);
549 
550  const double x3 = subst + (-W - sTmp2) / 2.;
551  roots.push_back(x3);
552 
553  if (sTmp2 > 0) {
554  const double x4 = subst + (-W + sTmp2) / 2.;
555  roots.push_back(x4);
556  }
557  }
558  }
559 
560 
561 
562  Vector
564  const Vector& normalIn,
565  const double sigma_alpha)
566  {
567  if (sigma_alpha == 0) {
568  return normalIn; // nothing to do
569  }
570 
571  // first create a reference system with normalIn as z normal
572  const CoordinateSystemPtr internalCS = normalIn.GetCoordinateSystem();
573  const double phiIn = normalIn.GetPhi (internalCS);
574  const double thetaIn = normalIn.GetTheta (internalCS);
575  const CoordinateSystemPtr tmpCS = CoordinateSystem::RotationZ (phiIn, internalCS);
576  const CoordinateSystemPtr normalCS = CoordinateSystem::RotationY (thetaIn, tmpCS);
577 
578  const double phi = RandFlat::shoot(&rndm.GetEngine(), 0., 2. * kPi);
579  const double sinPhi = sin(phi);
580  const double cosPhi = cos(phi);
581 
582  const double theta = RandGauss::shoot(&rndm.GetEngine(), 0., sigma_alpha);
583  const double sinTheta = sin(theta);
584  const double cosTheta = cos(theta);
585 
586  const double unit_x = sinTheta * cosPhi;
587  const double unit_y = sinTheta * sinPhi;
588  const double unit_z = cosTheta;
589 
590  return Vector (unit_x, unit_y, unit_z, normalCS);
591  } // end of RandomNormal
592 
593  /*
594 
595  Code equivalent to geant4 optical boundary process for unified model:
596 
597  return facet normal of rough surface, a ray rayIn will hit
598 
599  This function code alpha to a random value taken from the
600  distribution p(alpha) = g(alpha; 0, sigma_alpha)*std::sin(alpha),
601  for alpha > 0 and alpha < 90, where g(alpha; 0, sigma_alpha)
602  is a gaussian distribution with mean 0 and standard deviation
603  sigma_alpha.
604  */
605 
606  Vector
608  const Vector& normalIn,
609  const double sigma_alpha,
610  const Vector& rayIn) {
611 
612  if (sigma_alpha == 0) {
613  return normalIn; // nothing to do
614  }
615 
616  // first create a reference system with normalIn as z normal
617  const CoordinateSystemPtr internalCS = normalIn.GetCoordinateSystem();
618  const double phiIn = normalIn.GetPhi (internalCS);
619  const double thetaIn = normalIn.GetTheta (internalCS);
620  const CoordinateSystemPtr tmpCS = CoordinateSystem::RotationZ (phiIn, internalCS);
621  const CoordinateSystemPtr normalCS = CoordinateSystem::RotationY (thetaIn, tmpCS);
622 
623 
624  const double f_max = std::min(1., 4. * sigma_alpha);
625 
626  const double phi = RandFlat::shoot (&rndm.GetEngine(), 0., 2. * kPi);
627  const double sinPhi = sin(phi);
628  const double cosPhi = cos(phi);
629 
630  Vector facetNormal;
631 
632  do {
633 
634  double alpha = 0;
635  do {
636  alpha = RandGauss::shoot (&rndm.GetEngine(), 0., sigma_alpha);
637  } while (RandFlat::shoot (&rndm.GetEngine(), 0., f_max) > sin(alpha) ||
638  alpha >= kPi / 2.);
639 
640  double sinAlpha = sin(alpha);
641  double cosAlpha = cos(alpha);
642 
643  double unit_x = sinAlpha * cosPhi;
644  double unit_y = sinAlpha * sinPhi;
645  double unit_z = cosAlpha;
646 
647  facetNormal = Vector (unit_x, unit_y, unit_z, normalCS);
648 
649  } while (rayIn * facetNormal >= 0.0);
650 
651  return facetNormal;
652  }//end of randomfacet
653 
654 
655  /* put code for simulation of lambertian distribution here
656  */
657 
658  Vector
660  const Vector& rayIn,
661  const Vector& normal,
662  const double amountOfStrayLight,
663  const double MaxTheta) {
664 
665  double strayOrNot = RandFlat::shoot(&rndm.GetEngine(), 0., 1.);
666 
667  if (strayOrNot > amountOfStrayLight) {
668  return rayIn; // nothing to do
669  }
670  else {
671 
672  // first create a reference system with normal as z normal
673  const CoordinateSystemPtr internalCS = normal.GetCoordinateSystem();
674  const double phiIn = normal.GetPhi (internalCS);
675  const double thetaIn = normal.GetTheta (internalCS);
676  const CoordinateSystemPtr tmpCS = CoordinateSystem::RotationZ (phiIn, internalCS);
677  const CoordinateSystemPtr normalCS = CoordinateSystem::RotationY (thetaIn, tmpCS);
678 
679  // code taken from DrumPhotonGenerator.cc
680 
681  // values from DrumPhotonGenerator.xml
682  const double MinTheta = 0. * degree;
683  //const double MaxTheta = 25.*degree;
684  const double MinPhi = 0. * degree;
685  const double MaxPhi = 360. * degree;
686 
687  // Generating random direction on the diaphragm
688  double phi = RandFlat::shoot(&rndm.GetEngine(),
689  MinPhi, MaxPhi);
690  double NCos = 1.; // = 1 is lambertian
691  // = 0 would be isotropic according to DrumPhotonGenerator
692  double theta_1 = std::pow(cos(MinTheta), NCos + 1);
693  double theta_2 = std::pow(cos(MaxTheta), NCos + 1);
694  // th goes like cos^NCOS * d(cos)
695  double tmp = (theta_2 - theta_1) * RandFlat::shoot(&rndm.GetEngine(), 0., 1.) + theta_1;
696 
697  double theta;
698  if (NCos == 0) theta = acos(tmp);
699  else if (NCos == 1) theta = acos(sqrt(tmp));
700  else theta = acos(exp(log(tmp) / (1. + NCos) ) );
701 
702  Vector newDir (1., theta, phi, normalCS, Vector::kSpherical);
703  return newDir;
704  // end code from DrumPhotonGenerator.cc
705  }
706 
707  }//end of lambertdiffusion
708 
709  Vector
711  const Vector& specularDir,
712  const utl::TabulatedFunction* mirrorDiffusionTop,
713  const utl::TabulatedFunction* mirrorDiffusionBot,
714  const double verticalPosOnMirror) {
715 
716  // only do diffusion if diffusion function is given in xml aka the TabulatedFunction is not NULL
717  utl::TabulatedFunction cumuCurveTop = *mirrorDiffusionTop;
718  utl::TabulatedFunction cumuCurveBot = *mirrorDiffusionBot;
719 
720  double value = RandFlat::shoot(&rndm.GetEngine(), 0., 1.);
721  //angles from specular direction (--> z-axis of spherical coordinate system)
722  double theta = 0.;
723  double phi = 0.;
724  const double peripheralRegion = 18 * deg; //upper and lower periphery of mirror for which distribution was measured
725 
726  //photon hits central region of the mirror
727  //con't linear interpolation btw. scattering angles (from spec. dir.) using cumulative distr.
728  if ((verticalPosOnMirror < peripheralRegion) && (verticalPosOnMirror > -1 * peripheralRegion)) {
729  float mirrorInterpolWeight = (verticalPosOnMirror+peripheralRegion) / (2 * peripheralRegion); //1 for top of the mirror, 0 for bottom
730  theta = (mirrorInterpolWeight * cumuCurveTop.Y(value)) + ((1 - mirrorInterpolWeight) * cumuCurveBot.Y(value));
731  }
732 
733  //upper part of the mirror, using the distr. measured for the upper mirror region
734  else if (verticalPosOnMirror > peripheralRegion)
735  theta = cumuCurveTop.Y(value);
736 
737  //lower part of the mirror, using the distr. measured for the lower mirror region
738  else if (verticalPosOnMirror < -1 * peripheralRegion)
739  theta = cumuCurveBot.Y(value);
740 
741  // calculate new photon direction
742 
743  // get coordinate system with specular direction as z axis
744  const CoordinateSystemPtr internalCS = specularDir.GetCoordinateSystem();
745  const double phiIn = specularDir.GetPhi (internalCS);
746  const double thetaIn = specularDir.GetTheta (internalCS);
747  const CoordinateSystemPtr tmpCS = CoordinateSystem::RotationZ (phiIn, internalCS);
748  const CoordinateSystemPtr specularCS = CoordinateSystem::RotationY (thetaIn, tmpCS);
749 
750  //random phi direction
751  phi = RandFlat::shoot(&rndm.GetEngine(), 0, 2. * kPi);
752 
753  Vector newDir (1., theta, phi, specularCS, Vector::kSpherical);
754  return newDir;
755 
756  } //end of MirrorDiffusion
757 
758  } // namespace RTFunctions
759 
760 } // namesapce TelescopeSimulatorKG2
std::vector< PhotonNormalPair > IntersectionList
Definition: /RTFunctions.h:47
double Plane(const utl::Point &point, const utl::Vector &normal, const utl::Photon &photonIn, utl::Photon &photonOut)
Definition: RTFunctions.cc:41
void Normalize()
Definition: Vector.h:64
Point object.
Definition: Point.h:32
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
RandomEngineType & GetEngine()
Definition: RandomEngine.h:32
int Reflection(const utl::Photon &photonIn, const Vector &normal, utl::Photon &photonOut)
Definition: RTFunctions.cc:29
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
Definition: BasicVector.h:234
Class to hold collection (x,y) points and provide interpolation between them.
double GetWeight() const
weight assigned to the photon
Definition: Photon.h:21
void Cubic(const double a0, const double a1, const double a2, const double a3, vector< double > &roots)
double pow(const double x, const unsigned int i)
int exit
Definition: dump1090.h:237
double GetMag() const
Definition: Vector.h:58
void SetPosition(const utl::Point &p)
Definition: Photon.h:33
constexpr double deg
Definition: AugerUnits.h:140
Vector TorusNormal(const utl::Point &origin, const utl::Vector &inwards, const utl::Point &point, const double torusRadius, const double tubeRadius)
int Sphere(const Point &origin, const double radius, const utl::Photon &photonIn, IntersectionList &intersection)
Definition: RTFunctions.cc:142
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define max(a, b)
Wraps the random number engine used to generate distributions.
Definition: RandomEngine.h:27
constexpr double kPi
Definition: MathConstants.h:24
Vector MirrorDiffusion(utl::RandomEngine &rndm, const Vector &specularDir, const utl::TabulatedFunction *mirrorDiffusionTop, const utl::TabulatedFunction *mirrorDiffusionBot, const double verticalPosOnMirror)
void Quartic(const double a0, const double a1, const double a2, const double a3, const double a4, vector< double > &roots)
static Policy::type RotationY(const double angle, const CoordinateSystemPtr &theCS)
Construct from rotation about Y axis.
constexpr double degree
static Policy::type RotationZ(const double angle, const CoordinateSystemPtr &theCS)
Construct from rotation about Z axis.
void SetWeight(const double w)
source of the photons. Should use Eye::LightSource enum types
Definition: Photon.h:31
static const CSpherical kSpherical
Definition: BasicVector.h:335
const utl::Vector & GetDirection() const
Definition: Photon.h:26
int Refraction(const double n12, const utl::Photon &photonIn, const Vector &normal, PhotonList &photonsOut)
Definition: RTFunctions.cc:61
Vector LambertDiffusion(utl::RandomEngine &rndm, const Vector &rayIn, const Vector &normal, const double amountOfStrayLight, const double MaxTheta)
Vector object.
Definition: Vector.h:30
std::vector< utl::Photon > PhotonList
Definition: /RTFunctions.h:35
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
Vector RandomFacet(utl::RandomEngine &rndm, const Vector &normalIn, const double sigma_alpha, const Vector &rayIn)
void Torus(const utl::Point &origin, const utl::Vector &inwards, const double torusRadius, const double tubeRadius, const utl::Photon &photonIn, IntersectionList &intersections)
void SetDirection(const utl::Vector &v)
Definition: Photon.h:34
Vector RandomNormal(utl::RandomEngine &rndm, const Vector &normalIn, double sigma_alpha, const Vector &rayIn)
Definition: RTFunctions.cc:210
#define Q
double GetMag2() const
Definition: Vector.h:61
const utl::Point & GetPosition() const
Definition: Photon.h:25

, generated on Tue Sep 26 2023.