59 G4SPSPosDistribution::thread_data_t::thread_data_t()
69 SourcePosType =
"Point";
99 SourcePosType = PosType;
109 CentreCoords = coordsOfCentre;
116 if(verbosityLevel == 2)
120 GenerateRotationMatrices();
128 if(verbosityLevel == 2)
130 G4cout <<
"The vector in the x'-y' plane " << Roty <<
G4endl;
132 GenerateRotationMatrices();
193 return SourcePosType;
238 return SourcePosType;
242 return ThreadData.
Get().CParticlePos;
246 return ThreadData.
Get().CSideRefVec1;
250 return ThreadData.
Get().CSideRefVec2;
254 return ThreadData.
Get().CSideRefVec3;
257 void G4SPSPosDistribution::GenerateRotationMatrices()
265 Rotz = Rotx.
cross(Roty);
267 Roty =Rotz.
cross(Rotx);
269 if(verbosityLevel == 2)
271 G4cout <<
"The new axes, x', y', z' " << Rotx <<
" " << Roty <<
" " << Rotz <<
G4endl;
278 if(verbosityLevel == 2)
282 G4String theRequiredVolumeName = VolName;
286 if(verbosityLevel == 2)
288 while (!found && i<
G4int(PVStore->size())) {
289 tempPV = (*PVStore)[i];
290 found = tempPV->
GetName() == theRequiredVolumeName;
291 if(verbosityLevel == 2)
292 G4cout << i <<
" " <<
" " << tempPV->
GetName() <<
" " << theRequiredVolumeName <<
" " << found <<
G4endl;
299 if(verbosityLevel >= 1)
305 G4cout <<
" **** Error: Volume does not exist **** " <<
G4endl;
316 if(SourcePosType ==
"Point")
319 if(verbosityLevel >= 1)
320 G4cerr <<
"Error SourcePosType is not set to Point" <<
G4endl;
323 void G4SPSPosDistribution::GeneratePointsInBeam(
G4ThreeVector& pos)
332 if(Shape ==
"Circle")
336 while(std::sqrt((x*x) + (y*y)) > Radius)
341 x = (x*2.*Radius) - Radius;
342 y = (y*2.*Radius) - Radius;
352 x = (x*2.*halfx) - halfx;
353 y = (y*2.*halfy) - halfy;
359 if(verbosityLevel >= 2)
361 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
363 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
364 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
365 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
372 pos = CentreCoords + RandPos;
373 if(verbosityLevel >= 1)
375 if(verbosityLevel >= 2)
379 G4cout <<
"Rotated and Translated position " << pos <<
G4endl;
383 void G4SPSPosDistribution::GeneratePointsInPlane(
G4ThreeVector& pos)
390 thread_data_t& td = ThreadData.
Get();
391 if(SourcePosType !=
"Plane" && verbosityLevel >= 1)
392 G4cerr <<
"Error: SourcePosType is not Plane" <<
G4endl;
395 if(Shape ==
"Circle")
399 while(std::sqrt((x*x) + (y*y)) > Radius)
404 x = (x*2.*Radius) - Radius;
405 y = (y*2.*Radius) - Radius;
408 else if(Shape ==
"Annulus")
412 while(std::sqrt((x*x) + (y*y)) > Radius || std::sqrt((x*x) + (y*y)) < Radius0 )
417 x = (x*2.*Radius) - Radius;
418 y = (y*2.*Radius) - Radius;
421 else if(Shape ==
"Ellipse")
424 while(expression > 1.)
429 x = (x*2.*halfx) - halfx;
430 y = (y*2.*halfy) - halfy;
432 expression = ((x*
x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
435 else if(Shape ==
"Square")
439 x = (x*2.*halfx) - halfx;
440 y = (y*2.*halfy) - halfy;
442 else if(Shape ==
"Rectangle")
446 x = (x*2.*halfx) - halfx;
447 y = (y*2.*halfy) - halfy;
454 if(verbosityLevel == 2)
456 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
458 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
459 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
460 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
467 pos = CentreCoords + RandPos;
468 if(verbosityLevel >= 1)
470 if(verbosityLevel == 2)
474 G4cout <<
"Rotated and Translated position " << pos <<
G4endl;
479 td.CSideRefVec1 = Rotx;
480 td.CSideRefVec2 = Roty;
481 td.CSideRefVec3 = Rotz;
485 if((CentreCoords.
x() > 0. && Rotz.
x() < 0.)
486 || (CentreCoords.
x() < 0. && Rotz.
x() > 0.)
487 || (CentreCoords.
y() > 0. && Rotz.
y() < 0.)
488 || (CentreCoords.
y() < 0. && Rotz.
y() > 0.)
489 || (CentreCoords.
z() > 0. && Rotz.
z() < 0.)
490 || (CentreCoords.
z() < 0. && Rotz.
z() > 0.))
493 td.CSideRefVec2 = - td.CSideRefVec2;
494 td.CSideRefVec3 = - td.CSideRefVec3;
497 if(verbosityLevel == 2)
499 G4cout <<
"Reference vectors for cosine-law " << td.CSideRefVec1<<
" " << td.CSideRefVec2<<
" " << td.CSideRefVec3<<
G4endl;
503 void G4SPSPosDistribution::GeneratePointsOnSurface(
G4ThreeVector& pos)
511 thread_data_t& td = ThreadData.
Get();
512 if(SourcePosType !=
"Surface" && verbosityLevel >= 1)
515 if(Shape ==
"Sphere")
520 theta = std::acos(1. - 2.*theta);
524 x = Radius * std::sin(theta) * std::cos(phi);
525 y = Radius * std::sin(theta) * std::sin(phi);
526 z = Radius * std::cos(theta);
534 zdash = zdash.unit();
537 td.CSideRefVec1 = xdash.
unit();
538 td.CSideRefVec2 = ydash.
unit();
539 td.CSideRefVec3 = zdash.
unit();
542 else if(Shape ==
"Ellipsoid")
547 constant =
pi/(halfx*halfx) +
pi/(halfy*halfy) +
554 theta = std::acos(1. - 2.*theta);
557 while(maxphi-minphi > 0.)
559 middlephi = (maxphi+minphi)/2.;
560 answer = (1./(halfx*halfx))*(middlephi/2. + std::sin(2*middlephi)/4.)
561 + (1./(halfy*halfy))*(middlephi/2. - std::sin(2*middlephi)/4.)
562 + middlephi/(halfz*halfz);
563 answer = answer/constant;
564 if(answer > phi) maxphi = middlephi;
565 if(answer < phi) minphi = middlephi;
566 if(std::fabs(answer-phi) <= 0.00001)
573 x = std::sin(theta)*std::cos(phi);
574 y = std::sin(theta)*std::sin(phi);
582 tempxvar= 1./(halfx*halfx)+(numYinX*numYinX)/(halfy*halfy)
583 + (numZinX*numZinX)/(halfz*halfz);
585 tempxvar = 1./tempxvar;
586 G4double coordx = std::sqrt(tempxvar);
592 tempyvar=(numXinY*numXinY)/(halfx*halfx)+1./(halfy*halfy)
593 +(numZinY*numZinY)/(halfz*halfz);
594 tempyvar = 1./tempyvar;
595 G4double coordy = std::sqrt(tempyvar);
601 tempzvar=(numXinZ*numXinZ)/(halfx*halfx)
602 +(numYinZ*numYinZ)/(halfy*halfy)+1./(halfz*halfz);
603 tempzvar = 1./tempzvar;
604 G4double coordz = std::sqrt(tempzvar);
606 lhs = std::sqrt((coordx*coordx)/(halfx*halfx) +
607 (coordy*coordy)/(halfy*halfy) +
608 (coordz*coordz)/(halfz*halfz));
610 if(std::fabs(lhs-1.) > 0.001 && verbosityLevel >= 1)
611 G4cout <<
"Error: theta, phi not really on ellipsoid" <<
G4endl;
615 if(TestRandVar > 0.5)
620 if(TestRandVar > 0.5)
625 if(TestRandVar > 0.5)
630 RandPos.
setX(coordx);
631 RandPos.
setY(coordy);
632 RandPos.
setZ(coordz);
636 zdash = zdash.unit();
639 td.CSideRefVec1 = xdash.
unit();
640 td.CSideRefVec2 = ydash.
unit();
641 td.CSideRefVec3 = zdash.
unit();
643 else if(Shape ==
"Cylinder")
646 G4double AreaTotal, prob1, prob2, prob3;
653 AreaTop =
pi * Radius * Radius;
655 AreaLat = 2. *
pi * Radius * 2. * halfz;
656 AreaTotal = AreaTop + AreaBot + AreaLat;
658 prob1 = AreaTop / AreaTotal;
659 prob2 = AreaBot / AreaTotal;
660 prob3 = 1.00 - prob1 - prob2;
661 if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
663 if(verbosityLevel >= 1)
671 if(testrand <= prob1)
677 while(((x*x)+(y*y)) > (Radius*Radius))
688 td.CSideRefVec1 = Rotx;
689 td.CSideRefVec2 = Roty;
690 td.CSideRefVec3 = Rotz;
692 else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
698 while(((x*x)+(y*y)) > (Radius*Radius))
709 td.CSideRefVec1 = Rotx;
710 td.CSideRefVec2 = -Roty;
711 td.CSideRefVec3 = -Rotz;
713 else if(testrand > (prob1+prob2))
719 rand = rand * 2. *
pi;
721 x = Radius * std::cos(rand);
722 y = Radius * std::sin(rand);
731 zdash = zdash.unit();
734 td.CSideRefVec1 = xdash.
unit();
735 td.CSideRefVec2 = ydash.
unit();
736 td.CSideRefVec3 = zdash.
unit();
746 else if(Shape ==
"Para")
755 G4double AreaX = halfy * halfz * 4.;
756 G4double AreaY = halfx * halfz * 4.;
757 G4double AreaZ = halfx * halfy * 4.;
758 G4double AreaTotal = 2*(AreaX + AreaY + AreaZ);
760 Probs[0] = AreaX/AreaTotal;
761 Probs[1] = Probs[0] + AreaX/AreaTotal;
762 Probs[2] = Probs[1] + AreaY/AreaTotal;
763 Probs[3] = Probs[2] + AreaY/AreaTotal;
764 Probs[4] = Probs[3] + AreaZ/AreaTotal;
765 Probs[5] = Probs[4] + AreaZ/AreaTotal;
778 if(testrand < Probs[0])
781 x = halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
782 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
785 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
786 halfz*std::tan(ParTheta)*std::sin(ParPhi),
787 halfz/std::cos(ParPhi));
789 xdash = xdash.
unit();
790 ydash = ydash.
unit();
792 td.CSideRefVec1 = xdash.
unit();
793 td.CSideRefVec2 = ydash.
unit();
794 td.CSideRefVec3 = zdash.
unit();
796 else if(testrand >= Probs[0] && testrand < Probs[1])
799 x = -halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
800 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
803 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
804 halfz*std::tan(ParTheta)*std::sin(ParPhi),
805 halfz/std::cos(ParPhi));
807 xdash = xdash.
unit();
808 ydash = ydash.
unit();
810 td.CSideRefVec1 = xdash.
unit();
811 td.CSideRefVec2 = ydash.
unit();
812 td.CSideRefVec3 = zdash.
unit();
814 else if(testrand >= Probs[1] && testrand < Probs[2])
817 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + halfy*std::tan(ParAlpha);
818 y = halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
821 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
822 halfz*std::tan(ParTheta)*std::sin(ParPhi),
823 halfz/std::cos(ParPhi));
824 ydash = ydash.
unit();
827 td.CSideRefVec1 = xdash.
unit();
828 td.CSideRefVec2 = -ydash.
unit();
829 td.CSideRefVec3 = -zdash.
unit();
831 else if(testrand >= Probs[2] && testrand < Probs[3])
834 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) - halfy*std::tan(ParAlpha);
835 y = -halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
838 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
839 halfz*std::tan(ParTheta)*std::sin(ParPhi),
840 halfz/std::cos(ParPhi));
841 ydash = ydash.
unit();
844 td.CSideRefVec1 = xdash.
unit();
845 td.CSideRefVec2 = ydash.
unit();
846 td.CSideRefVec3 = zdash.
unit();
848 else if(testrand >= Probs[3] && testrand < Probs[4])
852 y = y + halfz*std::sin(ParPhi)*std::tan(ParTheta);
853 x = x + halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
855 td.CSideRefVec1 = Rotx;
856 td.CSideRefVec2 = Roty;
857 td.CSideRefVec3 = Rotz;
859 else if(testrand >= Probs[4] && testrand < Probs[5])
863 y = y - halfz*std::sin(ParPhi)*std::tan(ParTheta);
864 x = x - halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
866 td.CSideRefVec1 = Rotx;
867 td.CSideRefVec2 = -Roty;
868 td.CSideRefVec3 = -Rotz;
873 if(verbosityLevel >= 1)
874 G4cout <<
"testrand=" << testrand <<
" Probs[5]=" << Probs[5] <<
G4endl;
884 if(verbosityLevel == 2)
887 x=(RandPos.
x()*Rotx.
x())+(RandPos.
y()*Roty.
x())+(RandPos.
z()*Rotz.
x());
888 y=(RandPos.
x()*Rotx.
y())+(RandPos.
y()*Roty.
y())+(RandPos.
z()*Rotz.
y());
889 z=(RandPos.
x()*Rotx.
z())+(RandPos.
y()*Roty.
z())+(RandPos.
z()*Rotz.
z());
896 pos = CentreCoords + RandPos;
898 if(verbosityLevel >= 1)
900 if(verbosityLevel == 2)
902 G4cout <<
"Rotated and translated position " << pos <<
G4endl;
904 if(verbosityLevel == 2)
906 G4cout <<
"Reference vectors for cosine-law " << td.CSideRefVec1 <<
" " << td.CSideRefVec2 <<
" " << td.CSideRefVec3 <<
G4endl;
910 void G4SPSPosDistribution::GeneratePointsInVolume(
G4ThreeVector& pos)
916 if(SourcePosType !=
"Volume" && verbosityLevel >= 1)
919 if(Shape ==
"Sphere")
924 while(((x*x)+(y*y)+(z*z)) > (Radius*Radius))
930 x = (x*2.*Radius) - Radius;
931 y = (y*2.*Radius) - Radius;
932 z = (z*2.*Radius) - Radius;
935 else if(Shape ==
"Ellipsoid")
945 x = (x*2.*halfx) - halfx;
946 y = (y*2.*halfy) - halfy;
947 z = (z*2.*halfz) - halfz;
949 temp = ((x*
x)/(halfx*halfx)) + ((y*y)/(halfy*halfy))
950 + ((z*
z)/(halfz*halfz));
953 else if(Shape ==
"Cylinder")
957 while(((x*x)+(y*y)) > (Radius*Radius))
963 x = (x*2.*Radius) - Radius;
964 y = (y*2.*Radius) - Radius;
965 z = (z*2.*halfz) - halfz;
968 else if(Shape ==
"Para")
973 x = (x*2.*halfx) - halfx;
974 y = (y*2.*halfy) - halfy;
975 z = (z*2.*halfz) - halfz;
976 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
977 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
989 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
990 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
991 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
998 pos = CentreCoords + RandPos;
1000 if(verbosityLevel == 2)
1002 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
1005 if(verbosityLevel >= 1)
1006 G4cout <<
"Rotated and translated position " << pos <<
G4endl;
1010 zdash = zdash.
unit();
1013 thread_data_t& td = ThreadData.
Get();
1014 td.CSideRefVec1 = xdash.
unit();
1015 td.CSideRefVec2 = ydash.
unit();
1016 td.CSideRefVec3 = zdash.
unit();
1017 if(verbosityLevel == 2)
1019 G4cout <<
"Reference vectors for cosine-law " << td.CSideRefVec1 <<
" " << td.CSideRefVec2 <<
" " << td.CSideRefVec3 <<
G4endl;
1026 if(Confine ==
false)
1037 if(!theVolume)
return(
false);
1039 if(theVolName == VolName)
1041 if(verbosityLevel >= 1)
1042 G4cout <<
"Particle is in volume " << VolName <<
G4endl;
1054 G4int LoopCount = 0;
1055 while(srcconf ==
false)
1057 if(SourcePosType ==
"Point")
1058 GeneratePointSource(localP);
1059 else if(SourcePosType ==
"Beam")
1060 GeneratePointsInBeam(localP);
1061 else if(SourcePosType ==
"Plane")
1062 GeneratePointsInPlane(localP);
1063 else if(SourcePosType ==
"Surface")
1064 GeneratePointsOnSurface(localP);
1065 else if(SourcePosType ==
"Volume")
1066 GeneratePointsInVolume(localP);
1070 msg <<
"Error: SourcePosType undefined\n";
1071 msg <<
"Generating point source\n";
1073 GeneratePointSource(localP);
1077 srcconf = IsSourceConfined(localP);
1081 else if(Confine ==
false)
1084 if(LoopCount == 100000)
1087 msg <<
"LoopCount = 100000\n";
1088 msg <<
"Either the source distribution >> confinement\n";
1089 msg <<
"or any confining volume may not overlap with\n";
1090 msg <<
"the source distribution or any confining volumes\n";
1091 msg <<
"may not exist\n"<<
G4endl;
1092 msg <<
"If you have set confine then this will be ignored\n";
1093 msg <<
"for this event.\n" <<
G4endl;
1098 ThreadData.
Get().CParticlePos=localP;
ThreeVector shoot(const G4int Ap, const G4int Af)
DLL_API const Hep3Vector HepZHat
G4ThreeVector GetSideRefVec2() const
void SetBiasRndm(G4SPSRandomGenerator *a)
void SetPosDisType(G4String)
void SetParTheta(G4double)
std::ostringstream G4ExceptionDescription
void SetBeamSigmaInX(G4double)
CLHEP::Hep3Vector G4ThreeVector
G4String GetPosDisShape() const
std::vector< ExP01TrackerHit * > a
G4Navigator * GetNavigatorForTracking() const
#define G4MUTEXINIT(mutex)
void SetParAlpha(G4double)
G4double GetRadius() const
static constexpr double twopi
static G4PhysicalVolumeStore * GetInstance()
G4double GetHalfY() const
G4GLOB_DLL std::ostream G4cout
void SetCentreCoords(G4ThreeVector)
void SetBeamSigmaInR(G4double)
const G4String & GetName() const
G4ThreeVector GetCentreCoords() const
void SetPosRot1(G4ThreeVector)
void SetPosDisShape(G4String)
DLL_API const Hep3Vector HepYHat
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4ThreeVector GetSideRefVec3() const
static G4TransportationManager * GetTransportationManager()
DLL_API const Hep3Vector HepXHat
void SetPosRot2(G4ThreeVector)
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
G4ThreeVector GetSideRefVec1() const
G4String GetPosDisType() const
G4ThreeVector GetParticlePos() const
static constexpr double pi
Hep3Vector cross(const Hep3Vector &) const
G4double GetHalfX() const
G4double GenRandPosTheta()
void ConfineSourceToVolume(G4String)
G4String GetSourcePosType() const
#define G4MUTEXDESTROY(mutex)
G4ThreeVector GenerateOne()
void SetRadius0(G4double)
static const G4double pos
void SetBeamSigmaInY(G4double)
void SetVerbosity(G4int a)
G4GLOB_DLL std::ostream G4cerr
G4double GetHalfZ() const