G4PhantomParameterisation.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 //
00026 //
00027 // $Id$
00028 // GEANT4 tag $ Name:$
00029 //
00030 // class G4PhantomParameterisation implementation
00031 //
00032 // May 2007 Pedro Arce,   first version
00033 //
00034 // --------------------------------------------------------------------
00035 
00036 #include "G4PhantomParameterisation.hh"
00037 
00038 #include "globals.hh"
00039 #include "G4VSolid.hh"
00040 #include "G4VPhysicalVolume.hh"
00041 #include "G4LogicalVolume.hh"
00042 #include "G4VVolumeMaterialScanner.hh"
00043 #include "G4GeometryTolerance.hh"
00044 
00045 //------------------------------------------------------------------
00046 G4PhantomParameterisation::G4PhantomParameterisation()
00047   : fVoxelHalfX(0.), fVoxelHalfY(0.), fVoxelHalfZ(0.),
00048     fNoVoxelX(0), fNoVoxelY(0), fNoVoxelZ(0), fNoVoxelXY(0), fNoVoxel(0),
00049     fMaterialIndices(0), fContainerSolid(0),
00050     fContainerWallX(0.), fContainerWallY(0.), fContainerWallZ(0.),
00051     bSkipEqualMaterials(true)
00052 {
00053   kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00054 }
00055 
00056 
00057 //------------------------------------------------------------------
00058 G4PhantomParameterisation::~G4PhantomParameterisation()
00059 {
00060 }
00061 
00062 
00063 //------------------------------------------------------------------
00064 void G4PhantomParameterisation::
00065 BuildContainerSolid( G4VPhysicalVolume *pMotherPhysical )
00066 {
00067   fContainerSolid = pMotherPhysical->GetLogicalVolume()->GetSolid();
00068   fContainerWallX = fNoVoxelX * fVoxelHalfX;
00069   fContainerWallY = fNoVoxelY * fVoxelHalfY;
00070   fContainerWallZ = fNoVoxelZ * fVoxelHalfZ;
00071 
00072   // CheckVoxelsFillContainer();
00073 }
00074 
00075 //------------------------------------------------------------------
00076 void G4PhantomParameterisation::
00077 BuildContainerSolid( G4VSolid *pMotherSolid )
00078 {
00079   fContainerSolid = pMotherSolid;
00080   fContainerWallX = fNoVoxelX * fVoxelHalfX;
00081   fContainerWallY = fNoVoxelY * fVoxelHalfY;
00082   fContainerWallZ = fNoVoxelZ * fVoxelHalfZ;
00083 
00084   // CheckVoxelsFillContainer();
00085 }
00086 
00087 
00088 //------------------------------------------------------------------
00089 void G4PhantomParameterisation::
00090 ComputeTransformation(const G4int copyNo, G4VPhysicalVolume *physVol ) const
00091 {
00092   // Voxels cannot be rotated, return translation
00093   //
00094   G4ThreeVector trans = GetTranslation( copyNo );
00095 
00096   physVol->SetTranslation( trans );
00097 }
00098 
00099 
00100 //------------------------------------------------------------------
00101 G4ThreeVector G4PhantomParameterisation::
00102 GetTranslation(const G4int copyNo ) const
00103 {
00104   CheckCopyNo( copyNo );
00105 
00106   size_t nx;
00107   size_t ny;
00108   size_t nz;
00109 
00110   ComputeVoxelIndices( copyNo, nx, ny, nz );
00111 
00112   G4ThreeVector trans( (2*nx+1)*fVoxelHalfX - fContainerWallX,
00113                        (2*ny+1)*fVoxelHalfY - fContainerWallY,
00114                        (2*nz+1)*fVoxelHalfZ - fContainerWallZ);
00115   return trans;
00116 }
00117 
00118 
00119 //------------------------------------------------------------------
00120 G4VSolid* G4PhantomParameterisation::
00121 ComputeSolid(const G4int, G4VPhysicalVolume *pPhysicalVol) 
00122 {
00123   return pPhysicalVol->GetLogicalVolume()->GetSolid();
00124 }
00125        
00126 
00127 //------------------------------------------------------------------
00128 G4Material* G4PhantomParameterisation::
00129 ComputeMaterial(const G4int copyNo, G4VPhysicalVolume *, const G4VTouchable *) 
00130 { 
00131   CheckCopyNo( copyNo );
00132   size_t matIndex = GetMaterialIndex(copyNo);
00133 
00134   return fMaterials[ matIndex ];
00135 }
00136 
00137 
00138 //------------------------------------------------------------------
00139 size_t G4PhantomParameterisation::
00140 GetMaterialIndex( size_t copyNo ) const
00141 {
00142   CheckCopyNo( copyNo );
00143 
00144   if( !fMaterialIndices ) { return 0; }
00145   return *(fMaterialIndices+copyNo);
00146 }
00147 
00148 
00149 //------------------------------------------------------------------
00150 size_t G4PhantomParameterisation::
00151 GetMaterialIndex( size_t nx, size_t ny, size_t nz ) const
00152 {
00153   size_t copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00154   return GetMaterialIndex( copyNo );
00155 }
00156 
00157 
00158 //------------------------------------------------------------------
00159 G4Material* G4PhantomParameterisation::GetMaterial( size_t nx, size_t ny, size_t nz) const
00160 {
00161   return fMaterials[GetMaterialIndex(nx,ny,nz)];
00162 }
00163 
00164 //------------------------------------------------------------------
00165 G4Material* G4PhantomParameterisation::GetMaterial( size_t copyNo ) const
00166 {
00167   return fMaterials[GetMaterialIndex(copyNo)];
00168 }
00169 
00170 //------------------------------------------------------------------
00171 void G4PhantomParameterisation::
00172 ComputeVoxelIndices(const G4int copyNo, size_t& nx,
00173                             size_t& ny, size_t& nz ) const
00174 {
00175   CheckCopyNo( copyNo );
00176   nx = size_t(copyNo%fNoVoxelX);
00177   ny = size_t( (copyNo/fNoVoxelX)%fNoVoxelY );
00178   nz = size_t(copyNo/fNoVoxelXY);
00179 }
00180 
00181 
00182 //------------------------------------------------------------------
00183 void G4PhantomParameterisation::
00184 CheckVoxelsFillContainer( G4double contX, G4double contY, G4double contZ ) const
00185 {
00186   G4double toleranceForWarning = 0.25*kCarTolerance;
00187 
00188   // Any bigger value than 0.25*kCarTolerance will give a warning in
00189   // G4NormalNavigation::ComputeStep(), because the Inverse of a container
00190   // translation that is Z+epsilon gives -Z+epsilon (and the maximum tolerance
00191   // in G4Box::Inside is 0.5*kCarTolerance
00192   //
00193   G4double toleranceForError = 1.*kCarTolerance;  
00194 
00195   // Any bigger value than kCarTolerance will give an error in GetReplicaNo()
00196   //
00197   if( std::fabs(contX-fNoVoxelX*fVoxelHalfX) >= toleranceForError
00198    || std::fabs(contY-fNoVoxelY*fVoxelHalfY) >= toleranceForError  
00199    || std::fabs(contZ-fNoVoxelZ*fVoxelHalfZ) >= toleranceForError )
00200   {
00201     std::ostringstream message;
00202     message << "Voxels do not fully fill the container: "
00203             << fContainerSolid->GetName() << G4endl
00204             << "        DiffX= " << contX-fNoVoxelX*fVoxelHalfX << G4endl
00205             << "        DiffY= " << contY-fNoVoxelY*fVoxelHalfY << G4endl
00206             << "        DiffZ= " << contZ-fNoVoxelZ*fVoxelHalfZ << G4endl
00207             << "        Maximum difference is: " << toleranceForError;
00208     G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
00209                 "GeomNav0002", FatalException, message);
00210 
00211   }
00212   else if( std::fabs(contX-fNoVoxelX*fVoxelHalfX) >= toleranceForWarning
00213         || std::fabs(contY-fNoVoxelY*fVoxelHalfY) >= toleranceForWarning  
00214         || std::fabs(contZ-fNoVoxelZ*fVoxelHalfZ) >= toleranceForWarning )
00215   {
00216     std::ostringstream message;
00217     message << "Voxels do not fully fill the container: "
00218             << fContainerSolid->GetName() << G4endl
00219             << "          DiffX= " << contX-fNoVoxelX*fVoxelHalfX << G4endl
00220             << "          DiffY= " << contY-fNoVoxelY*fVoxelHalfY << G4endl
00221             << "          DiffZ= " << contZ-fNoVoxelZ*fVoxelHalfZ << G4endl
00222             << "          Maximum difference is: " << toleranceForWarning;
00223     G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
00224                 "GeomNav1002", JustWarning, message);
00225   }
00226 }
00227   
00228  
00229 //------------------------------------------------------------------
00230 G4int G4PhantomParameterisation::
00231 GetReplicaNo( const G4ThreeVector& localPoint, const G4ThreeVector& localDir )
00232 {
00233 
00234   // Check first that point is really inside voxels
00235   //
00236   if( fContainerSolid->Inside( localPoint ) == kOutside )
00237   {
00238     std::ostringstream message;
00239     message << "Point outside voxels!" << G4endl
00240             << "        localPoint - " << localPoint
00241             << " - is outside container solid: "
00242             << fContainerSolid->GetName() << G4endl;
00243     G4Exception("G4PhantomParameterisation::GetReplicaNo()", "GeomNav0003",
00244                 FatalErrorInArgument, message);
00245   }
00246   
00247   // Check the voxel numbers corresponding to localPoint
00248   // When a particle is on a surface, it may be between -kCarTolerance and
00249   // +kCartolerance. By a simple distance as:
00250   //   G4int nx = G4int( (localPoint.x()+)/fVoxelHalfX/2.);
00251   // those between -kCartolerance and 0 will be placed on voxel N-1 and those
00252   // between 0 and kCarTolerance on voxel N.
00253   // To avoid precision problems place the tracks that are on the surface on
00254   // voxel N-1 if they have negative direction and on voxel N if they have
00255   // positive direction.
00256   // Add +kCarTolerance so that they are first placed on voxel N, and then
00257   // if the direction is negative substract 1
00258 
00259   G4double fx = (localPoint.x()+fContainerWallX+kCarTolerance)/(fVoxelHalfX*2.);
00260   G4int nx = G4int(fx);
00261 
00262   G4double fy = (localPoint.y()+fContainerWallY+kCarTolerance)/(fVoxelHalfY*2.);
00263   G4int ny = G4int(fy);
00264 
00265   G4double fz = (localPoint.z()+fContainerWallZ+kCarTolerance)/(fVoxelHalfZ*2.);
00266   G4int nz = G4int(fz);
00267 
00268   // If it is on the surface side, check the direction: if direction is
00269   // negative place it on the previous voxel (if direction is positive it is
00270   // already in the next voxel...). 
00271   // Correct also cases where n = -1 or n = fNoVoxel. It is always traced to be
00272   // due to multiple scattering: track is entering a voxel but multiple
00273   // scattering changes the angle towards outside
00274   //
00275   if( fx - nx < kCarTolerance/fVoxelHalfX )
00276   {
00277     if( localDir.x() < 0 )
00278     {
00279       if( nx != 0 )
00280       {
00281         nx -= 1;
00282       }
00283     }
00284     else
00285     {
00286       if( nx == G4int(fNoVoxelX) )  
00287       {
00288         nx -= 1;       
00289       }
00290     }
00291   }
00292   if( fy - ny < kCarTolerance/fVoxelHalfY )
00293   {
00294     if( localDir.y() < 0 )
00295     {
00296       if( ny != 0 )
00297       {
00298         ny -= 1;
00299       }
00300     }
00301     else
00302     {
00303       if( ny == G4int(fNoVoxelY) )  
00304       {
00305         ny -= 1;       
00306       }
00307     }
00308   }
00309   if( fz - nz < kCarTolerance/fVoxelHalfZ )
00310   {
00311     if( localDir.z() < 0 )
00312     {
00313       if( nz != 0 )
00314       {
00315         nz -= 1;
00316       }
00317     }
00318     else
00319     {
00320       if( nz == G4int(fNoVoxelZ) )  
00321       {
00322         nz -= 1;       
00323       }
00324     }
00325   }
00326   
00327   G4int copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00328 
00329   // Check if there are still errors 
00330   //
00331   G4bool isOK = true;
00332   if( nx < 0 )
00333   {
00334     nx = 0;
00335     isOK = false;
00336   }
00337   else if( nx >= G4int(fNoVoxelX) )
00338   {
00339     nx = fNoVoxelX-1;
00340     isOK = false;
00341   }
00342   if( ny < 0 )
00343   {
00344     ny = 0;
00345     isOK = false;
00346   }
00347   else if( ny >= G4int(fNoVoxelY) )
00348   {
00349     ny = fNoVoxelY-1;
00350     isOK = false;
00351   }
00352   if( nz < 0 )
00353   {
00354     nz = 0;
00355     isOK = false;
00356   }
00357   else if( nz >= G4int(fNoVoxelZ) )
00358   {
00359     nz = fNoVoxelZ-1;
00360     isOK = false;
00361   }
00362   if( !isOK )
00363   {
00364     std::ostringstream message;
00365     message << "Corrected the copy number! It was negative or too big" << G4endl
00366             << "          LocalPoint: " << localPoint << G4endl
00367             << "          LocalDir: " << localDir << G4endl
00368             << "          Voxel container size: " << fContainerWallX
00369             << " " << fContainerWallY << " " << fContainerWallZ << G4endl
00370             << "          LocalPoint - wall: "
00371             << localPoint.x()-fContainerWallX << " "
00372             << localPoint.y()-fContainerWallY << " "
00373             << localPoint.z()-fContainerWallZ;
00374     G4Exception("G4PhantomParameterisation::GetReplicaNo()",
00375                 "GeomNav1002", JustWarning, message);
00376     copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00377   }
00378 
00379   // CheckCopyNo( copyNo ); // not needed, just for debugging code
00380 
00381   return copyNo;
00382 }
00383 
00384 
00385 //------------------------------------------------------------------
00386 void G4PhantomParameterisation::CheckCopyNo( const G4int copyNo ) const
00387 { 
00388   if( copyNo < 0 || copyNo >= G4int(fNoVoxel) )
00389   {
00390     std::ostringstream message;
00391     message << "Copy number is negative or too big!" << G4endl
00392             << "        Copy number: " << copyNo << G4endl
00393             << "        Total number of voxels: " << fNoVoxel;
00394     G4Exception("G4PhantomParameterisation::CheckCopyNo()",
00395                 "GeomNav0002", FatalErrorInArgument, message);
00396   }
00397 }

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