3 #include <utl/config.h>
5 #include <utl/Photon.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>
15 #include <CLHEP/Random/Randomize.h>
25 using CLHEP::RandFlat;
26 using CLHEP::RandGauss;
28 namespace TelescopeSimulatorKG2 {
30 namespace RTFunctions {
40 const double dot = nIn * normal;
50 const double filterAbsorptionFactor,
53 const double weightIn = photonIn.
GetWeight();
54 const double weightOut = weightIn * ( 1.0 - filterAbsorptionFactor);
65 const double mirrorAbsorptionFactorTop,
66 const double mirrorAbsorptionFactorBot,
67 const double verticalPosOnMirror,
69 const double mirrorSize)
72 double mirrorInterpolWeight = (verticalPosOnMirror + mirrorSize) / (2 * mirrorSize);
73 double absorptionFactor = (mirrorInterpolWeight * mirrorAbsorptionFactorTop) + ((1 - mirrorInterpolWeight) * mirrorAbsorptionFactorBot);
74 const double weightIn = photonIn.
GetWeight();
75 const double weightOut = weightIn * (1.0 - absorptionFactor);
90 double b = normal * nIn;
91 double a = (point - pIn) * normal;
114 const double cosTheta_in = nIn * normal;
116 Vector projOnSurface = nIn - cosTheta_in * normal;
118 projOnSurface *= n12;
120 double sin2theta_out = projOnSurface.
GetMag2();
123 Photon photonReflected(photonIn);
124 photonReflected.
SetDirection(nIn - 2. * cosTheta_in * normal);
127 if (sin2theta_out >= 1) {
128 photonsOut.push_back(photonReflected);
135 cosTheta_out = +
sqrt(1. - sin2theta_out);
137 cosTheta_out = -
sqrt(1. - sin2theta_out);
153 fact = 1. / n12 * cosTheta_out / cosTheta_in;
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);
159 const double weightIn = photonIn.
GetWeight();
161 Photon photonRefracted(photonIn);
162 photonRefracted.
SetDirection(projOnSurface + cosTheta_out*normal);
164 photonsOut.push_back(photonRefracted);
166 photonReflected.
SetWeight(weightIn * (1 - T));
167 photonsOut.push_back(photonReflected);
192 intersection.clear();
197 const Vector pointToOrigin = pIn - origin;
198 const double dist2 = pointToOrigin.
GetMag2();
200 const double projection = pointToOrigin * nIn;
201 double delta = projection*projection + radius*radius - dist2;
207 Photon photonOut(photonIn);
211 intersection.push_back(pair<Photon,Vector>(photonOut, normal));
217 const double move1 = -projection - delta;
218 const double move2 = -projection + delta;
220 Photon photonOut1(photonIn);
221 photonOut1.
SetPosition(pIn + min(move1, move2) * nIn);
224 intersection.push_back(pair<Photon,Vector>(photonOut1, normal1));
226 Photon photonOut2(photonIn);
230 intersection.push_back(pair<Photon,Vector>(photonOut2, normal2));
242 const double torusRadius,
243 const double tubeRadius)
245 const double R = torusRadius;
246 const double r = tubeRadius;
247 const Vector p = point - origin;
250 const Vector n = 4 * p * (p * p + R * R - r * r) - 8 * R * R * (p - inwards * (inwards * p));
262 const double torusRadius,
263 const double tubeRadius,
267 intersections.clear();
281 const double R = torusRadius;
282 const double r = tubeRadius;
286 const Vector p = inPos - origin;
288 const double pd = p * d;
289 const double dd = 1.;
290 const double pp = p *
p;
292 const double dz = d * inwards;
293 const double dx2dy2 = 1. - dz * dz;
294 const double pz = p * inwards;
295 const double px2py2 = p.
GetMag2() - pz * pz;
297 const double r2 = r * r;
298 const double R2 = R * R;
299 const double pprrRR = pp - r2 + R2;
302 const double a3 = 4 * dd * pd;
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;
307 vector<double> roots;
308 Quartic(a0, a1, a2, a3, a4, roots);
310 for (vector<double>::const_iterator iRoot = roots.begin();
311 iRoot != roots.end();
313 const Point pInt = inPos + (*iRoot) * d;
314 Photon photonOut(photonIn);
316 intersections.push_back(pair<Photon,Vector>(photonOut,
TorusNormal(origin, inwards, pInt, torusRadius, tubeRadius)));
327 vector<double>& roots)
331 const double Phalve = a1 / (2 * a2);
332 const double Phalve2_Q = Phalve * Phalve - a0 / a2;
335 const double sqrtPhalve2_Q =
sqrt(Phalve2_Q);
336 roots.push_back(-Phalve + sqrtPhalve2_Q);
338 roots.push_back(-Phalve - sqrtPhalve2_Q);
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);
356 const double trans = - a2 / (3 * a3);
358 if (fabs(P) < 1e-11) {
360 roots.push_back(trans - cbrt(Q));
362 }
else if (fabs(Q) < 1e-11) {
365 roots.push_back(trans);
369 const double PPP4QQ27 = 4 * P * P * P + 27 * Q *
Q;
370 if (fabs(PPP4QQ27) < 1e-11) {
372 roots.push_back(trans + 3 * Q / P);
373 roots.push_back(trans - 3 * Q / (2 * P));
379 const double PPP27 = P * P * P / 27;
380 const double QQ4PPP27 = Q * Q / 4 + PPP27;
382 if ( QQ4PPP27 >= 0) {
384 const double sqrtQQ4PPP27 =
sqrt(QQ4PPP27);
386 roots.push_back(trans + cbrt(-Q / 2 + sqrtQQ4PPP27) + cbrt(-Q / 2 - sqrtQQ4PPP27));
391 cout <<
" THIS CANNOT HAPPEN " << endl;
395 const double sqrt_PPP27 =
sqrt( -PPP27 );
396 const double mag = cbrt(sqrt_PPP27);
398 const double sqrt_QQ4PPP27 =
sqrt(-QQ4PPP27);
399 const double phi = atan2(sqrt_QQ4PPP27, -Q / 2);
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));
420 vector<double>& roots)
446 Cubic(a0, a1, a2, a3, roots);
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;
454 const double subst = - a3 / (4 * a4);
456 if (fabs(beta) < 1.e-11) {
465 const double tmp = alpha * alpha / 4 - gamma;
470 const double sTmp =
sqrt(tmp);
471 const double tmp2 = -alpha / 2 + sTmp;
472 const double tmp3 = -alpha / 2 - sTmp;
476 const double sTmp2 =
sqrt(tmp2);
477 const double x1 = subst + sTmp2;
481 const double x2 = subst - sTmp2;
486 if (tmp3 >= 0 && sTmp != 0) {
488 const double sTmp3 =
sqrt(tmp3);
489 const double x3 = subst + sTmp3;
493 const double x4 = subst - sTmp3;
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.;
509 vector<double> rootsC;
510 Cubic(b0, b1, b2, b3, rootsC);
512 if (rootsC.size() == 0)
515 const double y = rootsC[0];
516 const double alpha2y = alpha + 2 * y;
519 cout <<
"THIS SHOULD NOT HAPPEN!!!!!!!!!!!!" << endl;
523 const double W = alpha2y < 0 ? 0 :
sqrt(alpha2y);
526 const double tmp1 = -(3 * alpha + 2 * y + 2 * beta / W);
527 const double tmp2 = -(3 * alpha + 2 * y - 2 * beta / W);
529 if (tmp1 < 0 && tmp2 < 0)
535 const double sTmp1 =
sqrt(tmp1);
537 const double x1 = subst + (W - sTmp1 ) / 2.;
541 const double x2 = subst + (W + sTmp1) / 2.;
548 const double sTmp2 =
sqrt(tmp2);
550 const double x3 = subst + (-W - sTmp2) / 2.;
554 const double x4 = subst + (-W + sTmp2) / 2.;
565 const double sigma_alpha)
567 if (sigma_alpha == 0) {
573 const double phiIn = normalIn.
GetPhi (internalCS);
574 const double thetaIn = normalIn.
GetTheta (internalCS);
578 const double phi = RandFlat::shoot(&rndm.
GetEngine(), 0., 2. *
kPi);
579 const double sinPhi = sin(phi);
580 const double cosPhi = cos(phi);
582 const double theta = RandGauss::shoot(&rndm.
GetEngine(), 0., sigma_alpha);
583 const double sinTheta = sin(theta);
584 const double cosTheta = cos(theta);
586 const double unit_x = sinTheta * cosPhi;
587 const double unit_y = sinTheta * sinPhi;
588 const double unit_z = cosTheta;
590 return Vector (unit_x, unit_y, unit_z, normalCS);
609 const double sigma_alpha,
612 if (sigma_alpha == 0) {
618 const double phiIn = normalIn.
GetPhi (internalCS);
619 const double thetaIn = normalIn.
GetTheta (internalCS);
624 const double f_max = std::min(1., 4. * sigma_alpha);
626 const double phi = RandFlat::shoot (&rndm.
GetEngine(), 0., 2. *
kPi);
627 const double sinPhi = sin(phi);
628 const double cosPhi = cos(phi);
636 alpha = RandGauss::shoot (&rndm.
GetEngine(), 0., sigma_alpha);
637 }
while (RandFlat::shoot (&rndm.
GetEngine(), 0., f_max) > sin(alpha) ||
640 double sinAlpha = sin(alpha);
641 double cosAlpha = cos(alpha);
643 double unit_x = sinAlpha * cosPhi;
644 double unit_y = sinAlpha * sinPhi;
645 double unit_z = cosAlpha;
647 facetNormal =
Vector (unit_x, unit_y, unit_z, normalCS);
649 }
while (rayIn * facetNormal >= 0.0);
662 const double amountOfStrayLight,
663 const double MaxTheta) {
665 double strayOrNot = RandFlat::shoot(&rndm.
GetEngine(), 0., 1.);
667 if (strayOrNot > amountOfStrayLight) {
674 const double phiIn = normal.
GetPhi (internalCS);
675 const double thetaIn = normal.
GetTheta (internalCS);
682 const double MinTheta = 0. *
degree;
684 const double MinPhi = 0. *
degree;
685 const double MaxPhi = 360. *
degree;
688 double phi = RandFlat::shoot(&rndm.
GetEngine(),
692 double theta_1 =
std::pow(cos(MinTheta), NCos + 1);
693 double theta_2 =
std::pow(cos(MaxTheta), NCos + 1);
695 double tmp = (theta_2 - theta_1) * RandFlat::shoot(&rndm.
GetEngine(), 0., 1.) + theta_1;
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) ) );
711 const Vector& specularDir,
714 const double verticalPosOnMirror) {
720 double value = RandFlat::shoot(&rndm.
GetEngine(), 0., 1.);
724 const double peripheralRegion = 18 *
deg;
728 if ((verticalPosOnMirror < peripheralRegion) && (verticalPosOnMirror > -1 * peripheralRegion)) {
729 float mirrorInterpolWeight = (verticalPosOnMirror+peripheralRegion) / (2 * peripheralRegion);
730 theta = (mirrorInterpolWeight * cumuCurveTop.
Y(value)) + ((1 - mirrorInterpolWeight) * cumuCurveBot.
Y(value));
734 else if (verticalPosOnMirror > peripheralRegion)
735 theta = cumuCurveTop.
Y(value);
738 else if (verticalPosOnMirror < -1 * peripheralRegion)
739 theta = cumuCurveBot.
Y(value);
745 const double phiIn = specularDir.
GetPhi (internalCS);
746 const double thetaIn = specularDir.
GetTheta (internalCS);
std::vector< PhotonNormalPair > IntersectionList
double Plane(const utl::Point &point, const utl::Vector &normal, const utl::Photon &photonIn, utl::Photon &photonOut)
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
RandomEngineType & GetEngine()
int Reflection(const utl::Photon &photonIn, const Vector &normal, utl::Photon &photonOut)
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
Class to hold collection (x,y) points and provide interpolation between them.
double GetWeight() const
weight assigned to the photon
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)
void SetPosition(const utl::Point &p)
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)
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
Wraps the random number engine used to generate distributions.
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)
void SetWeight(const double w)
source of the photons. Should use Eye::LightSource enum types
static const CSpherical kSpherical
const utl::Vector & GetDirection() const
int Refraction(const double n12, const utl::Photon &photonIn, const Vector &normal, PhotonList &photonsOut)
Vector LambertDiffusion(utl::RandomEngine &rndm, const Vector &rayIn, const Vector &normal, const double amountOfStrayLight, const double MaxTheta)
std::vector< utl::Photon > PhotonList
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)
Vector RandomNormal(utl::RandomEngine &rndm, const Vector &normalIn, double sigma_alpha, const Vector &rayIn)
const utl::Point & GetPosition() const