31 using namespace G4TankSimulatorOG;
33 #include <G4Version.hh>
35 #include <fwk/RunController.h>
36 #include <fwk/CentralConfig.h>
38 #include <utl/Reader.h>
39 #include <utl/AugerException.h>
40 #include <utl/ErrorLogger.h>
41 #include <utl/MathConstants.h>
42 #include <utl/AugerException.h>
92 : G4VContinuousProcess(processName)
97 if (verboseLevel > 0) G4cerr << GetProcessName() <<
" is created "
103 const G4double betat = 7.658e-23 *
m3 /
MeV;
105 const G4double kboltz = 8.61739e-11 *
MeV /
kelvin;
107 const G4double temp = 283.15 *
kelvin;
108 const G4double hc4 =
pow(h_Planck * c_light, 4);
114 dynamic_cast<G4TankSimulator*
>(&RunController::GetInstance().GetModule(
"G4TankSimulatorOG"));
163 const double& collectionEfficiency =
168 std::vector<double>::iterator fIt;
170 (*fIt) *= collectionEfficiency;
193 pmt1.
GetY(pmt1Coord) *
m,
194 pmt1.
GetZ(pmt1Coord) *
m);
197 pmt2.
GetY(pmt2Coord) *
m,
198 pmt2.
GetZ(pmt2Coord) *
m);
201 pmt3.
GetY(pmt3Coord) *
m,
202 pmt3.
GetZ(pmt3Coord) *
m);
204 for(
unsigned int k=1; k<4; ++k)
221 return (aParticle.GetPDGCharge() != 0);
246 G4PhysicsOrderedFreeVector *v;
249 for (G4int i = 0; i < PhysicsTableSize; ++i) {
251 v =
static_cast<G4PhysicsOrderedFreeVector *
>((*fThePhysicsTable)[i]);
259 const G4Step& aStep) {
263 aParticleChange.Initialize(aTrack);
264 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
265 const G4Material* aMaterial = aTrack.GetMaterial();
266 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
267 G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
269 const G4ThreeVector x0 = pPreStepPoint->GetPosition();
270 const G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
271 const G4double t0 = pPreStepPoint->GetGlobalTime();
273 if (t0 > 1.0e6)
return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
275 G4ThreeVector aPrimaryDirection = pPreStepPoint->GetMomentumDirection();
277 const G4double cosAlpha = aPrimaryDirection.z();
278 const G4double sinAlpha =
sqrt(1.0 - (cosAlpha * cosAlpha));
279 const G4double cosBeta = aPrimaryDirection.x() / sinAlpha;
280 const G4double sinBeta = aPrimaryDirection.y() / sinAlpha;
282 G4MaterialPropertiesTable* aMaterialPropertiesTable =
283 aMaterial->GetMaterialPropertiesTable();
285 if (!aMaterialPropertiesTable)
286 return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
288 const G4MaterialPropertyVector* Rindex =
289 aMaterialPropertiesTable->GetProperty(
"RINDEX");
292 return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
296 if (MeanNumPhotons <= 0.0) {
297 aParticleChange.SetNumberOfSecondaries(0);
298 return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
301 MeanNumPhotons *= aStep.GetStepLength();
303 G4int NumPhotons =
static_cast<G4int
>(G4Poisson(MeanNumPhotons));
307 aParticleChange.SetNumberOfSecondaries(0);
309 return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
311 #if (G4VERSION_NUMBER < 920)
312 const G4double Pmin = Rindex->GetMinPhotonMomentum();
313 const G4double Pmax = Rindex->GetMaxPhotonMomentum();
315 const G4double Pmin = Rindex->GetMinPhotonEnergy();
316 const G4double Pmax = Rindex->GetMaxPhotonEnergy();
319 const G4double dp = Pmax - Pmin;
320 const G4double nMax = Rindex->GetMaxProperty();
322 const G4double betaInverse = aParticle->GetTotalEnergy() /
323 aParticle->GetTotalMomentum();
325 const G4double maxCos = betaInverse / nMax;
326 const G4double maxSin2 = (1.0 - (maxCos * maxCos));
328 const double minQEMomentum =
fQE[0].X();
335 G4double rand, cosTheta, sin2Theta;
336 G4double phi, sinTheta, px, py, pz;
338 G4double delta, deltaTime;
339 G4double sinThetaSinPhi, sinThetaCosPhi;
341 double absorptionMFP;
343 for (G4int i = 0; i < NumPhotons; ++i) {
345 rand = G4UniformRand();
349 sin2Theta = (1.0 - (cosTheta * cosTheta));
350 rand = G4UniformRand();
351 }
while ((rand * maxSin2) > sin2Theta);
363 G4double SampledRI_Sq, RIConst;
366 int iFirstValidBin_Wat = 0;
377 RIConst = (SampledRI_Sq + 2.0) * (SampledRI_Sq - 1.0);
382 invSumMFP = 1.0 / (absorptionMFP + rayleighMFP);
384 fInvMFP = (1.0 / absorptionMFP) + (1.0 / rayleighMFP);
389 sinTheta =
sqrt(sin2Theta);
390 rand = G4UniformRand();
393 sinThetaSinPhi = sin(phi) * sinTheta;
394 sinThetaCosPhi = cos(phi) * sinTheta;
396 px = (cosAlpha * cosBeta * sinThetaCosPhi) - (sinBeta * sinThetaSinPhi)
397 + (cosBeta * sinAlpha * cosTheta);
398 py = (cosAlpha * sinBeta * sinThetaCosPhi) + (cosBeta * sinThetaSinPhi)
399 + (sinBeta * sinAlpha * cosTheta);
400 pz = (cosAlpha * cosTheta) - (sinAlpha * sinThetaCosPhi);
406 rand = G4UniformRand();
407 delta = rand * aStep.GetStepLength();
408 deltaTime = delta / ((pPreStepPoint->GetVelocity() +
409 pPostStepPoint->GetVelocity()) / 2.0);
422 if (verboseLevel > 0) {
423 G4cerr <<
"\n Exiting from G4Cerenkov::DoIt -- NumberOfSecondaries = "
424 << aParticleChange.GetNumberOfSecondaries() << G4endl;
427 return G4VContinuousProcess::AlongStepDoIt(aTrack, aStep);
439 const G4MaterialTable* theMaterialTable= G4Material::GetMaterialTable();
440 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
443 G4PhysicsOrderedFreeVector *aPhysicsOrderedFreeVector;
444 G4Material *aMaterial;
445 G4MaterialPropertiesTable *aMaterialPropertiesTable;
446 G4MaterialPropertyVector *theRIndexVector;
447 G4double currentRI, currentPM, currentCAI;
448 G4double prevRI, prevPM, prevCAI;
450 for (G4int i = 0; i < numOfMaterials; ++i) {
452 aPhysicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
453 aMaterial = (*theMaterialTable)[i];
454 aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
456 if (aMaterialPropertiesTable) {
458 theRIndexVector = aMaterialPropertiesTable->GetProperty(
"RINDEX");
460 if (theRIndexVector) {
462 theRIndexVector->ResetIterator();
463 ++(*theRIndexVector);
464 currentRI = theRIndexVector->GetProperty();
466 if (currentRI > 1.0) {
468 #if (G4VERSION_NUMBER < 920)
469 currentPM = theRIndexVector->GetPhotonMomentum();
471 currentPM = theRIndexVector->GetPhotonEnergy();
475 aPhysicsOrderedFreeVector->InsertValues(currentPM , currentCAI);
478 prevCAI = currentCAI;
480 while(++(*theRIndexVector)) {
482 currentRI = theRIndexVector->GetProperty();
484 #if (G4VERSION_NUMBER < 920)
485 currentPM = theRIndexVector->GetPhotonMomentum();
487 currentPM = theRIndexVector->GetPhotonEnergy();
490 currentCAI = 0.5 * ((1.0 / (prevRI * prevRI)) +
491 (1.0 / (currentRI * currentRI)));
492 currentCAI = prevCAI + ((currentPM - prevPM) * currentCAI);
493 aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCAI);
495 prevCAI = currentCAI;
514 G4double, G4double, G4double &) {
519 const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
520 const G4Material* aMaterial = aTrack.GetMaterial();
522 G4MaterialPropertiesTable* aMaterialPropertiesTable =
523 aMaterial->GetMaterialPropertiesTable();
525 if (!aMaterialPropertiesTable)
528 const G4MaterialPropertyVector* Rindex =
529 aMaterialPropertiesTable->GetProperty(
"RINDEX");
536 if (meanNumPhotons <= 0.0)
546 const G4Material* aMaterial,
547 const G4MaterialPropertyVector* Rindex)
const {
548 const G4double Rfact = 369.81 / (
eV *
cm);
550 if (aParticle->GetTotalMomentum() <= 0.0)
553 G4double betaInverse = aParticle->GetTotalEnergy() /
554 aParticle->GetTotalMomentum();
556 G4int materialIndex = aMaterial->GetIndex();
558 G4PhysicsOrderedFreeVector* CerenkovAngleIntegrals =
561 if (!(CerenkovAngleIntegrals->IsFilledVectorExist()))
564 #if (G4VERSION_NUMBER < 920)
565 G4double Pmin = Rindex->GetMinPhotonMomentum();
566 G4double Pmax = Rindex->GetMaxPhotonMomentum();
568 G4double Pmin = Rindex->GetMinPhotonEnergy();
569 G4double Pmax = Rindex->GetMaxPhotonEnergy();
572 G4double nMin = Rindex->GetMinProperty();
573 G4double nMax = Rindex->GetMaxProperty();
574 G4double CAImax = CerenkovAngleIntegrals->GetMaxValue();
577 if (nMax < betaInverse) {
582 }
else if (nMin > betaInverse) {
589 #if (G4VERSION_NUMBER < 920)
590 Pmin = Rindex->GetPhotonMomentum(betaInverse);
592 Pmin = Rindex->GetPhotonEnergy(betaInverse);
596 G4double CAImin = CerenkovAngleIntegrals->GetValue(Pmin, isOutRange);
597 ge = CAImax - CAImin;
599 if (verboseLevel>0) {
600 G4cerr <<
"CAImin = " << CAImin << G4endl;
601 G4cerr <<
"ge = " << ge << G4endl;
606 G4double charge = aParticle->GetDefinition()->GetPDGCharge();
607 G4double numPhotons = Rfact *
pow((charge /
eplus), 2) *
608 (dp - ge * betaInverse*betaInverse);
621 const G4double rand = 2.0 * G4UniformRand() - 1.0;
622 const G4double cosTheta= (rand < 0.0)?
623 (-
pow(-rand, 1.0 / 3.0)):
pow(rand, 1.0 / 3.0);
624 const G4double sinTheta =
sqrt(1.0 - cosTheta * cosTheta);
625 const G4double phi = 2.0 *
utl::kPi * G4UniformRand();
626 const G4double cosPhi = cos(phi);
627 const G4double sinPhi = sin(phi);
631 const G4double k = 1.0 /
sqrt(1.0 - c * c);
632 const G4double R11 = k *
b;
633 const G4double R12 = k * a *
c;
634 const G4double R21 = -k *
a;
635 const G4double R22 = k * b *
c;
636 const G4double R32 = -1.0 / k;
644 if (G4UniformRand() < 0.5) {
646 x = sinTheta * cosPhi;
647 y = sinTheta * sinPhi;
650 (R21 * x + R22 * y + b * z),
652 x = cosTheta * cosPhi;
653 y = cosTheta * sinPhi;
656 (R21 * x + R22 * y + b * z),
661 x = sinTheta * cosPhi;
662 y = sinTheta * sinPhi;
665 (R21 * x + R22 * y + b * z),
667 x = -cosTheta * cosPhi;
668 y = -cosTheta * sinPhi;
672 (R21 * x + R22 * y + b * z),
703 G4ThreeVector displacement;
706 for(
unsigned int i=1; i<4; ++i){
708 closest = (displacement.x()*displacement.x()+displacement.y()*displacement.y())/
fDomeRadiusSq +
711 closest = (displacement.x()*displacement.x()+displacement.y()*displacement.y())/
fInterfaceRadiusSq +
714 closest = (displacement.x()*displacement.x()+displacement.y()*displacement.y())/
fPMTRadiusSq +
716 if (closest < 1. && -displacement.z() >
fHeightz ) {
738 Dead = TransitionToDome<1>(flag);
743 Dead = TransitionToDome<2>(flag);
748 Dead = TransitionToDome<3>(flag);
756 G4double DistanceToFloor, DistanceToWall, DistanceTravelled,
Distance;
757 G4double DistanceToRoof, DistanceToPMT1, DistanceToPMT2, DistanceToPMT3;
758 G4double alpha, beta, gamma;
761 G4double closest1, closest2, closest3;
762 G4ThreeVector closest, Displacement1, Displacement2, Displacement3;
763 G4double DotProduct, rand, DistanceToPMT;
764 G4int HitPMT, TargetPMT = -1, Target;
772 WARNING(
"The z component of the momentul is 0, skipping photon.");
786 const double distance=alpha * alpha - beta;
788 WARNING(
"Distance to wall is not finite, skipping photon");
792 DistanceToWall =
sqrt(distance) - alpha;
795 rand = G4UniformRand();
796 TestVal=(DistanceToWall < DistanceToFloor)?
797 (1.0 - exp(-DistanceToWall *
fInvMFP)):(1.0 - exp(-DistanceToFloor * fInvMFP));
799 if (rand < TestVal) {
803 DistanceTravelled = -log(1.0 - (rand / fRayleighFrac)) /
fInvMFP;
807 if ((fPhotonMomentum.z() < 0.0) &&
818 if (DistanceToWall < DistanceToFloor) {
848 DistanceToWall =
sqrt(alpha * alpha - beta) - alpha;
853 closest1 = (closest.x()*closest.x()+closest.y()*closest.y())/
fDomeRadiusSq +
855 if (closest1 < 1. ) HitPMT += 1;
860 closest2 = (closest.x()*closest.x()+closest.y()*closest.y())/
fDomeRadiusSq +
862 if (closest2 < 1. ) HitPMT += 2;
867 closest3 = (closest.x()*closest.x()+closest.y()*closest.y())/
fDomeRadiusSq +
869 if (closest3 < 1. ) HitPMT += 4;
873 DistanceToPMT = 1.0e99;
886 if (DistanceToPMT1 < DistanceToPMT2) {
888 DistanceToPMT = DistanceToPMT1;
892 DistanceToPMT = DistanceToPMT2;
902 if (DistanceToPMT1 < DistanceToPMT3) {
904 DistanceToPMT = DistanceToPMT1;
908 DistanceToPMT = DistanceToPMT3;
914 if (DistanceToPMT2 < DistanceToPMT3) {
916 DistanceToPMT = DistanceToPMT2;
920 DistanceToPMT = DistanceToPMT3;
925 WARNING(
"Error determining next photon intersection in PropagateInTank()");
933 if (DistanceToPMT < DistanceToWall) {
934 if (DistanceToPMT < DistanceToRoof) {
936 Distance = DistanceToPMT;
940 Distance = DistanceToRoof;
944 if (DistanceToRoof < DistanceToWall) {
946 Distance = DistanceToRoof;
950 Distance = DistanceToWall;
954 rand = G4UniformRand();
955 TestVal = 1.0 - exp(-Distance *
fInvMFP);
956 if (rand < TestVal) {
962 DistanceTravelled = -log(1.0 - (rand / fRayleighFrac)) /
fInvMFP;
966 if ((fPhotonMomentum.z() < 0.0) &&
988 Dead = TransitionToDome<1>(
INWARD);
992 Dead = TransitionToDome<2>(
INWARD);
996 Dead = TransitionToDome<3>(
INWARD);
1000 WARNING(
"Error finding target in PropagateInTank");
1018 std::string err(
"Tank photon tracking ran into an impossible condition");
1032 G4ThreeVector Alpha,
Beta, Delta, Normal;
1033 G4bool reflected, Dead;
1034 G4double n, n2, Transmission, VDotN;
1035 G4double ParaComp, PerpComp, ParaMag, PerpMag, X;
1036 G4ThreeVector ParaPolarization, PerpPolarization;
1041 Dead = PropagateInDome<pmtId>(flag);
1042 if (Dead)
return true;
1057 Normal /= Normal.mag();
1059 if (VDotN > 0.999999) {
1060 Transmission = 4.0 * n * n2 /
pow((n + n2), 2);
1061 reflected = G4UniformRand() > Transmission;
1070 Dead = PropagateInDome<pmtId>(flag);
1071 if (Dead)
return true;
1078 Dead = PropagateInDome<pmtId>(flag);
1079 if (Dead)
return true;
1084 Alpha /= Alpha.mag();
1085 X = (n2 * n2) - (n * n) * (1.0 - (VDotN * VDotN));
1086 if (X <= 0.0) X = 0.0;
1088 if (VDotN > 0.0) X = -
sqrt(X);
1094 PerpComp = PerpMag / (n * VDotN - X);
1095 ParaComp = ParaMag / (n2 * VDotN - (n * X / n2));
1096 Transmission = -(4.0 * n * VDotN * X) * (PerpComp * PerpComp +
1097 ParaComp * ParaComp);
1098 reflected = (G4UniformRand() >= Transmission);
1099 if (X == 0.0) reflected =
true;
1120 Dead = PropagateInDome<pmtId>(flag);
1121 if (Dead)
return true;
1133 Dead = PropagateInDome<pmtId>(flag);
1134 if (Dead)
return true;
1161 Dead = TransitionToInterface<pmtId>(flag);
1162 if (Dead)
return true;
1165 G4double DistanceThis, DistanceOther, DistanceToRoof;
1169 if (DistanceToRoof < 0.0) DistanceToRoof = 1.0e99;
1174 if (DistanceThis < DistanceOther) {
1175 if (DistanceToRoof < DistanceThis)
return true;
1176 Dead = (G4UniformRand() > exp(-DistanceThis /
1178 if (Dead)
return true;
1185 if (DistanceToRoof < DistanceOther)
return true;
1186 Dead = (G4UniformRand() > exp(-DistanceOther /
1188 if (Dead)
return true;
1191 Dead = TransitionToInterface<pmtId>(flag);
1192 if (Dead)
return true;
1197 if (DistanceToRoof < DistanceOther)
return true;
1198 Dead = (G4UniformRand() > exp(-DistanceOther /
1200 if (Dead)
return true;
1212 G4ThreeVector Alpha,
Beta, Delta, Normal;
1213 G4bool reflected, Dead;
1214 G4double n, n2, Transmission, VDotN;
1215 G4double ParaComp, PerpComp, ParaMag, PerpMag, X;
1216 G4ThreeVector ParaPolarization, PerpPolarization;
1222 Dead = PropagateInInterface<pmtId>(flag);
1223 if (Dead)
return true;
1238 Normal /= Normal.mag();
1240 if (VDotN > 0.999999) {
1241 Transmission = 4.0 * n * n2 /
pow((n + n2), 2);
1242 reflected = G4UniformRand() > Transmission;
1251 Dead = PropagateInInterface<pmtId>(flag);
1252 if (Dead)
return true;
1255 if (flag ==
OUTWARD)
return true;
1256 Dead = PropagateInInterface<pmtId>(flag);
1257 if (Dead)
return true;
1262 Alpha /= Alpha.mag();
1263 X = (n2 * n2) - (n * n) * (1.0 - (VDotN * VDotN));
1264 if (X <= 0.0) X = 0.0;
1266 if (VDotN > 0.0) X = -
sqrt(X);
1272 PerpComp = PerpMag / (n * VDotN - X);
1273 ParaComp = ParaMag / (n2 * VDotN - (n * X / n2));
1274 Transmission = -(4.0 * n * VDotN * X) * (PerpComp * PerpComp +
1275 ParaComp * ParaComp);
1276 reflected = (G4UniformRand() >= Transmission);
1277 if (X == 0.0) reflected =
true;
1297 Dead = PropagateInInterface<pmtId>(flag);
1298 if (Dead)
return true;
1310 Dead = PropagateInInterface<pmtId>(flag);
1311 if (Dead)
return true;
1332 G4double DistanceThis, DistanceOther, DistanceToRoof;
1334 if (DistanceToRoof < 0.0) DistanceToRoof = 1.0e99;
1341 if (DistanceThis < DistanceOther) {
1342 if (DistanceToRoof < DistanceThis)
return true;
1343 Dead = (G4UniformRand() > exp(-DistanceThis /
1345 if (Dead)
return true;
1352 if (DistanceToRoof < DistanceOther)
return true;
1353 Dead = (G4UniformRand() > exp(-DistanceOther /
1355 if (Dead)
return true;
1370 G4ThreeVector Normal(0.0, 0.0, -1.0);
1372 G4double r = G4UniformRand();
1373 if (r > Reflectivity)
return true;
1396 G4ThreeVector Normal;
1398 G4double r = G4UniformRand();
1399 if (r > Reflectivity)
return true;
1403 G4double W = 1.0 /
sqrt((X * X) + (Y * Y));
1404 Normal.set(-X * W, -Y * W, 0.0);
1426 G4ThreeVector Normal(0.0, 0.0, 1.0);
1428 G4double r = G4UniformRand();
1429 if (r > Reflectivity)
return true;
1461 G4double rand = G4UniformRand();
1462 G4double cosTheta =
sqrt(1.0 - rand);
1463 G4double sinTheta =
sqrt(rand);
1464 G4double Phi = 2.0 *
utl::kPi * G4UniformRand();
1465 G4double sinThetaCosPhi = sinTheta * cos(Phi);
1466 G4double sinThetaSinPhi = sinTheta * sin(Phi);
1467 G4double X = Normal.x();
1468 G4double Y = Normal.y();
1469 G4double W =
sqrt((X * X) + (Y * Y));
1470 G4double Vx = (X * cosTheta) - (Y * sinThetaSinPhi / W);
1471 G4double Vy = (Y * cosTheta) + (X * sinThetaSinPhi / W);
1472 G4double Vz = -W * sinThetaCosPhi;
1483 G4double rand = G4UniformRand();
1484 G4double cosTheta =
sqrt(1.0 - rand);
1485 G4double sinTheta =
sqrt(rand);
1486 G4double Phi = 2.0 *
utl::kPi * G4UniformRand();
1487 G4double Vx = sinTheta * cos(Phi);
1488 G4double Vy = sinTheta * sin(Phi);
1489 G4double Vz = Normal.z() * cosTheta;
1503 fPhotonMomentum /= fPhotonMomentum.mag();
1510 G4double Alpha, Phi;
1511 G4ThreeVector TrialMomentum;
1512 G4ThreeVector FacetNormal;
1513 G4double DotProduct;
1517 G4double sinAlpha, cosAlpha, sinAlphaSinPhi, sinAlphaCosPhi;
1518 G4double W, X, Y, Vx, Vy, Vz;
1523 sinAlpha = sin(Alpha);
1524 }
while (((G4UniformRand()*f_max) > sinAlpha) || (Alpha >= (0.5 *
utl::kPi)));
1525 Phi = 2.0 *
utl::kPi * G4UniformRand();
1526 cosAlpha = cos(Alpha);
1527 sinAlphaSinPhi = sinAlpha * sin(Phi);
1528 sinAlphaCosPhi = sinAlpha * cos(Phi);
1531 W =
sqrt((X * X) + (Y * Y));
1532 Vx = (X * cosAlpha) - (Y * sinAlphaSinPhi / W);
1533 Vy = (Y * cosAlpha) + (X * sinAlphaSinPhi / W);
1534 Vz = - W * sinAlphaCosPhi;
1535 FacetNormal.set(Vx, Vy, Vz);
1537 }
while (DotProduct >= 0.0);
1539 }
while (TrialMomentum.dot(Normal) <= 0.0);
1544 fPhotonMomentum /= fPhotonMomentum.mag();
1551 G4double Alpha, Phi;
1552 G4ThreeVector TrialMomentum;
1553 G4ThreeVector FacetNormal;
1554 G4double DotProduct;
1556 G4double sinAlpha, cosAlpha;
1557 G4double Vx, Vy, Vz;
1562 sinAlpha = sin(Alpha);
1563 }
while (((G4UniformRand()*f_max) > sinAlpha) || (Alpha >= (0.5 *
utl::kPi)));
1565 Phi = 2.0 *
utl::kPi * G4UniformRand();
1566 cosAlpha = cos(Alpha);
1567 Vx = sinAlpha * cos(Phi);
1568 Vy = sinAlpha * sin(Phi);
1569 Vz = Normal.z() * cosAlpha;
1570 FacetNormal.set(Vx, Vy, Vz);
1572 }
while (DotProduct >= 0.0);
1575 }
while (TrialMomentum.dot(Normal) <= 0.0);
1580 fPhotonMomentum /= fPhotonMomentum.mag();
1594 G4double DistA, DistB;
1597 c = Pos.dot(Pos) - (r * r);
1599 if (d < 0.0)
return 1.0e99;
1604 if (DistB < DistA) {
1605 if(DistB > 0.0)
return DistB;
1611 if (DistB > 0.0)
return DistB;
1618 const G4double r1,
const G4double r2)
1621 G4double a1, a2,
b[3],
c[3], d[3], e, f,
g;
1631 c[0] = Pos.x()*Pos.x();
1632 c[1] = Pos.y()*Pos.y();
1633 c[2] = Pos.z()*Pos.z();
1638 e = (b[0]+b[1])/(r1*r1) + b[2]/(r2*r2);
1639 f = 2.*((d[0]+d[1])/(r1*r1) + d[2]/(r2*r2));
1640 g = (c[0]+c[1])/(r1*r1)+c[2]/(r2*r2) - 1.;
1643 if ( (f*f-4*e*g) < 0 ) {
1647 a1 = 1./(2*e) * ( -f +
sqrt(f*f-4*e*g) );
1648 a2 = 1./(2*e) * ( -f -
sqrt(f*f-4*e*g) );
static utl::TabulatedFunction fPmtdomeRINDEX
unsigned int GetNPoints() const
static double fInterfaceRadius
static utl::TabulatedFunction fLinerSpecularSpike
G4double GetAverageNumberOfPhotons(const G4DynamicParticle *, const G4Material *, const G4MaterialPropertyVector *) const
G4bool PropagateInInterface(G4int &)
static double fTankHeight
Detector description interface for Station-related data.
static utl::TabulatedFunction fDomeRIndex
static double fPMTRadiuszSq
static void GetDataFromConstruction()
void PropagateInTank(G4int)
static double fInterfaceRzmax
static double fTankThickness
void AddPhoton(const int nPMT, const double peTime) const
G4bool TransitionToDome(G4int)
G4TankFastCerenkov(const G4String &processName="Cerenkov")
ArrayIterator XEnd()
end of array of X
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
static utl::TabulatedFunction fLinerReflectivity
Class to hold collection (x,y) points and provide interpolation between them.
static G4ThreeVector fPMTPos[4]
void DiffuseScatterHorizontal(const G4ThreeVector &)
void LobeScatterVertical(const G4ThreeVector &)
void SetMaxNumPhotonsPerStep(const G4int)
G4double GetSphereIntersect(const G4ThreeVector &, const G4double) const
G4bool TransitionToInterface(G4int &)
static utl::TabulatedFunction fPmtdomeABSORPTION
static utl::TabulatedFunction fInterfaceABSORPTION
G4double fSampledMomentum
const PMT & GetPMT(const int id) const
Get specified PMT by id.
static G4double fRoofPos[4]
double pow(const double x, const unsigned int i)
static double fTankRadius
static utl::TabulatedFunction fLinerSPECULARSPIKECONSTANT
static double fPMTRadiusz
static utl::TabulatedFunction fLinerSPECULARLOBECONSTANT
G4bool IsApplicable(const G4ParticleDefinition &)
Exception for reporting variable out of valid range.
static utl::TabulatedFunction fLinerREFLECTIVITY
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
static double fDomeRadius
double GetCollectionEfficiency() const
Collection efficiency.
static double fTankRadius
double GetX(const CoordinateSystemPtr &coordinateSystem) const
static double fDomeRadiusSq
static utl::TabulatedFunction fLinerBACKSCATTERCONSTANT
void LobeScatterHorizontal(const G4ThreeVector &)
G4ThreeVector fPhotonMomentum
G4double GetContinuousStepLimit(const G4Track &, G4double, G4double, G4double &)
G4PhysicsTable * fThePhysicsTable
static utl::TabulatedFunction fLinerBackscatter
G4bool fTrackSecondariesFirst
double Beta(const double energy)
Calculate the electron energy versus the relativistic beta.
static utl::TabulatedFunction fInterfaceRINDEX
static double fInterfaceRadiusz
static utl::TabulatedFunction fInterfaceAbsLength
static utl::TabulatedFunction fLinerSpecularLobe
G4VParticleChange * AlongStepDoIt(const G4Track &, const G4Step &)
static double fInterfaceRadiuszSq
#define WARNING(message)
Macro for logging warning messages.
class that handles Geant4 SD simulation
ArrayIterator YBegin()
begin of array of Y
double GetY(const CoordinateSystemPtr &coordinateSystem) const
static double fTankRadiusSq
double Distance(const Point &p, const sdet::Station &s)
static utl::TabulatedFunction fDomeAbsLength
static const sdet::Station * GetCurrentDetectorStation()
static double fSIGMA_ALPHA
static double fSigmaAlpha
ArrayIterator XBegin()
begin of array of X
void DiffuseScatterVertical(const G4ThreeVector &)
const utl::TabulatedFunction & GetQuantumEfficiency() const
Quantum efficiency.
G4double GetEllipsoidIntersect(const G4ThreeVector &, const G4double, const G4double) const
static double fInterfaceRadiusSq
G4PhysicsTable * GetPhysicsTable() const
static double fDomeRadiusz
G4ThreeVector fPhotonPolarization
void BuildThePhysicsTable()
static utl::TabulatedFunction fQE
static double fTankHalfHeight
void DumpPhysicsTable() const
ArrayIterator YEnd()
end of array of Y
static double fDomeRadiuszSq
static utl::TabulatedFunction fWaterABSORPTION
static utl::TabulatedFunction fInterfaceRIndex
static double fTankHalfHeight
void SetTrackSecondariesFirst(const G4bool)
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
static double fTankThickness
G4bool PropagateInDome(G4int &)
#define ERROR(message)
Macro for logging error messages.
static double fInterfaceRmax
G4ThreeVector fPhotonPosition
void SpikeScatter(const G4ThreeVector &)
static double fPMTRadiusSq
G4TankSimulator * fG4TankSimulator
static utl::TabulatedFunction fWaterAbsLength