33 #include <fwk/RunController.h>
34 #include <fwk/CentralConfig.h>
35 #include <utl/Reader.h>
36 #include <utl/AugerException.h>
37 #include <utl/ErrorLogger.h>
38 #include <utl/MathConstants.h>
39 #include <utl/AugerException.h>
42 #include <G4PhysicalConstants.hh>
43 #include <G4SystemOfUnits.hh>
53 #define DOWN_IN_TANK 1
58 #define IN_INTERFACE_1 21
59 #define IN_INTERFACE_2 22
60 #define IN_INTERFACE_3 23
61 #define IN_INTERFACE_4 24
70 #define TARGET_FLOOR 5
74 namespace G4StationSimulatorOG {
76 double G4StationFastCerenkov::fTankHeight;
77 double G4StationFastCerenkov::fTankHalfHeight;
78 double G4StationFastCerenkov::fTankThickness;
79 double G4StationFastCerenkov::fTankRadius;
80 double G4StationFastCerenkov::fTankRadiusSq;
81 double G4StationFastCerenkov::fDomeRadius;
82 double G4StationFastCerenkov::fDomeRadiusz;
83 double G4StationFastCerenkov::fInterfaceRadius;
84 double G4StationFastCerenkov::fInterfaceRadiusz;
85 double G4StationFastCerenkov::fPMTRadius;
86 double G4StationFastCerenkov::fPMTRadiusz;
87 double G4StationFastCerenkov::fDomeRadiusSq;
88 double G4StationFastCerenkov::fDomeRadiuszSq;
89 double G4StationFastCerenkov::fInterfaceRadiusSq;
90 double G4StationFastCerenkov::fInterfaceRadiuszSq;
91 double G4StationFastCerenkov::fPMTRadiusSq;
92 double G4StationFastCerenkov::fPMTRadiuszSq;
93 double G4StationFastCerenkov::fHeightz;
95 bool G4StationFastCerenkov::fHasSPMT;
96 double G4StationFastCerenkov::fDomeRadius_SPMT;
97 double G4StationFastCerenkov::fDomeThick_SPMT;
98 double G4StationFastCerenkov::fInterfaceRadius_SPMT;
99 double G4StationFastCerenkov::fInterfaceThick_SPMT;
100 double G4StationFastCerenkov::fPMTRadius_SPMT;
101 double G4StationFastCerenkov::fPMTActiveRadius_SPMT;
102 double G4StationFastCerenkov::fPMTThick_SPMT;
103 double G4StationFastCerenkov::fDomeRadius_SPMT_Sq;
104 double G4StationFastCerenkov::fInterfaceRadius_SPMT_Sq;
105 double G4StationFastCerenkov::fPMTRadius_SPMT_Sq;
106 double G4StationFastCerenkov::fPMTActiveRadius_SPMT_Sq;
108 double G4StationFastCerenkov::fSigmaAlpha;
125 G4ThreeVector G4StationFastCerenkov::fPMTPos[5];
127 double G4StationFastCerenkov::fRoofPos[5];
130 G4StationFastCerenkov::G4StationFastCerenkov(
const G4String& processName) :
131 G4VContinuousProcess(processName),
136 if (verboseLevel > 0)
137 G4cerr << GetProcessName() <<
" is created " << G4endl;
142 const G4double betat = 7.658e-23 *
m3 /
MeV;
144 const G4double kboltz = 8.61739e-11 *
MeV /
kelvin;
146 const G4double temp = 283.15 *
kelvin;
147 const G4double hc4 =
pow(h_Planck * c_light, 4);
197 const auto& pmt = dStation.
GetPMT(1);
198 fQE = pmt.GetQuantumEfficiency();
199 const double collectionEfficiency = pmt.GetCollectionEfficiency();
200 for (
auto& qe :
fQE.YRange())
201 qe *= collectionEfficiency;
202 for (
auto& en :
fQE.XRange())
206 for (
int i = 1; i <= 3; ++i) {
233 const auto& small_pmt = dStation.
GetPMT(4);
234 fQE_SPMT = small_pmt.GetQuantumEfficiency();
235 const double collectionEfficiency_SPMT = small_pmt.GetCollectionEfficiency();
237 qe *= collectionEfficiency_SPMT;
257 static_cast<G4PhysicsOrderedFreeVector*>((*
fPhysicsTable)[i])->DumpValues();
264 aParticleChange.Initialize(track);
265 const G4DynamicParticle*
particle = track.GetDynamicParticle();
266 const G4Material*
const material = track.GetMaterial();
267 G4StepPoint*
const preStepPoint = step.GetPreStepPoint();
268 G4StepPoint*
const postStepPoint = step.GetPostStepPoint();
270 const G4ThreeVector x0 = preStepPoint->GetPosition();
271 const G4ThreeVector p0 = step.GetDeltaPosition().unit();
272 const G4double t0 = preStepPoint->GetGlobalTime();
275 return G4VContinuousProcess::AlongStepDoIt(track, step);
277 G4ThreeVector primaryDirection = preStepPoint->GetMomentumDirection();
279 const G4double cosAlpha = primaryDirection.z();
280 const G4double sinAlpha =
sqrt(1 -
Sqr(cosAlpha));
281 const G4double cosBeta = primaryDirection.x() / sinAlpha;
282 const G4double sinBeta = primaryDirection.y() / sinAlpha;
284 G4MaterialPropertiesTable*
const materialPropertiesTable = material->GetMaterialPropertiesTable();
286 if (!materialPropertiesTable)
287 return G4VContinuousProcess::AlongStepDoIt(track, step);
289 G4MaterialPropertyVector*
const rIndex = materialPropertiesTable->GetProperty(
"RINDEX");
292 return G4VContinuousProcess::AlongStepDoIt(track, step);
295 if (meanNumPhotons <= 0) {
296 aParticleChange.SetNumberOfSecondaries(0);
297 return G4VContinuousProcess::AlongStepDoIt(track, step);
300 meanNumPhotons *= step.GetStepLength();
302 const G4int numPhotons =
static_cast<G4int
>(G4Poisson(meanNumPhotons));
306 aParticleChange.SetNumberOfSecondaries(0);
308 return G4VContinuousProcess::AlongStepDoIt(track, step);
310 const G4double pMin = rIndex->GetMinLowEdgeEnergy();
311 const G4double pMax = rIndex->GetMaxLowEdgeEnergy();
312 const G4double nMax = rIndex->GetMaxValue();
314 const G4double dp = pMax - pMin;
316 const G4double betaInverse = particle->GetTotalEnergy() / particle->GetTotalMomentum();
318 const G4double maxCos = betaInverse / nMax;
319 const G4double maxSin2 = 1 - maxCos * maxCos;
330 for (G4int i = 0; i < numPhotons; ++i) {
332 G4double sin2Theta = 0;
333 G4double cosTheta = 0;
335 rand = G4UniformRand();
339 sin2Theta = 1 - cosTheta * cosTheta;
340 rand = G4UniformRand();
341 }
while (rand * maxSin2 > sin2Theta);
345 if (fSampledMomentum < minQEMomentum || fSampledMomentum > maxQEMomentum)
356 int iFirstValidBin_Wat = 0;
365 const G4double rIConst = (sampledRI_Sq + 2) * (sampledRI_Sq - 1);
370 const G4double invSumMFP = 1 / (absorptionMFP + rayleighMFP);
372 fInvMFP = 1 / absorptionMFP + 1 / rayleighMFP;
377 const G4double sinTheta =
sqrt(sin2Theta);
378 rand = G4UniformRand();
380 const G4double phi = 2 *
utl::kPi * rand;
381 const G4double sinThetaSinPhi = sin(phi) * sinTheta;
382 const G4double sinThetaCosPhi = cos(phi) * sinTheta;
384 const G4double px = cosAlpha * cosBeta * sinThetaCosPhi - sinBeta * sinThetaSinPhi + cosBeta * sinAlpha * cosTheta;
385 const G4double py = cosAlpha * sinBeta * sinThetaCosPhi + cosBeta * sinThetaSinPhi + sinBeta * sinAlpha * cosTheta;
386 const G4double pz = cosAlpha * cosTheta - sinAlpha * sinThetaCosPhi;
392 rand = G4UniformRand();
393 const G4double delta = rand * step.GetStepLength();
394 const G4double deltaTime = delta / (0.5 * (preStepPoint->GetVelocity() + postStepPoint->GetVelocity()));
401 if (radiusTest < 0 &&
407 if (verboseLevel > 0) {
408 G4cerr <<
"\n Exiting from G4Cerenkov::DoIt -- NumberOfSecondaries = "
409 << aParticleChange.GetNumberOfSecondaries() << G4endl;
412 return G4VContinuousProcess::AlongStepDoIt(track, step);
422 const G4MaterialTable*
const materialTable = G4Material::GetMaterialTable();
423 const G4int numOfMaterials = G4Material::GetNumberOfMaterials();
426 for (G4int i = 0; i < numOfMaterials; ++i) {
428 G4PhysicsOrderedFreeVector*
const physicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
429 G4Material*
const material = (*materialTable)[i];
430 G4MaterialPropertiesTable*
const materialPropertiesTable = material->GetMaterialPropertiesTable();
432 if (materialPropertiesTable) {
434 G4MaterialPropertyVector*
const rIndexVector = materialPropertiesTable->GetProperty(
"RINDEX");
438 G4double currentRI = (*rIndexVector)[0];
442 G4double currentPM = rIndexVector->Energy(0);
444 G4double currentCAI = 0;
445 physicsOrderedFreeVector->InsertValues(currentPM , currentCAI);
446 G4double prevRI = currentRI;
447 G4double prevPM = currentPM;
448 G4double prevCAI = currentCAI;
450 for (
size_t ii = 1; ii < rIndexVector->GetVectorLength(); ++ii) {
452 currentRI = (*rIndexVector)[ii];
453 currentPM = rIndexVector->Energy(ii);
454 currentCAI = 0.5 * (1 / (prevRI * prevRI) + 1 / (currentRI * currentRI));
455 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
456 physicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
458 prevCAI = currentCAI;
481 const G4Material*
const material = track.GetMaterial();
482 G4MaterialPropertiesTable*
const materialPropertiesTable = material->GetMaterialPropertiesTable();
484 if (!materialPropertiesTable)
487 G4MaterialPropertyVector*
const rIndex = materialPropertiesTable->GetProperty(
"RINDEX");
492 const G4DynamicParticle*
const particle = track.GetDynamicParticle();
494 if (meanNumPhotons <= 0)
497 const G4double stepLimit =
fMaxPhotons / meanNumPhotons;
504 const G4Material*
const material,
505 G4MaterialPropertyVector*
const rIndex)
508 const G4double rFact = 369.81 / (
eV *
cm);
510 if (particle->GetTotalMomentum() <= 0)
513 const G4double betaInverse = particle->GetTotalEnergy() / particle->GetTotalMomentum();
515 const G4int materialIndex = material->GetIndex();
517 G4PhysicsOrderedFreeVector*
const cerenkovAngleIntegrals =
518 (G4PhysicsOrderedFreeVector*)((*
fPhysicsTable)(materialIndex));
520 if (!cerenkovAngleIntegrals->IsFilledVectorExist())
523 G4double pMin = rIndex->GetMinLowEdgeEnergy();
524 const G4double pMax = rIndex->GetMaxLowEdgeEnergy();
525 const G4double nMin = rIndex->GetMinValue();
526 const G4double nMax = rIndex->GetMaxValue();
528 const G4double cAImax = cerenkovAngleIntegrals->GetMaxValue();
532 if (nMax < betaInverse) {
537 }
else if (nMin > betaInverse) {
544 pMin = rIndex->GetEnergy(betaInverse);
546 G4bool isOutRange =
false;
547 const G4double cAImin = cerenkovAngleIntegrals->GetValue(pMin, isOutRange);
548 ge = cAImax - cAImin;
550 if (verboseLevel > 0) {
551 G4cerr <<
"CAImin = " << cAImin << G4endl;
552 G4cerr <<
"ge = " << ge << G4endl;
557 const G4double charge = particle->GetDefinition()->GetPDGCharge();
558 const G4double numPhotons = rFact *
pow(charge /
eplus, 2) * (dp - ge * betaInverse*betaInverse);
571 const G4double rand = 2 * G4UniformRand() - 1;
572 const G4double cosTheta = (rand < 0) ? -
pow(-rand, 1 / 3.) :
pow(rand, 1 / 3.);
573 const G4double sinTheta =
sqrt(1 - cosTheta * cosTheta);
574 const G4double phi = 2 *
utl::kPi * G4UniformRand();
575 const G4double cosPhi = cos(phi);
576 const G4double sinPhi = sin(phi);
580 const G4double k = 1 /
sqrt(1 - c * c);
581 const G4double R11 = k *
b;
582 const G4double R12 = k * a *
c;
583 const G4double R21 = -k *
a;
584 const G4double R22 = k * b *
c;
585 const G4double R32 = -1 / k;
591 if (G4UniformRand() < 0.5) {
593 x = sinTheta * cosPhi;
594 y = sinTheta * sinPhi;
597 (R21 * x + R22 * y + b * z),
599 x = cosTheta * cosPhi;
600 y = cosTheta * sinPhi;
603 (R21 * x + R22 * y + b * z),
608 x = sinTheta * cosPhi;
609 y = sinTheta * sinPhi;
612 (R21 * x + R22 * y + b * z),
614 x = -cosTheta * cosPhi;
615 y = -cosTheta * sinPhi;
619 (R21 * x + R22 * y + b * z),
650 G4double closest = 0;
651 G4ThreeVector displacement;
654 for (
unsigned int i = 1; i <= 3; ++i) {
661 if (closest < 1 && -displacement.z() >
fHeightz) {
683 dead = TransitionToDome<1>(flag);
687 dead = TransitionToDome<2>(flag);
691 dead = TransitionToDome<3>(flag);
695 dead = TransitionToDome<4>(flag);
705 G4double distanceToFloor, distanceToWall, distanceTravelled, distance;
706 G4double distanceToRoof, distanceToPMT1, distanceToPMT2, distanceToPMT3, distanceToSPMT;
707 G4double alpha, beta, gamma;
710 G4double closest1, closest2, closest3, closest4;
711 G4ThreeVector closest, displacement1, displacement2, displacement3, displacement4;
712 G4double dotProduct, rand, distanceToPMT;
713 G4int hitPMT, targetPMT = -1, target;
721 WARNING(
"The z component of the momentul is 0, skipping photon.");
731 const double distance =
Sqr(alpha) - beta;
733 WARNING(
"Distance to wall is not finite, skipping photon");
737 distanceToWall =
sqrt(distance) - alpha;
740 rand = G4UniformRand();
741 testVal = 1 - exp(-min(distanceToWall, distanceToFloor) *
fInvMFP);
743 if (rand < testVal) {
747 distanceTravelled = -log(1 - rand/fRayleighFrac) /
fInvMFP;
751 if (fPhotonMomentum.z() < 0 &&
762 if (distanceToWall < distanceToFloor) {
788 distanceToWall =
sqrt(
Sqr(alpha) - beta) - alpha;
798 dotProduct = displacement2.dot(fPhotonMomentum);
805 dotProduct = displacement3.dot(fPhotonMomentum);
811 if (
fHasSPMT && fPhotonMomentum.z() > 0) {
812 displacement4 =
fPhotonPosition + distanceToRoof * fPhotonMomentum - fPMTPos[4];
820 distanceToPMT = 1e99;
833 if (distanceToPMT1 < distanceToPMT2) {
835 distanceToPMT = distanceToPMT1;
838 distanceToPMT = distanceToPMT2;
848 if (distanceToPMT1 < distanceToPMT3) {
850 distanceToPMT = distanceToPMT1;
853 distanceToPMT = distanceToPMT3;
859 if (distanceToPMT2 < distanceToPMT3) {
861 distanceToPMT = distanceToPMT2;
864 distanceToPMT = distanceToPMT3;
868 distanceToPMT = distanceToRoof;
873 distanceToSPMT = distanceToRoof;
874 if (distanceToPMT1 < distanceToSPMT) {
876 distanceToPMT = distanceToPMT1;
879 distanceToPMT = distanceToSPMT;
884 distanceToSPMT = distanceToRoof;
885 if (distanceToPMT2 < distanceToSPMT) {
887 distanceToPMT = distanceToPMT2;
890 distanceToPMT = distanceToSPMT;
895 distanceToSPMT = distanceToRoof;
896 if (distanceToPMT3 < distanceToSPMT) {
898 distanceToPMT = distanceToPMT3;
901 distanceToPMT = distanceToSPMT;
906 WARNING(
"Error determining next photon intersection in PropagateInTank()");
910 if (distanceToPMT < distanceToWall) {
911 if (distanceToPMT < distanceToRoof ||
914 distance = distanceToPMT;
917 distance = distanceToRoof;
920 if (distanceToRoof < distanceToWall) {
922 distance = distanceToRoof;
925 distance = distanceToWall;
929 rand = G4UniformRand();
930 testVal = 1 - exp(-distance *
fInvMFP);
931 if (rand < testVal) {
936 distanceTravelled = -log(1 - rand/fRayleighFrac) /
fInvMFP;
940 if (fPhotonMomentum.z() < 0 &&
956 if (fPhotonMomentum.z() < 0)
964 dead = TransitionToDome<1>(
INWARD);
969 dead = TransitionToDome<2>(
INWARD);
974 dead = TransitionToDome<3>(
INWARD);
979 dead = TransitionToDome<4>(
INWARD);
984 WARNING(
"Error finding target in PropagateInTank");
1001 const std::string err =
"Tank photon tracking ran into an impossible condition";
1014 G4ThreeVector alpha, beta, delta, normal;
1015 G4bool reflected, dead;
1016 G4double n, n2, transmission, vDotN;
1017 G4double paraComp, perpComp, paraMag, perpMag, x;
1018 G4ThreeVector paraPolarization, perpPolarization;
1028 dead = PropagateInDome<pmtId>(flag);
1046 normal *= 1/normal.mag();
1048 normal.set(0, 0, -1);
1050 if (vDotN > 0.999999) {
1051 transmission = 4 * n * n2 /
pow(n + n2, 2);
1052 reflected = (G4UniformRand() > transmission);
1061 dead = PropagateInDome<pmtId>(flag);
1069 dead = PropagateInDome<pmtId>(flag);
1075 alpha *= 1/alpha.mag();
1076 x =
Sqr(n2) -
Sqr(n) * (1 -
Sqr(vDotN));
1080 x = (vDotN > 0) ? -
sqrt(x) :
sqrt(x);
1084 perpComp = perpMag / (n * vDotN - x);
1085 paraComp = paraMag / (n2 * vDotN - (n * x / n2));
1086 transmission = -4 * n * vDotN * x * (
Sqr(perpComp) +
Sqr(paraComp));
1087 reflected = (G4UniformRand() >= transmission);
1109 dead = PropagateInDome<pmtId>(flag);
1122 dead = PropagateInDome<pmtId>(flag);
1152 dead = TransitionToInterface<pmtId>(flag);
1157 while (pmtId == 4) {
1163 G4ThreeVector displacement;
1168 if (distanceToInterface < 0) {
1169 const std::string err =
"Photon tracking inside SPMT dome run into an impossible condition : INWARD & distToInterface<0";
1182 dead = TransitionToInterface<pmtId>(flag);
1190 if (distanceToWater < 0) {
1191 const std::string err =
"Photon tracking inside SPMT dome run into an impossible condition : OUTWARD & distToWater<0";
1211 G4double distanceThis, distanceOther, distanceToRoof;
1215 if (distanceToRoof < 0)
1216 distanceToRoof = 1e99;
1220 if (distanceThis < distanceOther) {
1221 if (distanceToRoof < distanceThis)
1231 if (distanceToRoof < distanceOther)
1238 dead = TransitionToInterface<pmtId>(flag);
1244 if (distanceToRoof < distanceOther)
1262 G4ThreeVector alpha, beta, delta, normal;
1263 G4bool reflected, dead;
1264 G4double n, n2, transmission, vDotN;
1265 G4double paraComp, perpComp, paraMag, perpMag, x;
1266 G4ThreeVector paraPolarization, perpPolarization;
1272 dead = PropagateInInterface<pmtId>(flag);
1290 normal *= 1/normal.mag();
1292 normal.set(0, 0, -1);
1294 if (vDotN > 0.999999) {
1295 transmission = 4 * n * n2 /
pow(n + n2, 2);
1296 reflected = (G4UniformRand() > transmission);
1305 dead = PropagateInInterface<pmtId>(flag);
1311 dead = PropagateInInterface<pmtId>(flag);
1317 alpha *= 1/alpha.mag();
1318 x =
Sqr(n2) -
Sqr(n) * (1 -
Sqr(vDotN));
1322 x = (vDotN > 0) ? -
sqrt(x) :
sqrt(x);
1326 perpComp = perpMag / (n * vDotN - x);
1327 paraComp = paraMag / (n2 * vDotN - n * x / n2);
1328 transmission = -4 * n * vDotN * x * (
Sqr(perpComp) +
Sqr(paraComp));
1329 reflected = (G4UniformRand() >= transmission);
1350 dead = PropagateInInterface<pmtId>(flag);
1363 dead = PropagateInInterface<pmtId>(flag);
1388 while (pmtId == 4) {
1395 G4ThreeVector displacement;
1400 if (distanceToPMT < 0) {
1401 const std::string err =
"Photon tracking inside SPMT interface run into an impossible condition : INWARD & distToPMT<0";
1423 G4double maxDistanceInsidePMT =
fPMTThick_SPMT / fPhotonMomentum.z();
1438 if (distanceToDome < 0) {
1439 const std::string err =
"Photon tracking inside SPMT interface run into an impossible condition : OUTWARD & distToDome<0";
1459 if (distanceToRoof < 0)
1460 distanceToRoof = 1e99;
1467 if (distanceThis < distanceOther) {
1468 if (distanceToRoof < distanceThis)
1478 if (distanceToRoof < distanceOther)
1503 const G4ThreeVector normal(0, 0, -1);
1505 G4double r = G4UniformRand();
1506 if (r > reflectivity)
1533 G4double r = G4UniformRand();
1534 if (r > reflectivity)
1539 const G4double w = 1 /
sqrt(
Sqr(x) +
Sqr(y));
1540 const G4ThreeVector normal(-x * w, -y * w, 0);
1564 const G4ThreeVector normal(0, 0, 1);
1566 G4double r = G4UniformRand();
1567 if (r > reflectivity)
1603 const G4double rand = G4UniformRand();
1604 const G4double cosTheta =
sqrt(1 - rand);
1605 const G4double sinTheta =
sqrt(rand);
1606 const G4double phi = 2 *
utl::kPi * G4UniformRand();
1607 const G4double sinThetaCosPhi = sinTheta * cos(phi);
1608 const G4double sinThetaSinPhi = sinTheta * sin(phi);
1609 const G4double x = normal.x();
1610 const G4double y = normal.y();
1612 const G4double vx = x * cosTheta - y * sinThetaSinPhi / w;
1613 const G4double vy = y * cosTheta + x * sinThetaSinPhi / w;
1614 const G4double vz = -w * sinThetaCosPhi;
1626 const G4double rand = G4UniformRand();
1627 const G4double cosTheta =
sqrt(1 - rand);
1628 const G4double sinTheta =
sqrt(rand);
1629 const G4double phi = 2 *
utl::kPi * G4UniformRand();
1630 const G4double vx = sinTheta * cos(phi);
1631 const G4double vy = sinTheta * sin(phi);
1632 const G4double vz = normal.z() * cosTheta;
1647 fPhotonMomentum /= fPhotonMomentum.mag();
1656 const G4double x = normal.x();
1657 const G4double y = normal.y();
1659 G4ThreeVector trialMomentum;
1661 G4ThreeVector facetNormal;
1662 G4double dotProduct;
1668 sinAlpha = sin(alpha);
1669 }
while (G4UniformRand()*fMax > sinAlpha || alpha >= 0.5*
utl::kPi);
1670 const G4double phi = 2*
utl::kPi * G4UniformRand();
1671 const G4double cosAlpha = cos(alpha);
1672 const G4double sinAlphaSinPhi = sinAlpha * sin(phi);
1673 const G4double sinAlphaCosPhi = sinAlpha * cos(phi);
1674 const G4double vx = x * cosAlpha - y * sinAlphaSinPhi / w;
1675 const G4double vy = y * cosAlpha + x * sinAlphaSinPhi / w;
1676 const G4double vz = -w * sinAlphaCosPhi;
1677 facetNormal.set(vx, vy, vz);
1679 }
while (dotProduct >= 0);
1681 }
while (trialMomentum.dot(normal) <= 0);
1686 fPhotonMomentum /= fPhotonMomentum.mag();
1695 G4ThreeVector trialMomentum;
1697 G4ThreeVector facetNormal;
1698 G4double dotProduct;
1704 sinAlpha = sin(alpha);
1705 }
while (G4UniformRand()*fMax > sinAlpha || alpha >= 0.5*
utl::kPi);
1706 const G4double phi = 2*
utl::kPi * G4UniformRand();
1707 const G4double cosAlpha = cos(alpha);
1708 const G4double vx = sinAlpha * cos(phi);
1709 const G4double vy = sinAlpha * sin(phi);
1710 const G4double vz = normal.z() * cosAlpha;
1711 facetNormal.set(vx, vy, vz);
1713 }
while (dotProduct >= 0);
1715 }
while (trialMomentum.dot(normal) <= 0);
1720 fPhotonMomentum /= fPhotonMomentum.mag();
1733 const G4double
c = pos.dot(pos) -
Sqr(r);
1734 G4double d =
Sqr(b) -
c;
1739 const G4double distA = b + d;
1740 const G4double distB = b - d;
1742 if (distB < distA) {
1759 const G4double r1,
const G4double r2)
1767 const double c[3] = {
Sqr(pos.x()),
Sqr(pos.y()),
Sqr(pos.z()) };
1770 const double r12 =
Sqr(r1);
1771 const double r22 =
Sqr(r2);
1772 const double e = (b[0] + b[1]) / r12 + b[2] / r22;
1773 const double f = 2*((d[0] + d[1]) / r12 + d[2] / r22);
1774 const double g = (c[0] + c[1]) / r12 + c[2] / r22 - 1;
1776 const double dis =
Sqr(f) - 4*e*
g;
1781 const double sq =
sqrt(dis);
1783 const double i2e = 1 / (2*e);
1784 const double a1 = i2e * (-f + sq);
1785 const double a2 = i2e * (-f - sq);
static double fDomeRadius
void SpikeScatter(const G4ThreeVector &normal)
static double fPMTRadiuszSq
void AddPhoton(const int nPMT, const double peTime) const
peTime in Auger units!
static double fgTankHalfHeight
unsigned int GetNPoints() const
void DumpPhysicsTable() const
constexpr T Sqr(const T &x)
static double fInterfaceThick_SPMT
Detector description interface for Station-related data.
static double fgTankRadius
ArrayConstReference XBack() const
read-only reference to back of array of X
G4bool PropagateInInterface(G4int &flag)
static double fDomeRadius_SPMT
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &step) override
void DiffuseScatterVertical(const G4ThreeVector &normal)
static utl::TabulatedFunction fInterfaceAbsLength
static double fDomeThick_SPMT
static double fDomeThickness_SPMT
Class to hold collection (x,y) points and provide interpolation between them.
G4bool TransitionToInterface(G4int &flag)
static double fInterfaceRadiusSq
static double fPMTActiveRadius_SPMT_Sq
static G4ThreeVector fPMTPos[5]
static double fInterfaceRadius_SPMT_Sq
static double fPMTActiveRadius_SPMT
static utl::TabulatedFunction fLinerBackscatter
static double fInterfaceRadiuszSq
static utl::TabulatedFunction fgWaterABSORPTION
static double fPMTThick_SPMT
const PMT & GetPMT(const int id) const
Get specified PMT by id.
static utl::TabulatedFunction fLinerReflectivity
static double fPMTRadius_SPMT
static utl::TabulatedFunction fgLinerSPECULARLOBECONSTANT
double pow(const double x, const unsigned int i)
void LobeScatterVertical(const G4ThreeVector &normal)
static double fTankHeight
static double fPmtRmin_SPMT
virtual ~G4StationFastCerenkov()
static utl::TabulatedFunction fWaterAbsLength
Exception for reporting variable out of valid range.
G4ThreeVector fPhotonMomentum
static double fgInterfaceRmax
static double fInterfaceRadius_SPMT
const sdet::Station & GetDetectorStation() const
static double fgTankThickness
static double fSigmaAlpha
ArrayConstReference XFront() const
read-only reference to front of array of X
G4double GetAverageNumberOfPhotons(const G4DynamicParticle *, const G4Material *, G4MaterialPropertyVector *) const
static double fInterfaceRadius
G4double GetContinuousStepLimit(const G4Track &, G4double, G4double, G4double &) override
static utl::TabulatedFunction fQE_SPMT
static double fPMTRadiusz
const utl::Point & GetPosition() const
PMT position.
void DiffuseScatterHorizontal(const G4ThreeVector &normal)
Auger Software Run Control.
G4StationSimulator & fG4StationSimulator
G4bool TransitionToDome(G4int flag)
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger reference system centered on the tank.
static double fTankRadius
void PropagateInTank(G4int flag)
static G4double fRoofPos[5]
#define WARNING(message)
Macro for logging warning messages.
static double fInterfaceRadius_SPMT
G4double GetSphereIntersect(const G4ThreeVector &, const G4double) const
static double fGlassThickness_SPMT
static void GetDataFromConstruction()
G4double GetEllipsoidIntersect(const G4ThreeVector &, const G4double, const G4double) const
static double fgSIGMA_ALPHA
static double fPMTRadiusSq
static utl::TabulatedFunction fDomeRIndex
static utl::TabulatedFunction fgLinerBACKSCATTERCONSTANT
G4ThreeVector fPhotonPosition
G4ThreeVector fPhotonPolarization
G4double fSampledMomentum
static utl::TabulatedFunction fgPmtdomeRINDEX
static double fgDomeRzmax
G4ThreeVector ToG4Vector(const V &v, const utl::CoordinateSystemPtr &cs, const double unitConversion)
void BuildThePhysicsTable()
static double fDomeRadiusz
static utl::TabulatedFunction fQE
static double fPmtRmax_SPMT
static utl::TabulatedFunction fgLinerREFLECTIVITY
static utl::TabulatedFunction fInterfaceRIndex
class that handles Geant4 SD Station simulation adopted from G4TankSimulator
G4PhysicsTable * fPhysicsTable
struct particle_info particle[80]
static utl::TabulatedFunction fLinerSpecularSpike
void LobeScatterHorizontal(const G4ThreeVector &normal)
static utl::TabulatedFunction fgLinerSPECULARSPIKECONSTANT
static double fDomeRadiusSq
static double fInterfaceThickness_SPMT
static double fTankHalfHeight
static double fTankThickness
static double fPMTRadius_SPMT_Sq
static double fDomeRadius_SPMT
static utl::TabulatedFunction fLinerSpecularLobe
static utl::TabulatedFunction fDomeAbsLength
static double fgInterfaceRzmax
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
static double fDomeRadiuszSq
static utl::TabulatedFunction fgInterfaceRINDEX
G4bool PropagateInDome(G4int &flag)
#define ERROR(message)
Macro for logging error messages.
static double fInterfaceRadiusz
static utl::TabulatedFunction fgPmtdomeABSORPTION
static double fTankRadiusSq
static utl::TabulatedFunction fgInterfaceABSORPTION
static double fDomeRadius_SPMT_Sq