00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00040
00041
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.);
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
00074 G4bool ifound = true;
00075 if (volName != volumeName || copyN != copyNumber)
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
00094 G4ThreeVector vertex;
00095
00096
00097
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
00121 if (fSolid_type == "BoundingSphere")
00122 {
00123 G4bool point_in_volume = false;
00124 G4int iloop=0;
00125 while (!point_in_volume && iloop<10000)
00126 {
00127
00128 vertex = generatorUtil->pick_point_in_sphere(radius);
00129
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
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
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
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;
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
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.);
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
00281 G4bool ifound = true;
00282 if (volName != volumeName || copyN != copyNumber)
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
00301 G4ThreeVector vertex;
00302
00303 return vertex_world;
00304 }
00305
00306 G4VPhysicalVolume* MaGeGeneratorPositionSampling::FindTheDirectMother(G4VPhysicalVolume* vol)
00307 {
00308
00309 G4PhysicalVolumeStore* volumeStore = G4PhysicalVolumeStore::GetInstance();
00310 G4int nVolumes = (G4int) volumeStore->size();
00311 std::vector<G4VPhysicalVolume*> auxVect;
00312
00313 G4int i,j;
00314
00315 for (i=0; i<nVolumes; i++) {
00316 if ((*volumeStore)[i]->GetLogicalVolume()->IsAncestor(vol))
00317 {
00318
00319 auxVect.push_back((*volumeStore)[i]);
00320 }
00321 }
00322 G4int nAncestors = (G4int) auxVect.size();
00323 std::vector<G4VPhysicalVolume*>::iterator iter = auxVect.begin();
00324
00325
00326
00327 G4bool erased = false;
00328 while (nAncestors > 1) {
00329 erased = false;
00330
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
00340
00341 {
00342 iter += i;
00343 auxVect.erase(iter);
00344 erased = true;
00345 }
00346 if (erased) break;
00347 }
00348 if (erased) break;
00349 }
00350 nAncestors = (G4int) auxVect.size();
00351
00352 }
00353 return auxVect[0];
00354 }