G4SPSPosDistribution.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00027 //
00028 // MODULE:        G4SPSPosDistribution.cc
00029 //
00030 // Version:      1.0
00031 // Date:         5/02/04
00032 // Author:       Fan Lei 
00033 // Organisation: QinetiQ ltd.
00034 // Customer:     ESA/ESTEC
00035 //
00037 //
00038 // CHANGE HISTORY
00039 // --------------
00040 //
00041 //
00042 // Version 1.0, 05/02/2004, Fan Lei, Created.
00043 //    Based on the G4GeneralParticleSource class in Geant4 v6.0
00044 //
00046 //
00047 
00048 #include "G4SPSPosDistribution.hh"
00049 
00050 #include "G4PhysicalConstants.hh"
00051 #include "Randomize.hh"
00052 #include "G4TransportationManager.hh"
00053 #include "G4VPhysicalVolume.hh"
00054 #include "G4PhysicalVolumeStore.hh"
00055 
00056 G4SPSPosDistribution::G4SPSPosDistribution()
00057   : posRndm(0)
00058 {
00059 
00060   // Initialise all variables
00061   // Position distribution Variables
00062 
00063   SourcePosType = "Point";
00064   Shape = "NULL";
00065   halfx = 0.;
00066   halfy = 0.;
00067   halfz = 0.;
00068   Radius = 0.;
00069   Radius0 = 0.;
00070   SR = 0.;
00071   SX = 0.;
00072   SY = 0.;
00073   ParAlpha = 0.;
00074   ParTheta = 0.;
00075   ParPhi = 0.;
00076   CentreCoords = G4ThreeVector(0., 0., 0.);
00077   Rotx = CLHEP::HepXHat;
00078   Roty = CLHEP::HepYHat;
00079   Rotz = CLHEP::HepZHat;
00080   Confine = false; //If true confines source distribution to VolName
00081   VolName = "NULL";
00082   SideRefVec1 = CLHEP::HepXHat; // x-axis
00083   SideRefVec2 = CLHEP::HepYHat; // y-axis
00084   SideRefVec3 = CLHEP::HepZHat; // z-axis
00085   verbosityLevel = 0 ;
00086   gNavigator = G4TransportationManager::GetTransportationManager()
00087     ->GetNavigatorForTracking();
00088 }
00089 
00090 G4SPSPosDistribution::~G4SPSPosDistribution()
00091 {
00092 }
00093 
00094 void G4SPSPosDistribution::SetPosDisType(G4String PosType)
00095 {
00096   SourcePosType = PosType;
00097 }
00098 
00099 void G4SPSPosDistribution::SetPosDisShape(G4String shapeType)
00100 {
00101   Shape = shapeType;
00102 }
00103 
00104 void G4SPSPosDistribution::SetCentreCoords(G4ThreeVector coordsOfCentre)
00105 {
00106   CentreCoords = coordsOfCentre;
00107 }
00108 
00109 void G4SPSPosDistribution::SetPosRot1(G4ThreeVector posrot1)
00110 {
00111   // This should be x'
00112   Rotx = posrot1;
00113   if(verbosityLevel == 2)
00114     {
00115       G4cout << "Vector x' " << Rotx << G4endl;
00116     }
00117   GenerateRotationMatrices();
00118 }
00119 
00120 void G4SPSPosDistribution::SetPosRot2(G4ThreeVector posrot2)
00121 {
00122   // This is a vector in the plane x'y' but need not
00123   // be y'
00124   Roty = posrot2;
00125   if(verbosityLevel == 2)
00126     {
00127       G4cout << "The vector in the x'-y' plane " << Roty << G4endl;
00128     }
00129   GenerateRotationMatrices();
00130 }
00131 
00132 void G4SPSPosDistribution::SetHalfX(G4double xhalf)
00133 {
00134   halfx = xhalf;
00135 }
00136 
00137 void G4SPSPosDistribution::SetHalfY(G4double yhalf)
00138 {
00139   halfy = yhalf;
00140 }
00141 
00142 void G4SPSPosDistribution::SetHalfZ(G4double zhalf)
00143 {
00144   halfz = zhalf;
00145 }
00146 
00147 void G4SPSPosDistribution::SetRadius(G4double rds)
00148 {
00149   Radius = rds;
00150 }
00151 
00152 void G4SPSPosDistribution::SetRadius0(G4double rds)
00153 {
00154   Radius0 = rds;
00155 }
00156 
00157 void G4SPSPosDistribution::SetBeamSigmaInR(G4double r)
00158 {
00159   SX = SY = r;
00160   SR = r;
00161 }
00162 
00163 void G4SPSPosDistribution::SetBeamSigmaInX(G4double r)
00164 {
00165   SX = r;
00166 }
00167 
00168 void G4SPSPosDistribution::SetBeamSigmaInY(G4double r)
00169 {
00170   SY = r;
00171 }
00172 
00173 void G4SPSPosDistribution::SetParAlpha(G4double paralp)
00174 {
00175   ParAlpha = paralp;
00176 }
00177 
00178 void G4SPSPosDistribution::SetParTheta(G4double parthe)
00179 {
00180   ParTheta = parthe;
00181 }
00182 
00183 void G4SPSPosDistribution::SetParPhi(G4double parphi)
00184 {
00185   ParPhi = parphi;
00186 }
00187 
00188 void G4SPSPosDistribution::GenerateRotationMatrices()
00189 {
00190   // This takes in 2 vectors, x' and one in the plane x'-y',
00191   // and from these takes a cross product to calculate z'.
00192   // Then a cross product is taken between x' and z' to give
00193   // y'.
00194   Rotx = Rotx.unit(); // x'
00195   Roty = Roty.unit(); // vector in x'y' plane
00196   Rotz = Rotx.cross(Roty); // z'
00197   Rotz = Rotz.unit();
00198   Roty = Rotz.cross(Rotx); // y'
00199   Roty = Roty.unit();
00200   if(verbosityLevel == 2)
00201     {
00202       G4cout << "The new axes, x', y', z' " << Rotx << " " << Roty << " " << Rotz << G4endl;
00203     }
00204 }
00205 
00206 void G4SPSPosDistribution::ConfineSourceToVolume(G4String Vname)
00207 {
00208   VolName = Vname;
00209   if(verbosityLevel == 2)
00210     G4cout << VolName << G4endl;
00211   G4VPhysicalVolume *tempPV      = NULL;
00212   G4PhysicalVolumeStore *PVStore = 0;
00213   G4String theRequiredVolumeName = VolName;
00214   PVStore      = G4PhysicalVolumeStore::GetInstance();
00215   G4int      i = 0;
00216   G4bool found = false;
00217   if(verbosityLevel == 2)
00218     G4cout << PVStore->size() << G4endl;
00219   while (!found && i<G4int(PVStore->size())) {
00220     tempPV = (*PVStore)[i];
00221     found  = tempPV->GetName() == theRequiredVolumeName;
00222     if(verbosityLevel == 2)
00223       G4cout << i << " " << " " << tempPV->GetName() << " " << theRequiredVolumeName << " " << found << G4endl;
00224     if (!found)
00225       {i++;}
00226   }
00227   // found = true then the volume exists else it doesnt.
00228   if(found == true)
00229     {
00230       if(verbosityLevel >= 1)
00231         G4cout << "Volume " << VolName << " exists" << G4endl;
00232       Confine = true;
00233     }
00234   else
00235     {
00236       G4cout << " **** Error: Volume does not exist **** " << G4endl;
00237       G4cout << " Ignoring confine condition" << G4endl;
00238       Confine = false;
00239       VolName = "NULL";
00240     }
00241 
00242 }
00243 
00244 void G4SPSPosDistribution::GeneratePointSource()
00245 {
00246   // Generates Points given the point source.
00247   if(SourcePosType == "Point")
00248     particle_position = CentreCoords;
00249   else
00250     if(verbosityLevel >= 1)
00251       G4cout << "Error SourcePosType is not set to Point" << G4endl;
00252 }
00253 
00254 void G4SPSPosDistribution::GeneratePointsInBeam()
00255 {
00256   G4double x, y, z;
00257 
00258   G4ThreeVector RandPos;
00259   G4double tempx, tempy, tempz;
00260   z = 0.;
00261   
00262   // Private Method to create points in a plane
00263   if(Shape == "Circle")
00264     {
00265       x = Radius + 100.;
00266       y = Radius + 100.;
00267       while(std::sqrt((x*x) + (y*y)) > Radius)
00268         {
00269           x = posRndm->GenRandX();
00270           y = posRndm->GenRandY();
00271 
00272           x = (x*2.*Radius) - Radius;
00273           y = (y*2.*Radius) - Radius;
00274         }
00275       x += G4RandGauss::shoot(0.0,SX) ;
00276       y += G4RandGauss::shoot(0.0,SY) ;
00277     }  
00278   else
00279     {
00280       // all other cases default to Rectangle case
00281       x = posRndm->GenRandX();
00282       y = posRndm->GenRandY();
00283       x = (x*2.*halfx) - halfx;
00284       y = (y*2.*halfy) - halfy;
00285       x += G4RandGauss::shoot(0.0,SX);
00286       y += G4RandGauss::shoot(0.0,SY);
00287     } 
00288   // Apply Rotation Matrix
00289   // x * Rotx, y * Roty and z * Rotz
00290   if(verbosityLevel >= 2)
00291     {
00292       G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
00293     }
00294   tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
00295   tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
00296   tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
00297   
00298   RandPos.setX(tempx);
00299   RandPos.setY(tempy);
00300   RandPos.setZ(tempz);
00301   
00302   // Translate
00303   particle_position = CentreCoords + RandPos;
00304   if(verbosityLevel >= 1)
00305     {
00306       if(verbosityLevel >= 2)
00307         {
00308           G4cout << "Rotated Position " << RandPos << G4endl;
00309         }
00310       G4cout << "Rotated and Translated position " << particle_position << G4endl;
00311     }
00312 }
00313 
00314 void G4SPSPosDistribution::GeneratePointsInPlane()
00315 {
00316   G4double x, y, z;
00317   G4double expression;
00318   G4ThreeVector RandPos;
00319   G4double tempx, tempy, tempz;
00320   x = y = z = 0.;
00321 
00322   if(SourcePosType != "Plane" && verbosityLevel >= 1)
00323     G4cout << "Error: SourcePosType is not Plane" << G4endl;
00324 
00325   // Private Method to create points in a plane
00326   if(Shape == "Circle")
00327     {
00328       x = Radius + 100.;
00329       y = Radius + 100.;
00330       while(std::sqrt((x*x) + (y*y)) > Radius)
00331         {
00332           x = posRndm->GenRandX();
00333           y = posRndm->GenRandY();
00334 
00335           x = (x*2.*Radius) - Radius;
00336           y = (y*2.*Radius) - Radius;
00337         }
00338     }
00339   else if(Shape == "Annulus")
00340     {
00341       x = Radius + 100.;
00342       y = Radius + 100.;
00343       while(std::sqrt((x*x) + (y*y)) > Radius || std::sqrt((x*x) + (y*y)) < Radius0 )
00344         {
00345           x = posRndm->GenRandX();
00346           y = posRndm->GenRandY();
00347 
00348           x = (x*2.*Radius) - Radius;
00349           y = (y*2.*Radius) - Radius;
00350         }
00351     }
00352   else if(Shape == "Ellipse")
00353     {
00354       expression = 20.;
00355       while(expression > 1.)
00356         {
00357           x = posRndm->GenRandX();
00358           y = posRndm->GenRandY();
00359 
00360           x = (x*2.*halfx) - halfx;
00361           y = (y*2.*halfy) - halfy;
00362 
00363           expression = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy));
00364         }
00365     }
00366   else if(Shape == "Square")
00367     {
00368       x = posRndm->GenRandX();
00369       y = posRndm->GenRandY();
00370       x = (x*2.*halfx) - halfx;
00371       y = (y*2.*halfy) - halfy;
00372     }
00373   else if(Shape == "Rectangle")
00374     {
00375       x = posRndm->GenRandX();
00376       y = posRndm->GenRandY();
00377       x = (x*2.*halfx) - halfx;
00378       y = (y*2.*halfy) - halfy;
00379     }
00380   else
00381     G4cout << "Shape not one of the plane types" << G4endl;
00382 
00383   // Apply Rotation Matrix
00384   // x * Rotx, y * Roty and z * Rotz
00385   if(verbosityLevel == 2)
00386     {
00387       G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
00388     }
00389   tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
00390   tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
00391   tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
00392 
00393   RandPos.setX(tempx);
00394   RandPos.setY(tempy);
00395   RandPos.setZ(tempz);
00396 
00397   // Translate
00398   particle_position = CentreCoords + RandPos;
00399   if(verbosityLevel >= 1)
00400     {
00401       if(verbosityLevel == 2)
00402         {
00403           G4cout << "Rotated Position " << RandPos << G4endl;
00404         }
00405       G4cout << "Rotated and Translated position " << particle_position << G4endl;
00406     }
00407 
00408   // For Cosine-Law make SideRefVecs = to Rotation matrix vectors
00409   SideRefVec1 = Rotx;
00410   SideRefVec2 = Roty;
00411   SideRefVec3 = Rotz;
00412   // If rotation matrix z' point to origin then invert the matrix
00413   // So that SideRefVecs point away.
00414   if((CentreCoords.x() > 0. && Rotz.x() < 0.)
00415      || (CentreCoords.x() < 0. && Rotz.x() > 0.)
00416      || (CentreCoords.y() > 0. && Rotz.y() < 0.)
00417      || (CentreCoords.y() < 0. && Rotz.y() > 0.)
00418      || (CentreCoords.z() > 0. && Rotz.z() < 0.)
00419      || (CentreCoords.z() < 0. && Rotz.z() > 0.))
00420     {
00421       // Invert y and z.
00422       SideRefVec2 = -SideRefVec2;
00423       SideRefVec3 = -SideRefVec3;
00424     }
00425   if(verbosityLevel == 2)
00426     {
00427       G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
00428     }
00429 }
00430 
00431 void G4SPSPosDistribution::GeneratePointsOnSurface()
00432 {
00433   //Private method to create points on a surface
00434   G4double theta, phi;
00435   G4double x, y, z;
00436   x = y = z = 0.;
00437   G4ThreeVector RandPos;
00438   //  G4double tempx, tempy, tempz;
00439 
00440   if(SourcePosType != "Surface" && verbosityLevel >= 1)
00441     G4cout << "Error SourcePosType not Surface" << G4endl;
00442 
00443   if(Shape == "Sphere")
00444     {
00445       // G4double tantheta;
00446       theta = posRndm->GenRandPosTheta();
00447       phi = posRndm->GenRandPosPhi();
00448       theta = std::acos(1. - 2.*theta); // theta isotropic
00449       phi = phi * 2. * pi;
00450       // tantheta = std::tan(theta);
00451       
00452       x = Radius * std::sin(theta) * std::cos(phi);
00453       y = Radius * std::sin(theta) * std::sin(phi);
00454       z = Radius * std::cos(theta);
00455       
00456       RandPos.setX(x);
00457       RandPos.setY(y);
00458       RandPos.setZ(z);
00459 
00460       // Cosine-law (not a good idea to use this here)
00461       G4ThreeVector zdash(x,y,z);
00462       zdash = zdash.unit();
00463       G4ThreeVector xdash = Rotz.cross(zdash);
00464       G4ThreeVector ydash = xdash.cross(zdash);
00465       SideRefVec1 = xdash.unit();
00466       SideRefVec2 = ydash.unit();
00467       SideRefVec3 = zdash.unit();
00468     }
00469   else if(Shape == "Ellipsoid")
00470     {
00471       G4double minphi, maxphi, middlephi;
00472       G4double answer, constant;
00473 
00474       constant = pi/(halfx*halfx) + pi/(halfy*halfy) + 
00475         twopi/(halfz*halfz);
00476       
00477       // simplified approach
00478       theta = posRndm->GenRandPosTheta();
00479       phi = posRndm->GenRandPosPhi();
00480       
00481       theta = std::acos(1. - 2.*theta);
00482       minphi = 0.;
00483       maxphi = twopi;
00484       while(maxphi-minphi > 0.)
00485         {
00486           middlephi = (maxphi+minphi)/2.;
00487           answer = (1./(halfx*halfx))*(middlephi/2. + std::sin(2*middlephi)/4.)
00488             + (1./(halfy*halfy))*(middlephi/2. - std::sin(2*middlephi)/4.)
00489                + middlephi/(halfz*halfz);
00490           answer = answer/constant;
00491           if(answer > phi) maxphi = middlephi;
00492           if(answer < phi) minphi = middlephi;
00493           if(std::fabs(answer-phi) <= 0.00001)
00494             {
00495               minphi = maxphi +1;
00496               phi = middlephi;
00497             }
00498         }
00499 
00500       x = std::sin(theta)*std::cos(phi);
00501       y = std::sin(theta)*std::sin(phi);
00502       z = std::cos(theta);
00503       // x,y and z form a unit vector. Put this onto the ellipse.
00504       G4double lhs;
00505       // solve for x
00506       G4double numYinX = y/x;
00507       G4double numZinX = z/x;
00508       G4double tempxvar;          
00509       tempxvar= 1./(halfx*halfx)+(numYinX*numYinX)/(halfy*halfy)
00510         + (numZinX*numZinX)/(halfz*halfz);
00511 
00512       tempxvar = 1./tempxvar;
00513       G4double coordx = std::sqrt(tempxvar);
00514   
00515       //solve for y
00516       G4double numXinY = x/y;
00517       G4double numZinY = z/y;
00518       G4double tempyvar;
00519       tempyvar=(numXinY*numXinY)/(halfx*halfx)+1./(halfy*halfy)
00520         +(numZinY*numZinY)/(halfz*halfz);
00521       tempyvar = 1./tempyvar;
00522       G4double coordy = std::sqrt(tempyvar);
00523       
00524       //solve for z
00525       G4double numXinZ = x/z;
00526       G4double numYinZ = y/z;
00527       G4double tempzvar;
00528       tempzvar=(numXinZ*numXinZ)/(halfx*halfx)
00529         +(numYinZ*numYinZ)/(halfy*halfy)+1./(halfz*halfz);
00530       tempzvar = 1./tempzvar;
00531       G4double coordz = std::sqrt(tempzvar);
00532 
00533       lhs = std::sqrt((coordx*coordx)/(halfx*halfx) + 
00534                  (coordy*coordy)/(halfy*halfy) + 
00535                  (coordz*coordz)/(halfz*halfz));
00536       
00537       if(std::fabs(lhs-1.) > 0.001 && verbosityLevel >= 1)
00538         G4cout << "Error: theta, phi not really on ellipsoid" << G4endl;
00539 
00540       // coordx, coordy and coordz are all positive
00541       G4double TestRandVar = G4UniformRand();
00542       if(TestRandVar > 0.5)
00543         {
00544           coordx = -coordx;
00545         }
00546       TestRandVar = G4UniformRand();
00547       if(TestRandVar > 0.5)
00548         {
00549           coordy = -coordy;
00550         }
00551       TestRandVar = G4UniformRand();
00552       if(TestRandVar > 0.5)
00553         {
00554           coordz = -coordz;
00555         }
00556 
00557       RandPos.setX(coordx);
00558       RandPos.setY(coordy);
00559       RandPos.setZ(coordz);
00560 
00561       // Cosine-law (not a good idea to use this here)
00562       G4ThreeVector zdash(coordx,coordy,coordz);
00563       zdash = zdash.unit();
00564       G4ThreeVector xdash = Rotz.cross(zdash);
00565       G4ThreeVector ydash = xdash.cross(zdash);
00566       SideRefVec1 = xdash.unit();
00567       SideRefVec2 = ydash.unit();
00568       SideRefVec3 = zdash.unit();
00569     }
00570   else if(Shape == "Cylinder")
00571     {
00572       G4double AreaTop, AreaBot, AreaLat;
00573       G4double AreaTotal, prob1, prob2, prob3;
00574       G4double testrand;
00575 
00576       // User giver Radius and z-half length
00577       // Calculate surface areas, maybe move this to 
00578       // a different routine.
00579 
00580       AreaTop = pi * Radius * Radius;
00581       AreaBot = AreaTop;
00582       AreaLat = 2. * pi * Radius * 2. * halfz;
00583       AreaTotal = AreaTop + AreaBot + AreaLat;
00584       
00585       prob1 = AreaTop / AreaTotal;
00586       prob2 = AreaBot / AreaTotal;
00587       prob3 = 1.00 - prob1 - prob2;
00588       if(std::fabs(prob3 - (AreaLat/AreaTotal)) >= 0.001)
00589         {
00590           if(verbosityLevel >= 1)
00591             G4cout << AreaLat/AreaTotal << " " << prob3<<G4endl;
00592           G4cout << "Error in prob3" << G4endl;
00593         }
00594 
00595       // Decide surface to calculate point on.
00596 
00597       testrand = G4UniformRand();
00598       if(testrand <= prob1)
00599         {
00600           //Point on Top surface
00601           z = halfz;
00602           x = Radius + 100.;
00603           y = Radius + 100.;
00604           while(((x*x)+(y*y)) > (Radius*Radius))
00605             {
00606               x = posRndm->GenRandX();
00607               y = posRndm->GenRandY();
00608 
00609               x = x * 2. * Radius;
00610               y = y * 2. * Radius;
00611               x = x - Radius;
00612               y = y - Radius;
00613             }
00614           // Cosine law
00615           SideRefVec1 = Rotx;
00616           SideRefVec2 = Roty;
00617           SideRefVec3 = Rotz;
00618         }
00619       else if((testrand > prob1) && (testrand <= (prob1 + prob2)))
00620         {
00621           //Point on Bottom surface
00622           z = -halfz;
00623           x = Radius + 100.;
00624           y = Radius + 100.;
00625           while(((x*x)+(y*y)) > (Radius*Radius))
00626             {
00627               x = posRndm->GenRandX();
00628               y = posRndm->GenRandY();
00629 
00630               x = x * 2. * Radius;
00631               y = y * 2. * Radius;
00632               x = x - Radius;
00633               y = y - Radius;
00634             }
00635           // Cosine law
00636           SideRefVec1 = Rotx;
00637           SideRefVec2 = -Roty;
00638           SideRefVec3 = -Rotz;
00639         }
00640       else if(testrand > (prob1+prob2))
00641         {
00642           G4double rand;
00643           //Point on Lateral Surface
00644 
00645           rand = posRndm->GenRandPosPhi();
00646           rand = rand * 2. * pi;
00647 
00648           x = Radius * std::cos(rand);
00649           y = Radius * std::sin(rand);
00650 
00651           z = posRndm->GenRandZ();
00652 
00653           z = z * 2. * halfz;
00654           z = z - halfz;
00655           
00656           // Cosine law
00657           G4ThreeVector zdash(x,y,0.);
00658           zdash = zdash.unit();
00659           G4ThreeVector xdash = Rotz.cross(zdash);
00660           G4ThreeVector ydash = xdash.cross(zdash);
00661           SideRefVec1 = xdash.unit();
00662           SideRefVec2 = ydash.unit();
00663           SideRefVec3 = zdash.unit();
00664         }
00665       else
00666         G4cout << "Error: testrand " << testrand << G4endl;
00667 
00668       RandPos.setX(x);
00669       RandPos.setY(y);
00670       RandPos.setZ(z);
00671 
00672     }
00673   else if(Shape == "Para")
00674     {
00675       G4double testrand;
00676       //Right Parallelepiped.
00677       // User gives x,y,z half lengths and ParAlpha
00678       // ParTheta and ParPhi
00679       // +x = <1, -x >1 & <2, +y >2 & <3, -y >3 &<4
00680       // +z >4 & < 5, -z >5 &<6.
00681       testrand = G4UniformRand();
00682       G4double AreaX = halfy * halfz * 4.;
00683       G4double AreaY = halfx * halfz * 4.;
00684       G4double AreaZ = halfx * halfy * 4.;
00685       G4double AreaTotal = 2*(AreaX + AreaY + AreaZ);
00686       G4double Probs[6];
00687       Probs[0] = AreaX/AreaTotal;
00688       Probs[1] = Probs[0] + AreaX/AreaTotal;
00689       Probs[2] = Probs[1] + AreaY/AreaTotal;
00690       Probs[3] = Probs[2] + AreaY/AreaTotal;
00691       Probs[4] = Probs[3] + AreaZ/AreaTotal;
00692       Probs[5] = Probs[4] + AreaZ/AreaTotal;
00693       
00694       x = posRndm->GenRandX();
00695       y = posRndm->GenRandY();
00696       z = posRndm->GenRandZ();
00697       
00698       x = x * halfx * 2.;
00699       x = x - halfx;
00700       y = y * halfy * 2.;
00701       y = y - halfy;
00702       z = z * halfz * 2.;
00703       z = z - halfz;
00704       // Pick a side first
00705       if(testrand < Probs[0])
00706         {
00707           // side is +x
00708           x = halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
00709           y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
00710           // z = z;
00711           // Cosine-law
00712           G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
00713                               halfz*std::tan(ParTheta)*std::sin(ParPhi), 
00714                               halfz/std::cos(ParPhi));
00715           G4ThreeVector ydash(halfy*std::tan(ParAlpha), -halfy, 0.0);
00716           xdash = xdash.unit();
00717           ydash = ydash.unit();
00718           G4ThreeVector zdash = xdash.cross(ydash);
00719           SideRefVec1 = xdash.unit();
00720           SideRefVec2 = ydash.unit();
00721           SideRefVec3 = zdash.unit();
00722         }
00723       else if(testrand >= Probs[0] && testrand < Probs[1])
00724         {
00725           // side is -x
00726           x = -halfx + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
00727           y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
00728           // z = z;
00729           // Cosine-law
00730           G4ThreeVector xdash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
00731                               halfz*std::tan(ParTheta)*std::sin(ParPhi), 
00732                               halfz/std::cos(ParPhi));
00733           G4ThreeVector ydash(halfy*std::tan(ParAlpha), halfy, 0.0);
00734           xdash = xdash.unit();
00735           ydash = ydash.unit();
00736           G4ThreeVector zdash = xdash.cross(ydash);
00737           SideRefVec1 = xdash.unit();
00738           SideRefVec2 = ydash.unit();
00739           SideRefVec3 = zdash.unit();
00740         }
00741       else if(testrand >= Probs[1] && testrand < Probs[2])
00742         {
00743           // side is +y
00744           x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + halfy*std::tan(ParAlpha);
00745           y = halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
00746           // z = z;
00747           // Cosine-law
00748           G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
00749                               halfz*std::tan(ParTheta)*std::sin(ParPhi), 
00750                               halfz/std::cos(ParPhi));
00751           ydash = ydash.unit();
00752           G4ThreeVector xdash = Roty.cross(ydash);
00753           G4ThreeVector zdash = xdash.cross(ydash);
00754           SideRefVec1 = xdash.unit();
00755           SideRefVec2 = -ydash.unit();
00756           SideRefVec3 = -zdash.unit();
00757         }
00758       else if(testrand >= Probs[2] && testrand < Probs[3])
00759         {
00760           // side is -y
00761           x = x + z*std::tan(ParTheta)*std::cos(ParPhi) - halfy*std::tan(ParAlpha);
00762           y = -halfy + z*std::tan(ParTheta)*std::sin(ParPhi);
00763           // z = z;
00764           // Cosine-law
00765           G4ThreeVector ydash(halfz*std::tan(ParTheta)*std::cos(ParPhi),
00766                               halfz*std::tan(ParTheta)*std::sin(ParPhi), 
00767                               halfz/std::cos(ParPhi));
00768           ydash = ydash.unit();
00769           G4ThreeVector xdash = Roty.cross(ydash);
00770           G4ThreeVector zdash = xdash.cross(ydash);
00771           SideRefVec1 = xdash.unit();
00772           SideRefVec2 = ydash.unit();
00773           SideRefVec3 = zdash.unit();
00774         }
00775       else if(testrand >= Probs[3] && testrand < Probs[4])
00776         {
00777           // side is +z
00778           z = halfz;
00779           y = y + halfz*std::sin(ParPhi)*std::tan(ParTheta);
00780           x = x + halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
00781           // Cosine-law
00782           SideRefVec1 = Rotx;
00783           SideRefVec2 = Roty;
00784           SideRefVec3 = Rotz;
00785         }
00786       else if(testrand >= Probs[4] && testrand < Probs[5])
00787         {
00788           // side is -z
00789           z = -halfz;
00790           y = y - halfz*std::sin(ParPhi)*std::tan(ParTheta);
00791           x = x - halfz*std::cos(ParPhi)*std::tan(ParTheta) + y*std::tan(ParAlpha);
00792           // Cosine-law
00793           SideRefVec1 = Rotx;
00794           SideRefVec2 = -Roty;
00795           SideRefVec3 = -Rotz;
00796         }
00797       else
00798         {
00799           G4cout << "Error: testrand out of range" << G4endl;
00800           if(verbosityLevel >= 1)
00801             G4cout << "testrand=" << testrand << " Probs[5]=" << Probs[5] <<G4endl;
00802         }
00803 
00804       RandPos.setX(x);
00805       RandPos.setY(y);
00806       RandPos.setZ(z);
00807     }
00808 
00809   // Apply Rotation Matrix
00810   // x * Rotx, y * Roty and z * Rotz
00811   if(verbosityLevel == 2)
00812     G4cout << "Raw position " << RandPos << G4endl;
00813 
00814   x=(RandPos.x()*Rotx.x())+(RandPos.y()*Roty.x())+(RandPos.z()*Rotz.x());
00815   y=(RandPos.x()*Rotx.y())+(RandPos.y()*Roty.y())+(RandPos.z()*Rotz.y());
00816   z=(RandPos.x()*Rotx.z())+(RandPos.y()*Roty.z())+(RandPos.z()*Rotz.z());
00817   
00818   RandPos.setX(x);
00819   RandPos.setY(y);
00820   RandPos.setZ(z);
00821 
00822   // Translate
00823   particle_position = CentreCoords + RandPos;
00824 
00825   if(verbosityLevel >= 1)
00826     {
00827       if(verbosityLevel == 2)
00828         G4cout << "Rotated position " << RandPos << G4endl;
00829       G4cout << "Rotated and translated position " << particle_position << G4endl;
00830     }
00831   if(verbosityLevel == 2)
00832     {
00833       G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
00834     }
00835 }
00836 
00837 void G4SPSPosDistribution::GeneratePointsInVolume()
00838 {
00839   G4ThreeVector RandPos;
00840   G4double tempx, tempy, tempz;
00841   G4double x, y, z;
00842   x = y = z = 0.;
00843   if(SourcePosType != "Volume" && verbosityLevel >= 1)
00844     G4cout << "Error SourcePosType not Volume" << G4endl;
00845   //Private method to create points in a volume
00846   if(Shape == "Sphere")
00847     {
00848       x = Radius*2.;
00849       y = Radius*2.;
00850       z = Radius*2.;
00851       while(((x*x)+(y*y)+(z*z)) > (Radius*Radius))
00852         {
00853           x = posRndm->GenRandX();
00854           y = posRndm->GenRandY();
00855           z = posRndm->GenRandZ();
00856 
00857           x = (x*2.*Radius) - Radius;
00858           y = (y*2.*Radius) - Radius;
00859           z = (z*2.*Radius) - Radius;
00860         }
00861     }
00862   else if(Shape == "Ellipsoid")
00863     {
00864       G4double temp;
00865       temp = 100.;
00866       while(temp > 1.)
00867         {
00868           x = posRndm->GenRandX();
00869           y = posRndm->GenRandY();
00870           z = posRndm->GenRandZ();
00871 
00872           x = (x*2.*halfx) - halfx;
00873           y = (y*2.*halfy) - halfy;
00874           z = (z*2.*halfz) - halfz;
00875           
00876           temp = ((x*x)/(halfx*halfx)) + ((y*y)/(halfy*halfy))
00877             + ((z*z)/(halfz*halfz));
00878         }
00879     }
00880   else if(Shape == "Cylinder")
00881     {
00882       x = Radius*2.;
00883       y = Radius*2.;
00884       while(((x*x)+(y*y)) > (Radius*Radius))
00885         {
00886           x = posRndm->GenRandX();
00887           y = posRndm->GenRandY();
00888           z = posRndm->GenRandZ();
00889 
00890           x = (x*2.*Radius) - Radius;
00891           y = (y*2.*Radius) - Radius;
00892           z = (z*2.*halfz) - halfz;
00893         }
00894     }
00895   else if(Shape == "Para")
00896     {
00897       x = posRndm->GenRandX();
00898       y = posRndm->GenRandY();
00899       z = posRndm->GenRandZ();
00900       x = (x*2.*halfx) - halfx;
00901       y = (y*2.*halfy) - halfy;
00902       z = (z*2.*halfz) - halfz;
00903       x = x + z*std::tan(ParTheta)*std::cos(ParPhi) + y*std::tan(ParAlpha);
00904       y = y + z*std::tan(ParTheta)*std::sin(ParPhi);
00905       // z = z;
00906     }
00907   else
00908     G4cout << "Error: Volume Shape Doesnt Exist" << G4endl;
00909 
00910   RandPos.setX(x);
00911   RandPos.setY(y);
00912   RandPos.setZ(z);
00913 
00914   // Apply Rotation Matrix
00915   // x * Rotx, y * Roty and z * Rotz
00916   tempx = (x * Rotx.x()) + (y * Roty.x()) + (z * Rotz.x());
00917   tempy = (x * Rotx.y()) + (y * Roty.y()) + (z * Rotz.y());
00918   tempz = (x * Rotx.z()) + (y * Roty.z()) + (z * Rotz.z());
00919 
00920   RandPos.setX(tempx);
00921   RandPos.setY(tempy);
00922   RandPos.setZ(tempz);
00923 
00924   // Translate
00925   particle_position = CentreCoords + RandPos;
00926 
00927   if(verbosityLevel == 2)
00928     {
00929       G4cout << "Raw position " << x << "," << y << "," << z << G4endl;
00930       G4cout << "Rotated position " << RandPos << G4endl;
00931     }
00932   if(verbosityLevel >= 1)
00933     G4cout << "Rotated and translated position " << particle_position << G4endl;
00934 
00935   // Cosine-law (not a good idea to use this here)
00936   G4ThreeVector zdash(tempx,tempy,tempz);
00937   zdash = zdash.unit();
00938   G4ThreeVector xdash = Rotz.cross(zdash);
00939   G4ThreeVector ydash = xdash.cross(zdash);
00940   SideRefVec1 = xdash.unit();
00941   SideRefVec2 = ydash.unit();
00942   SideRefVec3 = zdash.unit();
00943 
00944   if(verbosityLevel == 2)
00945     {
00946       G4cout << "Reference vectors for cosine-law " << SideRefVec1 << " " << SideRefVec2 << " " << SideRefVec3 << G4endl;
00947     } 
00948 }
00949 
00950 G4bool G4SPSPosDistribution::IsSourceConfined()
00951 {
00952   // Method to check point is within the volume specified
00953   if(Confine == false)
00954     G4cout << "Error: Confine is false" << G4endl;
00955   G4ThreeVector null(0.,0.,0.);
00956   G4ThreeVector *ptr;
00957   ptr = &null;
00958 
00959   // Check particle_position is within VolName, if so true, 
00960   // else false
00961   G4VPhysicalVolume *theVolume;
00962   theVolume=gNavigator->LocateGlobalPointAndSetup(particle_position,ptr,true);
00963   G4String theVolName = theVolume->GetName();
00964   if(theVolName == VolName)
00965     {
00966       if(verbosityLevel >= 1)
00967         G4cout << "Particle is in volume " << VolName << G4endl;
00968       return(true);
00969     }
00970   else
00971     return(false);
00972 }
00973 
00974 G4ThreeVector G4SPSPosDistribution::GenerateOne()
00975 {
00976   //
00977   G4bool srcconf = false;
00978   G4int LoopCount = 0;
00979   while(srcconf == false)
00980     {
00981       if(SourcePosType == "Point")
00982         GeneratePointSource();
00983       else if(SourcePosType == "Beam")
00984         GeneratePointsInBeam();
00985       else if(SourcePosType == "Plane")
00986         GeneratePointsInPlane();
00987       else if(SourcePosType == "Surface")
00988         GeneratePointsOnSurface();
00989       else if(SourcePosType == "Volume")
00990         GeneratePointsInVolume();
00991       else
00992         {
00993           G4cout << "Error: SourcePosType undefined" << G4endl;
00994           G4cout << "Generating point source" << G4endl;
00995           GeneratePointSource();
00996         }
00997       if(Confine == true)
00998         {
00999           srcconf = IsSourceConfined();
01000           // if source in confined srcconf = true terminating the loop
01001           // if source isnt confined srcconf = false and loop continues
01002         }
01003       else if(Confine == false)
01004         srcconf = true; // terminate loop
01005       LoopCount++;
01006       if(LoopCount == 100000)
01007         {
01008           G4cout << "*************************************" << G4endl;
01009           G4cout << "LoopCount = 100000" << G4endl;
01010           G4cout << "Either the source distribution >> confinement" << G4endl;
01011           G4cout << "or any confining volume may not overlap with" << G4endl;
01012           G4cout << "the source distribution or any confining volumes" << G4endl;
01013           G4cout << "may not exist"<< G4endl;
01014           G4cout << "If you have set confine then this will be ignored" <<G4endl;
01015           G4cout << "for this event." << G4endl;
01016           G4cout << "*************************************" << G4endl;
01017           srcconf = true; //Avoids an infinite loop
01018         }
01019     }
01020   return particle_position;
01021 }
01022 
01023 
01024 
01025 

Generated on Mon May 27 17:49:52 2013 for Geant4 by  doxygen 1.4.7