43G4SPSPosDistribution::thread_data_t::thread_data_t()
53 SourcePosType =
"Point";
82 SourcePosType = PosType;
92 CentreCoords = coordsOfCentre;
100 if(verbosityLevel == 2)
104 GenerateRotationMatrices();
112 if(verbosityLevel == 2)
114 G4cout <<
"The vector in the x'-y' plane " << Roty <<
G4endl;
116 GenerateRotationMatrices();
177 return SourcePosType;
223 return SourcePosType;
228 return ThreadData.
Get().CParticlePos;
233 return ThreadData.
Get().CSideRefVec1;
238 return ThreadData.
Get().CSideRefVec2;
243 return ThreadData.
Get().CSideRefVec3;
246void G4SPSPosDistribution::GenerateRotationMatrices()
254 Rotz = Rotx.
cross(Roty);
256 Roty =Rotz.
cross(Rotx);
258 if(verbosityLevel == 2)
260 G4cout <<
"The new axes, x', y', z' "
261 << Rotx <<
" " << Roty <<
" " << Rotz <<
G4endl;
268 if(verbosityLevel == 2) {
G4cout << VolName <<
G4endl; }
272 if(verbosityLevel >= 1)
273 {
G4cout <<
"Volume confinement is set off." <<
G4endl; }
280 if(verbosityLevel == 2) {
G4cout << PVStore->size() <<
G4endl; }
286 if (tempPV !=
nullptr)
288 if(verbosityLevel >= 1)
296 G4cout <<
" **** Error: Volume <" << VolName
297 <<
"> does not exist **** " <<
G4endl;
304void G4SPSPosDistribution::GeneratePointSource(
G4ThreeVector& pos)
308 if(SourcePosType ==
"Point")
314 if(verbosityLevel >= 1)
316 G4cerr <<
"Error SourcePosType is not set to Point" <<
G4endl;
321void G4SPSPosDistribution::GeneratePointsInBeam(
G4ThreeVector& pos)
331 if(Shape ==
"Circle")
335 while(std::sqrt((x*x) + (y*y)) > Radius)
340 x = (x*2.*Radius) - Radius;
341 y = (y*2.*Radius) - Radius;
343 x += G4RandGauss::shoot(0.0,SX) ;
344 y += G4RandGauss::shoot(0.0,SY) ;
352 x = (x*2.*halfx) - halfx;
353 y = (y*2.*halfy) - halfy;
354 x += G4RandGauss::shoot(0.0,SX);
355 y += G4RandGauss::shoot(0.0,SY);
361 if(verbosityLevel >= 2)
363 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
365 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
366 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
367 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
375 pos = CentreCoords + RandPos;
376 if(verbosityLevel >= 1)
378 if(verbosityLevel >= 2)
386void G4SPSPosDistribution::GeneratePointsInPlane(
G4ThreeVector& pos)
393 thread_data_t& td = ThreadData.
Get();
395 if(SourcePosType !=
"Plane" && verbosityLevel >= 1)
397 G4cerr <<
"Error: SourcePosType is not Plane" <<
G4endl;
402 if(Shape ==
"Circle")
406 while(std::sqrt((x*x) + (y*y)) > Radius)
411 x = (x*2.*Radius) - Radius;
412 y = (y*2.*Radius) - Radius;
415 else if(Shape ==
"Annulus")
419 while(std::sqrt((x*x) + (y*y)) > Radius
420 || std::sqrt((x*x) + (y*y)) < Radius0 )
425 x = (x*2.*Radius) - Radius;
426 y = (y*2.*Radius) - Radius;
429 else if(Shape ==
"Ellipse")
432 while(expression > 1.)
437 x = (x*2.*halfx) - halfx;
438 y = (y*2.*halfy) - halfy;
440 expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
443 else if(Shape ==
"Square")
447 x = (x*2.*halfx) - halfx;
448 y = (y*2.*halfy) - halfy;
450 else if(Shape ==
"Rectangle")
454 x = (x*2.*halfx) - halfx;
455 y = (y*2.*halfy) - halfy;
465 if(verbosityLevel == 2)
467 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
469 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
470 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
471 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
479 pos = CentreCoords + RandPos;
480 if(verbosityLevel >= 1)
482 if(verbosityLevel == 2)
492 td.CSideRefVec1 = Rotx;
493 td.CSideRefVec2 = Roty;
494 td.CSideRefVec3 = Rotz;
499 if((CentreCoords.
x() > 0. && Rotz.
x() < 0.)
500 || (CentreCoords.
x() < 0. && Rotz.
x() > 0.)
501 || (CentreCoords.
y() > 0. && Rotz.
y() < 0.)
502 || (CentreCoords.
y() < 0. && Rotz.
y() > 0.)
503 || (CentreCoords.
z() > 0. && Rotz.
z() < 0.)
504 || (CentreCoords.
z() < 0. && Rotz.
z() > 0.))
508 td.CSideRefVec2 = - td.CSideRefVec2;
509 td.CSideRefVec3 = - td.CSideRefVec3;
511 if(verbosityLevel == 2)
513 G4cout <<
"Reference vectors for cosine-law "
514 << td.CSideRefVec1<<
" " << td.CSideRefVec2
515 <<
" " << td.CSideRefVec3 <<
G4endl;
519void G4SPSPosDistribution::GeneratePointsOnSurface(
G4ThreeVector& pos)
529 thread_data_t& td = ThreadData.
Get();
530 if(SourcePosType !=
"Surface" && verbosityLevel >= 1)
535 if(Shape ==
"Sphere")
539 theta = std::acos(1. - 2.*theta);
542 x = Radius * std::sin(theta) * std::cos(phi);
543 y = Radius * std::sin(theta) * std::sin(phi);
544 z = Radius * std::cos(theta);
553 zdash = zdash.unit();
556 td.CSideRefVec1 = xdash.
unit();
557 td.CSideRefVec2 = ydash.
unit();
558 td.CSideRefVec3 = zdash.
unit();
560 else if(Shape ==
"Ellipsoid")
565 constant =
pi/(halfx*halfx) + pi/(halfy*halfy) + twopi/(halfz*halfz);
572 theta = std::acos(1. - 2.*theta);
575 while(maxphi-minphi > 0.)
577 middlephi = (maxphi+minphi)/2.;
578 answer = (1./(halfx*halfx))*(middlephi/2. + std::sin(2*middlephi)/4.)
579 + (1./(halfy*halfy))*(middlephi/2. - std::sin(2*middlephi)/4.)
580 + middlephi/(halfz*halfz);
581 answer = answer/constant;
582 if(answer > phi) maxphi = middlephi;
583 if(answer < phi) minphi = middlephi;
584 if(std::fabs(answer-phi) <= 0.00001)
593 x = std::sin(theta)*std::cos(phi);
594 y = std::sin(theta)*std::sin(phi);
604 tempxvar = 1./(halfx*halfx)+(numYinX*numYinX)/(halfy*halfy)
605 + (numZinX*numZinX)/(halfz*halfz);
606 tempxvar = 1./tempxvar;
607 G4double coordx = std::sqrt(tempxvar);
614 tempyvar = (numXinY*numXinY)/(halfx*halfx)+1./(halfy*halfy)
615 + (numZinY*numZinY)/(halfz*halfz);
616 tempyvar = 1./tempyvar;
617 G4double coordy = std::sqrt(tempyvar);
624 tempzvar = (numXinZ*numXinZ)/(halfx*halfx)
625 + (numYinZ*numYinZ)/(halfy*halfy)+1./(halfz*halfz);
626 tempzvar = 1./tempzvar;
627 G4double coordz = std::sqrt(tempzvar);
629 lhs = std::sqrt((coordx*coordx)/(halfx*halfx) +
630 (coordy*coordy)/(halfy*halfy) +
631 (coordz*coordz)/(halfz*halfz));
633 if(std::fabs(lhs-1.) > 0.001 && verbosityLevel >= 1)
635 G4cout <<
"Error: theta, phi not really on ellipsoid" <<
G4endl;
641 if(TestRandVar > 0.5)
646 if(TestRandVar > 0.5)
651 if(TestRandVar > 0.5)
656 RandPos.
setX(coordx);
657 RandPos.
setY(coordy);
658 RandPos.
setZ(coordz);
663 zdash = zdash.unit();
666 td.CSideRefVec1 = xdash.
unit();
667 td.CSideRefVec2 = ydash.
unit();
668 td.CSideRefVec3 = zdash.
unit();
670 else if(Shape ==
"Cylinder")
673 G4double AreaTotal, prob1, prob2, prob3;
680 AreaTop =
pi * Radius * Radius;
682 AreaLat = 2. *
pi * Radius * 2. * halfz;
683 AreaTotal = AreaTop + AreaBot + AreaLat;
685 prob1 = AreaTop / AreaTotal;
686 prob2 = AreaBot / AreaTotal;
687 prob3 = 1.00 - prob1 - prob2;
688 if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
690 if(verbosityLevel >= 1)
700 if(testrand <= prob1)
705 while(((x*x)+(y*y)) > (Radius*Radius))
717 td.CSideRefVec1 = Rotx;
718 td.CSideRefVec2 = Roty;
719 td.CSideRefVec3 = Rotz;
721 else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
726 while(((x*x)+(y*y)) > (Radius*Radius))
738 td.CSideRefVec1 = Rotx;
739 td.CSideRefVec2 = -Roty;
740 td.CSideRefVec3 = -Rotz;
742 else if(testrand > (prob1+prob2))
747 rand = rand * 2. *
pi;
749 x = Radius * std::cos(rand);
750 y = Radius * std::sin(rand);
760 zdash = zdash.unit();
763 td.CSideRefVec1 = xdash.
unit();
764 td.CSideRefVec2 = ydash.
unit();
765 td.CSideRefVec3 = zdash.
unit();
776 else if(Shape ==
"EllipticCylinder")
778 G4double AreaTop, AreaBot, AreaLat, AreaTotal;
787 AreaTop =
pi * halfx * halfy;
795 h = ((halfx - halfy)*(halfx - halfy)) / ((halfx + halfy)*(halfx + halfy));
796 AreaLat = 2*halfz *
pi*(halfx + halfy)
797 * (1 + (3*h)/(10 + std::sqrt(4 - 3*h)));
798 AreaTotal = AreaTop + AreaBot + AreaLat;
800 prob1 = AreaTop / AreaTotal;
801 prob2 = AreaBot / AreaTotal;
802 prob3 = 1.00 - prob1 - prob2;
803 if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
805 if(verbosityLevel >= 1)
815 if(testrand <= prob1)
819 while(expression > 1.)
824 x = (x * 2. * halfx) - halfx;
825 y = (y * 2. * halfy) - halfy;
827 expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
830 else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
834 while(expression > 1.)
839 x = (x * 2. * halfx) - halfx;
840 y = (y * 2. * halfy) - halfy;
842 expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
845 else if(testrand > (prob1+prob2))
850 rand = rand * 2. *
pi;
852 x = halfx * std::cos(rand);
853 y = halfy * std::sin(rand);
857 z = (z * 2. * halfz) - halfz;
871 zdash = zdash.unit();
874 td.CSideRefVec1 = xdash.
unit();
875 td.CSideRefVec2 = ydash.
unit();
876 td.CSideRefVec3 = zdash.
unit();
878 else if(Shape ==
"Para")
887 G4double AreaX = halfy * halfz * 4.;
888 G4double AreaY = halfx * halfz * 4.;
889 G4double AreaZ = halfx * halfy * 4.;
890 G4double AreaTotal = 2*(AreaX + AreaY + AreaZ);
892 Probs[0] = AreaX/AreaTotal;
893 Probs[1] = Probs[0] + AreaX/AreaTotal;
894 Probs[2] = Probs[1] + AreaY/AreaTotal;
895 Probs[3] = Probs[2] + AreaY/AreaTotal;
896 Probs[4] = Probs[3] + AreaZ/AreaTotal;
897 Probs[5] = Probs[4] + AreaZ/AreaTotal;
912 if(testrand < Probs[0])
916 x = halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
917 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
922 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
923 halfz*std::tan(ParTheta)*std::sin(ParPhi),
924 halfz/std::cos(ParPhi));
926 xdash = xdash.
unit();
927 ydash = ydash.
unit();
929 td.CSideRefVec1 = xdash.
unit();
930 td.CSideRefVec2 = ydash.
unit();
931 td.CSideRefVec3 = zdash.
unit();
933 else if(testrand >= Probs[0] && testrand < Probs[1])
937 x = -halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
938 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
943 G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
944 halfz*std::tan(ParTheta)*std::sin(ParPhi),
945 halfz/std::cos(ParPhi));
947 xdash = xdash.
unit();
948 ydash = ydash.
unit();
950 td.CSideRefVec1 = xdash.
unit();
951 td.CSideRefVec2 = ydash.
unit();
952 td.CSideRefVec3 = zdash.
unit();
954 else if(testrand >= Probs[1] && testrand < Probs[2])
958 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + halfy*std::tan(ParAlpha);
959 y = halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
964 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
965 halfz*std::tan(ParTheta)*std::sin(ParPhi),
966 halfz/std::cos(ParPhi));
967 ydash = ydash.
unit();
970 td.CSideRefVec1 = xdash.
unit();
971 td.CSideRefVec2 = -ydash.
unit();
972 td.CSideRefVec3 = -zdash.
unit();
974 else if(testrand >= Probs[2] && testrand < Probs[3])
978 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) - halfy*std::tan(ParAlpha);
979 y = -halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
984 G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
985 halfz*std::tan(ParTheta)*std::sin(ParPhi),
986 halfz/std::cos(ParPhi));
987 ydash = ydash.
unit();
990 td.CSideRefVec1 = xdash.
unit();
991 td.CSideRefVec2 = ydash.
unit();
992 td.CSideRefVec3 = zdash.
unit();
994 else if(testrand >= Probs[3] && testrand < Probs[4])
999 y = y + halfz*std::sin(ParPhi)*std::tan(ParTheta);
1000 x = x + halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
1004 td.CSideRefVec1 = Rotx;
1005 td.CSideRefVec2 = Roty;
1006 td.CSideRefVec3 = Rotz;
1008 else if(testrand >= Probs[4] && testrand < Probs[5])
1013 y = y - halfz*std::sin(ParPhi)*std::tan(ParTheta);
1014 x = x - halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
1018 td.CSideRefVec1 = Rotx;
1019 td.CSideRefVec2 = -Roty;
1020 td.CSideRefVec3 = -Rotz;
1025 if(verbosityLevel >= 1)
1027 G4cout <<
"testrand=" << testrand <<
" Probs[5]=" << Probs[5] <<
G4endl;
1039 if(verbosityLevel == 2)
1043 x=(RandPos.
x()*Rotx.
x())+(RandPos.
y()*Roty.
x())+(RandPos.
z()*Rotz.
x());
1044 y=(RandPos.
x()*Rotx.
y())+(RandPos.
y()*Roty.
y())+(RandPos.
z()*Rotz.
y());
1045 z=(RandPos.
x()*Rotx.
z())+(RandPos.
y()*Roty.
z())+(RandPos.
z()*Rotz.
z());
1053 pos = CentreCoords + RandPos;
1055 if(verbosityLevel >= 1)
1057 if(verbosityLevel == 2)
1063 if(verbosityLevel == 2)
1065 G4cout <<
"Reference vectors for cosine-law " << td.CSideRefVec1
1066 <<
" " << td.CSideRefVec2 <<
" " << td.CSideRefVec3 <<
G4endl;
1070void G4SPSPosDistribution::GeneratePointsInVolume(
G4ThreeVector& pos)
1078 if(SourcePosType !=
"Volume" && verbosityLevel >= 1)
1085 if(Shape ==
"Sphere")
1090 while(((x*x)+(y*y)+(z*z)) > (Radius*Radius))
1096 x = (x*2.*Radius) - Radius;
1097 y = (y*2.*Radius) - Radius;
1098 z = (z*2.*Radius) - Radius;
1101 else if(Shape ==
"Ellipsoid")
1111 x = (x*2.*halfx) - halfx;
1112 y = (y*2.*halfy) - halfy;
1113 z = (z*2.*halfz) - halfz;
1115 temp = ((x*x)/(halfx*halfx))+((y*y)/(halfy*halfy))+((z*z)/(halfz*halfz));
1118 else if(Shape ==
"Cylinder")
1122 while(((x*x)+(y*y)) > (Radius*Radius))
1128 x = (x*2.*Radius) - Radius;
1129 y = (y*2.*Radius) - Radius;
1130 z = (z*2.*halfz) - halfz;
1133 else if(Shape ==
"EllipticCylinder")
1136 while(expression > 1.)
1142 x = (x*2.*halfx) - halfx;
1143 y = (y*2.*halfy) - halfy;
1144 z = (z*2.*halfz) - halfz;
1146 expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
1149 else if(Shape ==
"Para")
1154 x = (x*2.*halfx) - halfx;
1155 y = (y*2.*halfy) - halfy;
1156 z = (z*2.*halfz) - halfz;
1157 x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
1158 y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
1163 G4cout <<
"Error: Volume Shape does not exist" <<
G4endl;
1173 tempx = (x * Rotx.
x()) + (y * Roty.
x()) + (z * Rotz.
x());
1174 tempy = (x * Rotx.
y()) + (y * Roty.
y()) + (z * Rotz.
y());
1175 tempz = (x * Rotx.
z()) + (y * Roty.
z()) + (z * Rotz.
z());
1177 RandPos.
setX(tempx);
1178 RandPos.
setY(tempy);
1179 RandPos.
setZ(tempz);
1183 pos = CentreCoords + RandPos;
1185 if(verbosityLevel == 2)
1187 G4cout <<
"Raw position " << x <<
"," << y <<
"," << z <<
G4endl;
1190 if(verbosityLevel >= 1)
1198 zdash = zdash.
unit();
1201 thread_data_t& td = ThreadData.
Get();
1202 td.CSideRefVec1 = xdash.
unit();
1203 td.CSideRefVec2 = ydash.
unit();
1204 td.CSideRefVec3 = zdash.
unit();
1205 if(verbosityLevel == 2)
1207 G4cout <<
"Reference vectors for cosine-law " << td.CSideRefVec1
1208 <<
" " << td.CSideRefVec2 <<
" " << td.CSideRefVec3 <<
G4endl;
1229 if(theVolume ==
nullptr) {
return false; }
1232 if(theVolName == VolName)
1234 if(verbosityLevel >= 1)
1236 G4cout <<
"Particle is in volume " << VolName <<
G4endl;
1249 G4int LoopCount = 0;
1252 if(SourcePosType ==
"Point")
1253 GeneratePointSource(localP);
1254 else if(SourcePosType ==
"Beam")
1255 GeneratePointsInBeam(localP);
1256 else if(SourcePosType ==
"Plane")
1257 GeneratePointsInPlane(localP);
1258 else if(SourcePosType ==
"Surface")
1259 GeneratePointsOnSurface(localP);
1260 else if(SourcePosType ==
"Volume")
1261 GeneratePointsInVolume(localP);
1265 msg <<
"Error: SourcePosType undefined\n";
1266 msg <<
"Generating point source\n";
1267 G4Exception(
"G4SPSPosDistribution::GenerateOne()",
1269 GeneratePointSource(localP);
1273 srcconf = IsSourceConfined(localP);
1282 if(LoopCount == 100000)
1285 msg <<
"LoopCount = 100000\n";
1286 msg <<
"Either the source distribution >> confinement\n";
1287 msg <<
"or any confining volume may not overlap with\n";
1288 msg <<
"the source distribution or any confining volumes\n";
1289 msg <<
"may not exist\n"<<
G4endl;
1290 msg <<
"If you have set confine then this will be ignored\n";
1291 msg <<
"for this event.\n" <<
G4endl;
1292 G4Exception(
"G4SPSPosDistribution::GenerateOne()",
1297 ThreadData.
Get().CParticlePos = localP;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
#define G4MUTEXDESTROY(mutex)
#define G4MUTEXINIT(mutex)
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
Hep3Vector cross(const Hep3Vector &) const
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=nullptr, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
static G4PhysicalVolumeStore * GetInstance()
G4VPhysicalVolume * GetVolume(const G4String &name, G4bool verbose=true, G4bool reverseSearch=false) const
G4double GetRadius() const
const G4ThreeVector & GetCentreCoords() const
G4double GetHalfZ() const
void SetParAlpha(G4double)
void SetPosRot2(const G4ThreeVector &)
void SetBeamSigmaInX(G4double)
void ConfineSourceToVolume(const G4String &)
void SetBiasRndm(G4SPSRandomGenerator *a)
const G4String & GetPosDisType() const
void SetPosDisShape(const G4String &)
void SetVerbosity(G4int a)
const G4ThreeVector & GetParticlePos() const
void SetCentreCoords(const G4ThreeVector &)
G4ThreeVector GenerateOne()
void SetBeamSigmaInR(G4double)
const G4String & GetSourcePosType() const
void SetRadius0(G4double)
const G4ThreeVector & GetSideRefVec2() const
G4double GetHalfX() const
void SetParTheta(G4double)
const G4String & GetPosDisShape() const
const G4ThreeVector & GetSideRefVec3() const
const G4ThreeVector & GetSideRefVec1() const
void SetPosRot1(const G4ThreeVector &)
G4double GetHalfY() const
void SetPosDisType(const G4String &)
void SetBeamSigmaInY(G4double)
G4double GenRandPosTheta()
static G4TransportationManager * GetTransportationManager()
G4Navigator * GetNavigatorForTracking() const
const G4String & GetName() const
DLL_API const Hep3Vector HepZHat
DLL_API const Hep3Vector HepXHat
DLL_API const Hep3Vector HepYHat