Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Class Members | File Members

MaGeGeneratorPositionSampling.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * DISCLAIMER                                                       *
00004 // *                                                                  *
00005 // * Neither the authors of this software system, nor their employing *
00006 // * institutes,nor the agencies providing financial support for this *
00007 // * work  make  any representation or  warranty, express or implied, *
00008 // * regarding  this  software system or assume any liability for its *
00009 // * use.                                                             *
00010 // *                                                                  *
00011 // ********************************************************************
00012 //
00013 // This class is supposed to sample the position of the primary
00014 // particle randomly in a volume or on a surface. The actual
00015 // algorithms are not implemented, but the interfaces are ok
00016 //
00017 // History:
00018 // --------
00019 // 28 Oct 2004   L.Pandola    First implementation (interfaces ok)
00020 // 10 Nov 2004   Xiang        Implemented SampleUniformlyInVolume for Tubs 
00021 // 11 Nov 2004   Luciano      Added check if the sampled point is inside (now it should work also if 
00022 //                            the Tub has an asymmetric hole, as Ge detectors)
00023 // 19 Nov 2004   Luciano      A lot of changes: implemented a modified 
00024 //                            version of Dave Jordan algorithm
00025 //
00026 #include "generators/MaGeGeneratorPositionSampling.hh"
00027 #include "generators/MJGeneratorUtil.hh"
00028 #include "io/MJLogger.hh"
00029 #include "Randomize.hh"
00030 #include "G4LogicalVolume.hh"
00031 #include "G4PhysicalVolumeStore.hh"
00032 #include "G4SolidStore.hh"
00033 #include "G4Tubs.hh"
00034 #include "G4Box.hh"
00035 #include "G4VisExtent.hh"
00036 #include "G4Navigator.hh"
00037 #include "G4TransportationManager.hh"
00038 
00039 //Da mettere dentro:
00040 // intera catena di inclusioni
00041 // numero di copia
00042 
00043 MaGeGeneratorPositionSampling::MaGeGeneratorPositionSampling() :
00044   myVolume(0)
00045 {
00046   volumeName="NULL";
00047   myNavigator = G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking();
00048   generatorUtil = new MJGeneratorUtil();
00049   copyNumber = 0;
00050   fSolid_type = "NULL";
00051   radius = 0;
00052 
00053 }
00054 
00055 MaGeGeneratorPositionSampling::~MaGeGeneratorPositionSampling()
00056 {
00057   delete generatorUtil;
00058 }
00059 
00060 G4ThreeVector MaGeGeneratorPositionSampling::SampleUniformlyInVolume(G4String volName,G4int copyN)
00061 {
00062   MJLog(debugging) << "Starting SampleUniformlyInVolume" << endlog;
00063   G4ThreeVector vertex_world(0.,0.,0.); //vertex in world coordinates
00064   
00065   if (volName == "NULL") 
00066      {
00067        MJLog(warning) << 
00068         "The confinement is set but the volume was not specified" << endlog;
00069        MJLog(warning) << "Return default position" << endlog; 
00070        return vertex_world;
00071      }
00072 
00073   //Step 1: check if the volume changed since the last call
00074   G4bool ifound = true;
00075   if (volName != volumeName || copyN != copyNumber) //volume changed
00076     {  
00077       volumeName = volName;
00078       copyNumber = copyN;
00079       ifound = InitializeSamplingVolume();
00080       if (!ifound)
00081         {
00082           MJLog(warning) << 
00083             "The confinement is set but the volume was not specified" << endlog;
00084           MJLog(warning) << "Return default position" << endlog; 
00085           return vertex_world;
00086         }
00087       else 
00088         {
00089           MJLog(debugging) << "Volume initialized" << endlog;
00090         }
00091     }
00092 
00093   //Step 2: sample the point in the three cases
00094   G4ThreeVector vertex;       // vertex in local volume's coordinates
00095  
00096   //If the type is G4Box or G4Tubs it's not necessary 
00097   //to shoot and check many times
00098   if (fSolid_type == "G4Box") 
00099     {
00100       G4double x_lo = fSolid_par_arr[0];
00101       G4double x_hi = fSolid_par_arr[1];
00102       G4double y_lo = fSolid_par_arr[2];
00103       G4double y_hi = fSolid_par_arr[3];
00104       G4double z_lo = fSolid_par_arr[4];
00105       G4double z_hi = fSolid_par_arr[5];
00106       vertex = generatorUtil->pick_point_in_box(x_lo, x_hi, y_lo, y_hi, z_lo, z_hi);
00107       vertex_world = (GetGlobalRotation()*vertex) + GetGlobalTranslation();
00108     }
00109   if (fSolid_type == "G4Tubs")
00110     {
00111       G4double r1      = fSolid_par_arr[0];
00112       G4double r2      = fSolid_par_arr[1];
00113       G4double h       = fSolid_par_arr[2] * 2.0;
00114       G4double theta0  = fSolid_par_arr[3];
00115       G4double d_theta = fSolid_par_arr[4];
00116       vertex = generatorUtil->pick_point_in_annulus(r1, r2, h, theta0, d_theta);
00117       vertex_world = (GetGlobalRotation()*vertex) + GetGlobalTranslation();
00118     }
00119 
00120   //for other volumes and for non-located boxes/tubs one must instead shoot and try
00121   if (fSolid_type == "BoundingSphere")
00122     {
00123       G4bool point_in_volume = false;
00124       G4int iloop=0;
00125       while (!point_in_volume && iloop<10000) //prevents infinite loops
00126         {  
00127           // loop until point falls in physical vol.
00128           vertex = generatorUtil->pick_point_in_sphere(radius);
00129           //It is a sphere: no need to rotate!
00130           vertex_world = vertex + GetGlobalTranslation();
00131           G4VPhysicalVolume* pVol_sampled = 
00132             myNavigator->LocateGlobalPointAndSetup(vertex_world);
00133           if (pVol_sampled == myVolume) {
00134             point_in_volume = true;
00135           }
00136           iloop++;
00137         }
00138     }
00139 
00140   MJLog(debugging) << "Sampled vertex " << vertex_world.x() << " " << 
00141     vertex_world.y() << " " << vertex_world.z() << " mm" << endlog;
00142   MJLog(debugging) << "Volume: " <<  
00143     myNavigator->LocateGlobalPointAndSetup(vertex_world)->GetName() << endlog;
00144 
00145   if (myNavigator->LocateGlobalPointAndSetup(vertex_world) != myVolume) 
00146     MJLog(warning) << "The sampled point is not in the right volume!?!" << endlog;
00147 
00148   return vertex_world;
00149 }
00150 
00151 G4bool MaGeGeneratorPositionSampling::InitializeSamplingVolume()
00152 {
00153   MJLog(debugging) << "Starting InitializeSamplingVolume" << endlog;  
00154   MJLog(debugging) << "Volume to be found: " << volumeName << endlog; 
00155 
00156   //For now it works if there are no copies
00157   G4PhysicalVolumeStore* volumeStore = G4PhysicalVolumeStore::GetInstance();
00158   G4int nVolumes = (G4int) volumeStore->size();
00159   G4bool ifound = false;
00160   G4int nfound=0;
00161   G4int i;
00162   for (i=0; i<nVolumes; i++) {
00163     if ((*volumeStore)[i]->GetName() == volumeName) {
00164       ifound = true;
00165       nfound++;
00166       myVolume = (*volumeStore)[i];   
00167     }
00168   }
00169 
00170   if (nfound > 1) {
00171     ifound = false;
00172     MJLog(warning) << "The volume name is not unique: retrieve copy number" << endlog;
00173     for (i=0; i<nVolumes; i++) {
00174       if ((*volumeStore)[i]->GetName() == volumeName && 
00175           (*volumeStore)[i]->GetCopyNo() == copyNumber && !ifound){
00176         ifound = true;
00177         myVolume = (*volumeStore)[i];
00178       }
00179     }
00180   }
00181 
00182   if (!ifound) return ifound;
00183 
00184   MJLog(debugging) << "Found volume: " << myVolume->GetName() << ", copy " << myVolume->GetCopyNo() << 
00185     endlog;
00186  
00187   //Store the dimensions of solids for Tubs and Boxes
00188   G4VSolid* pSolid = myVolume->GetLogicalVolume()->GetSolid();
00189   fSolid_type = pSolid->GetEntityType();
00190 
00191   MJLog(debugging) << "pSolid->GetEntityType()= " << fSolid_type << endlog;
00192 
00193   if (fSolid_type == "G4Box") 
00194     {
00195       MJLog(debugging) << "Identified source solid type as G4Box." << endlog;
00196       MJLog(debugging) << "Geometry parameters for box shape follow:" << endlog;
00197       G4double x_half_length = ((G4Box*)pSolid)->GetXHalfLength();
00198       G4double y_half_length = ((G4Box*)pSolid)->GetYHalfLength();
00199       G4double z_half_length = ((G4Box*)pSolid)->GetZHalfLength();
00200       
00201       MJLog(debugging) << "X half-length (mm): " << x_half_length << endlog;
00202       MJLog(debugging) << "Y half-length (mm): " << y_half_length << endlog;
00203       MJLog(debugging) << "Z half-length (mm): " << z_half_length << endlog;
00204       
00205       fSolid_par_arr[0] = -x_half_length;
00206       fSolid_par_arr[1] =  x_half_length;
00207       fSolid_par_arr[2] = -y_half_length;
00208       fSolid_par_arr[3] =  y_half_length;
00209       fSolid_par_arr[4] = -z_half_length;
00210       fSolid_par_arr[5] =  z_half_length;
00211 
00212     }
00213     else if (fSolid_type == "G4Tubs") 
00214       {
00215         MJLog(debugging) << "Identified source solid type as G4Tubs." << endlog;
00216         MJLog(debugging) << "Geometry parameters for annulus shape follow:" << endlog;
00217         fSolid_par_arr[0] = ((G4Tubs*)pSolid)->GetInnerRadius();
00218         fSolid_par_arr[1] = ((G4Tubs*)pSolid)->GetOuterRadius();
00219         fSolid_par_arr[2] = ((G4Tubs*)pSolid)->GetZHalfLength();
00220         fSolid_par_arr[3] = ((G4Tubs*)pSolid)->GetStartPhiAngle();
00221         fSolid_par_arr[4] = ((G4Tubs*)pSolid)->GetDeltaPhiAngle();
00222         MJLog(debugging) << "Inner radius (mm):        " << fSolid_par_arr[0] << endlog;
00223         MJLog(debugging) << "Outer radius (mm):        " << fSolid_par_arr[1] << endlog;
00224         MJLog(debugging) << "Z half-length (mm):       " << fSolid_par_arr[2] << endlog;
00225         MJLog(debugging) << "Starting phi angle (rad): " << fSolid_par_arr[3] << endlog;
00226         MJLog(debugging) << "Delta phi angle (rad):    " << fSolid_par_arr[4] << endlog;
00227       }
00228   else {
00229     MJLog(debugging) << "The source volume solid is neither G4Box nor G4Tubs." << endlog;
00230     fSolid_type = "BoundingSphere";
00231   }
00232 
00233   //MJLog(debugging) << "Retrieving bounding sphere dimensions...." << endlog;
00234   radius = pSolid->GetExtent().GetExtentRadius();
00235   MJLog(debugging) << "Sphere for solid. " << "Radius " << radius/mm << " mm" << endlog;
00236 
00237   G4VPhysicalVolume* worldV = myNavigator->GetWorldVolume();
00238   if (!worldV) MJLog(error) << "World volume not defined" << endlog;
00239   
00240   G4VPhysicalVolume* testVolume = myVolume;
00241   G4ThreeVector globTrasl(0,0,0);
00242   G4RotationMatrix  rotM;   // Initialised to identity
00243   G4int iloop = 0;
00244   while (testVolume != worldV && iloop < nVolumes) 
00245     {
00246       MJLog(debugging) << "Going up: volume " << testVolume->GetName() << endlog;
00247       globTrasl = globTrasl + testVolume->GetObjectTranslation();
00248       rotM = (*(testVolume->GetObjectRotation())) * rotM;
00249       testVolume = FindTheDirectMother(testVolume);
00250       iloop++; 
00251     }
00252   SetGlobalRotation(rotM);
00253   SetGlobalTranslation(globTrasl);
00254   
00255   //Just dump infos
00256   MJLog(debugging) << "Global volume translation: " << 
00257     globTrasl.x() << " " << globTrasl.y() << " " << globTrasl.z() << " mm" << endlog;
00258   MJLog(debugging) << "Global volume rotation: " << endlog;
00259   for (i=0;i<3;i++) {
00260     MJLog(debugging) << rotM(i,0) << " " << rotM(i,1) << " " << rotM(i,2) << 
00261       endlog;
00262   }
00263   return ifound;
00264 }         
00265 
00266 G4ThreeVector MaGeGeneratorPositionSampling::SampleOnSurface(G4String volName,G4int copyN)
00267 {
00268   
00269   MJLog(debugging) << "Starting SampleOnSurface" << endlog;
00270   G4ThreeVector vertex_world(0.,0.,0.); //vertex in world coordinates
00271   
00272   if (volName == "NULL") 
00273      {
00274        MJLog(warning) << 
00275         "The confinement is set but the volume was not specified" << endlog;
00276        MJLog(warning) << "Return default position" << endlog; 
00277        return vertex_world;
00278      }
00279 
00280   //Step 1: check if the volume changed since the last call
00281   G4bool ifound = true;
00282   if (volName != volumeName || copyN != copyNumber) //volume changed
00283     {  
00284       volumeName = volName;
00285       copyNumber = copyN;
00286       ifound = InitializeSamplingVolume();
00287       if (!ifound)
00288         {
00289           MJLog(warning) << 
00290             "The confinement is set but the volume was not specified" << endlog;
00291           MJLog(warning) << "Return default position" << endlog; 
00292           return vertex_world;
00293         }
00294       else 
00295         {
00296           MJLog(debugging) << "Volume initialized" << endlog;
00297         }
00298     }
00299 
00300   //Step 2: sample the point in the three cases
00301   G4ThreeVector vertex;       // vertex in local volume's coordinates
00302  
00303   return vertex_world;
00304 }
00305 
00306 G4VPhysicalVolume* MaGeGeneratorPositionSampling::FindTheDirectMother(G4VPhysicalVolume* vol)
00307 {
00308   //Find the direct mother of vol
00309   G4PhysicalVolumeStore* volumeStore = G4PhysicalVolumeStore::GetInstance();
00310   G4int nVolumes = (G4int) volumeStore->size();
00311   std::vector<G4VPhysicalVolume*> auxVect; 
00312 
00313   G4int i,j;
00314   //1st step: look for all the ancestors
00315   for (i=0; i<nVolumes; i++) {
00316     if ((*volumeStore)[i]->GetLogicalVolume()->IsAncestor(vol)) 
00317       {
00318         //MJLog(debugging) << "Ancestor found: " << (*volumeStore)[i]->GetName() << endlog;
00319         auxVect.push_back((*volumeStore)[i]);
00320       }
00321   }
00322   G4int nAncestors = (G4int) auxVect.size();
00323   std::vector<G4VPhysicalVolume*>::iterator iter = auxVect.begin();
00324   //MJLog(debugging) << "Initial number of ancestors: " << nAncestors << endlog;
00325   
00326   //2nd step: remove the non-direct ancestors
00327   G4bool erased = false;
00328   while (nAncestors > 1) {
00329     erased = false;
00330     //MJLog(debugging) << "Number of ancestors: " << nAncestors << endlog;
00331     for (i=0;i<nAncestors;i++) 
00332       {
00333         for (j=0;j<nAncestors;j++) 
00334           {
00335             iter = auxVect.begin();
00336             G4VPhysicalVolume* vol1 = auxVect[i];
00337             G4VPhysicalVolume* vol2 = auxVect[j];
00338             if (vol1->GetLogicalVolume()->IsAncestor(vol2)) 
00339               //vol1 is ancestor of vol2
00340               //so vol1 is not a direct ancestor of the target volume!
00341               {
00342                 iter += i; //moves to the i-th element of the vector
00343                 auxVect.erase(iter); //removes vol1 from the list
00344                 erased = true;
00345               }
00346             if (erased) break;
00347           }
00348         if (erased) break;
00349       }
00350     nAncestors = (G4int) auxVect.size(); //updates the dimension of the list
00351     //Here ends the loop
00352   }
00353   return auxVect[0];
00354 }

Generated on Mon Nov 29 16:58:50 2004 for Majorana Simulation by  doxygen 1.3.9.1