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
00027
00028
00029
00030
00031
00032 #include "G4ios.hh"
00033 #include "G4ParallelWorldProcess.hh"
00034 #include "G4Step.hh"
00035 #include "G4StepPoint.hh"
00036 #include "G4Navigator.hh"
00037 #include "G4VTouchable.hh"
00038 #include "G4VPhysicalVolume.hh"
00039 #include "G4ParticleChange.hh"
00040 #include "G4PathFinder.hh"
00041 #include "G4TransportationManager.hh"
00042 #include "G4ParticleChange.hh"
00043 #include "G4StepPoint.hh"
00044 #include "G4FieldTrackUpdator.hh"
00045 #include "G4Material.hh"
00046 #include "G4ProductionCuts.hh"
00047 #include "G4ProductionCutsTable.hh"
00048
00049 #include "G4SDManager.hh"
00050 #include "G4VSensitiveDetector.hh"
00051
00052 G4Step* G4ParallelWorldProcess::fpHyperStep = 0;
00053 G4int G4ParallelWorldProcess::nParallelWorlds = 0;
00054 G4int G4ParallelWorldProcess::fNavIDHyp = 0;
00055 const G4Step* G4ParallelWorldProcess::GetHyperStep()
00056 { return fpHyperStep; }
00057 G4int G4ParallelWorldProcess::GetHypNavigatorID()
00058 { return fNavIDHyp; }
00059
00060 G4ParallelWorldProcess::
00061 G4ParallelWorldProcess(const G4String& processName,G4ProcessType theType)
00062 :G4VProcess(processName,theType), fGhostNavigator(0), fNavigatorID(-1),
00063 fFieldTrack('0'),layeredMaterialFlag(false)
00064 {
00065 if(!fpHyperStep) fpHyperStep = new G4Step();
00066 iParallelWorld = ++nParallelWorlds;
00067
00068 pParticleChange = &aDummyParticleChange;
00069
00070 fGhostStep = new G4Step();
00071 fGhostPreStepPoint = fGhostStep->GetPreStepPoint();
00072 fGhostPostStepPoint = fGhostStep->GetPostStepPoint();
00073
00074 fTransportationManager = G4TransportationManager::GetTransportationManager();
00075 fTransportationManager->GetNavigatorForTracking()->SetPushVerbosity(false);
00076 fPathFinder = G4PathFinder::GetInstance();
00077
00078 if (verboseLevel>0)
00079 {
00080 G4cout << GetProcessName() << " is created " << G4endl;
00081 }
00082 }
00083
00084 G4ParallelWorldProcess::~G4ParallelWorldProcess()
00085 {
00086 delete fGhostStep;
00087 nParallelWorlds--;
00088 if(nParallelWorlds==0)
00089 {
00090 delete fpHyperStep;
00091 fpHyperStep = 0;
00092 }
00093 }
00094
00095 void G4ParallelWorldProcess::
00096 SetParallelWorld(G4String parallelWorldName)
00097 {
00098 fGhostWorldName = parallelWorldName;
00099 fGhostWorld = fTransportationManager->GetParallelWorld(fGhostWorldName);
00100 fGhostNavigator = fTransportationManager->GetNavigator(fGhostWorld);
00101 fGhostNavigator->SetPushVerbosity(false);
00102 }
00103
00104 void G4ParallelWorldProcess::
00105 SetParallelWorld(G4VPhysicalVolume* parallelWorld)
00106 {
00107 fGhostWorldName = parallelWorld->GetName();
00108 fGhostWorld = parallelWorld;
00109 fGhostNavigator = fTransportationManager->GetNavigator(fGhostWorld);
00110 fGhostNavigator->SetPushVerbosity(false);
00111 }
00112
00113 void G4ParallelWorldProcess::StartTracking(G4Track* trk)
00114 {
00115 if(fGhostNavigator)
00116 { fNavigatorID = fTransportationManager->ActivateNavigator(fGhostNavigator); }
00117 else
00118 {
00119 G4Exception("G4ParallelWorldProcess::StartTracking",
00120 "ProcParaWorld000",FatalException,
00121 "G4ParallelWorldProcess is used for tracking without having a parallel world assigned");
00122 }
00123 fPathFinder->PrepareNewTrack(trk->GetPosition(),trk->GetMomentumDirection());
00124
00125 fOldGhostTouchable = fPathFinder->CreateTouchableHandle(fNavigatorID);
00126 fGhostPreStepPoint->SetTouchableHandle(fOldGhostTouchable);
00127 fNewGhostTouchable = fOldGhostTouchable;
00128 fGhostPostStepPoint->SetTouchableHandle(fNewGhostTouchable);
00129
00130 fGhostSafety = -1.;
00131 fOnBoundary = false;
00132 fGhostPreStepPoint->SetStepStatus(fUndefined);
00133 fGhostPostStepPoint->SetStepStatus(fUndefined);
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 *(fpHyperStep->GetPostStepPoint()) = *(trk->GetStep()->GetPostStepPoint());
00144 if(layeredMaterialFlag)
00145 {
00146 G4StepPoint* realWorldPostStepPoint = trk->GetStep()->GetPostStepPoint();
00147 SwitchMaterial(realWorldPostStepPoint);
00148 }
00149 *(fpHyperStep->GetPreStepPoint()) = *(fpHyperStep->GetPostStepPoint());
00150 }
00151
00152 G4double
00153 G4ParallelWorldProcess::AtRestGetPhysicalInteractionLength(
00154 const G4Track& ,
00155 G4ForceCondition* condition)
00156 {
00157
00158
00159
00160
00161 *condition = Forced;
00162 return DBL_MAX;
00163 }
00164
00165 G4VParticleChange* G4ParallelWorldProcess::AtRestDoIt(
00166 const G4Track& track,
00167 const G4Step& step)
00168 {
00169
00170
00171
00172
00173 fOldGhostTouchable = fGhostPostStepPoint->GetTouchableHandle();
00174 G4VSensitiveDetector* aSD = 0;
00175 if(fOldGhostTouchable->GetVolume())
00176 { aSD = fOldGhostTouchable->GetVolume()->GetLogicalVolume()->GetSensitiveDetector(); }
00177 fOnBoundary = false;
00178 if(aSD)
00179 {
00180 CopyStep(step);
00181 fGhostPreStepPoint->SetSensitiveDetector(aSD);
00182
00183 fNewGhostTouchable = fOldGhostTouchable;
00184
00185 fGhostPreStepPoint->SetTouchableHandle(fOldGhostTouchable);
00186 fGhostPostStepPoint->SetTouchableHandle(fNewGhostTouchable);
00187 if(fNewGhostTouchable->GetVolume())
00188 {
00189 fGhostPostStepPoint->SetSensitiveDetector(
00190 fNewGhostTouchable->GetVolume()->GetLogicalVolume()->GetSensitiveDetector());
00191 }
00192 else
00193 { fGhostPostStepPoint->SetSensitiveDetector(0); }
00194
00195 aSD->Hit(fGhostStep);
00196 }
00197
00198 pParticleChange->Initialize(track);
00199 return pParticleChange;
00200 }
00201
00202 G4double
00203 G4ParallelWorldProcess::PostStepGetPhysicalInteractionLength(
00204 const G4Track& ,
00205 G4double ,
00206 G4ForceCondition* condition)
00207 {
00208 *condition = StronglyForced;
00209 return DBL_MAX;
00210 }
00211
00212 G4VParticleChange* G4ParallelWorldProcess::PostStepDoIt(
00213 const G4Track& track,
00214 const G4Step& step)
00215 {
00216 fOldGhostTouchable = fGhostPostStepPoint->GetTouchableHandle();
00217 G4VSensitiveDetector* aSD = 0;
00218 if(fOldGhostTouchable->GetVolume())
00219 { aSD = fOldGhostTouchable->GetVolume()->GetLogicalVolume()->GetSensitiveDetector(); }
00220 CopyStep(step);
00221 fGhostPreStepPoint->SetSensitiveDetector(aSD);
00222
00223 if(fOnBoundary)
00224 {
00225 fNewGhostTouchable = fPathFinder->CreateTouchableHandle(fNavigatorID);
00226 }
00227 else
00228 {
00229 fNewGhostTouchable = fOldGhostTouchable;
00230 }
00231
00232 fGhostPreStepPoint->SetTouchableHandle(fOldGhostTouchable);
00233 fGhostPostStepPoint->SetTouchableHandle(fNewGhostTouchable);
00234
00235 if(fNewGhostTouchable->GetVolume())
00236 {
00237 fGhostPostStepPoint->SetSensitiveDetector(
00238 fNewGhostTouchable->GetVolume()->GetLogicalVolume()->GetSensitiveDetector());
00239 }
00240 else
00241 { fGhostPostStepPoint->SetSensitiveDetector(0); }
00242
00243 G4VSensitiveDetector* sd = fGhostPreStepPoint->GetSensitiveDetector();
00244 if(sd)
00245 {
00246 sd->Hit(fGhostStep);
00247 }
00248
00249 pParticleChange->Initialize(track);
00250 if(layeredMaterialFlag)
00251 {
00252 G4StepPoint* realWorldPostStepPoint =
00253 ((G4Step*)(track.GetStep()))->GetPostStepPoint();
00254 SwitchMaterial(realWorldPostStepPoint);
00255 }
00256 return pParticleChange;
00257 }
00258
00259 G4double G4ParallelWorldProcess::AlongStepGetPhysicalInteractionLength(
00260 const G4Track& track, G4double previousStepSize, G4double currentMinimumStep,
00261 G4double& proposedSafety, G4GPILSelection* selection)
00262 {
00263 static G4FieldTrack endTrack('0');
00264
00265 ELimited eLimited;
00266 ELimited eLim = kUndefLimited;
00267
00268 *selection = NotCandidateForSelection;
00269 G4double returnedStep = DBL_MAX;
00270
00271 if (previousStepSize > 0.)
00272 { fGhostSafety -= previousStepSize; }
00273 if (fGhostSafety < 0.) fGhostSafety = 0.0;
00274
00275 if (currentMinimumStep <= fGhostSafety && currentMinimumStep > 0.)
00276 {
00277
00278 returnedStep = currentMinimumStep;
00279 fOnBoundary = false;
00280 proposedSafety = fGhostSafety - currentMinimumStep;
00281 eLim = kDoNot;
00282 }
00283 else
00284 {
00285 G4FieldTrackUpdator::Update(&fFieldTrack,&track);
00286 returnedStep
00287 = fPathFinder->ComputeStep(fFieldTrack,currentMinimumStep,fNavigatorID,
00288 track.GetCurrentStepNumber(),fGhostSafety,eLimited,
00289 endTrack,track.GetVolume());
00290 if(eLimited == kDoNot)
00291 {
00292 fOnBoundary = false;
00293 fGhostSafety = fGhostNavigator->ComputeSafety(endTrack.GetPosition());
00294 }
00295 else
00296 {
00297 fOnBoundary = true;
00298 }
00299 proposedSafety = fGhostSafety;
00300 if(eLimited == kUnique || eLimited == kSharedOther) {
00301 *selection = CandidateForSelection;
00302 }
00303 else if (eLimited == kSharedTransport) {
00304 returnedStep *= (1.0 + 1.0e-9);
00305 }
00306 eLim = eLimited;
00307 }
00308
00309 if(iParallelWorld==nParallelWorlds) fNavIDHyp = 0;
00310 if(eLim == kUnique || eLim == kSharedOther) fNavIDHyp = fNavigatorID;
00311 return returnedStep;
00312 }
00313
00314 G4VParticleChange* G4ParallelWorldProcess::AlongStepDoIt(
00315 const G4Track& track, const G4Step& )
00316 {
00317 pParticleChange->Initialize(track);
00318 return pParticleChange;
00319 }
00320
00321 void G4ParallelWorldProcess::CopyStep(const G4Step & step)
00322 {
00323 G4StepStatus prevStat = fGhostPostStepPoint->GetStepStatus();
00324
00325 fGhostStep->SetTrack(step.GetTrack());
00326 fGhostStep->SetStepLength(step.GetStepLength());
00327 fGhostStep->SetTotalEnergyDeposit(step.GetTotalEnergyDeposit());
00328 fGhostStep->SetNonIonizingEnergyDeposit(step.GetNonIonizingEnergyDeposit());
00329 fGhostStep->SetControlFlag(step.GetControlFlag());
00330
00331 *fGhostPreStepPoint = *(step.GetPreStepPoint());
00332 *fGhostPostStepPoint = *(step.GetPostStepPoint());
00333
00334 fGhostPreStepPoint->SetStepStatus(prevStat);
00335 if(fOnBoundary)
00336 { fGhostPostStepPoint->SetStepStatus(fGeomBoundary); }
00337 else if(fGhostPostStepPoint->GetStepStatus()==fGeomBoundary)
00338 { fGhostPostStepPoint->SetStepStatus(fPostStepDoItProc); }
00339
00340 if(iParallelWorld==1)
00341 {
00342 G4StepStatus prevStatHyp = fpHyperStep->GetPostStepPoint()->GetStepStatus();
00343
00344 fpHyperStep->SetTrack(step.GetTrack());
00345 fpHyperStep->SetStepLength(step.GetStepLength());
00346 fpHyperStep->SetTotalEnergyDeposit(step.GetTotalEnergyDeposit());
00347 fpHyperStep->SetNonIonizingEnergyDeposit(step.GetNonIonizingEnergyDeposit());
00348 fpHyperStep->SetControlFlag(step.GetControlFlag());
00349
00350 *(fpHyperStep->GetPreStepPoint()) = *(fpHyperStep->GetPostStepPoint());
00351 *(fpHyperStep->GetPostStepPoint()) = *(step.GetPostStepPoint());
00352
00353 fpHyperStep->GetPreStepPoint()->SetStepStatus(prevStatHyp);
00354 }
00355
00356 if(fOnBoundary)
00357 { fpHyperStep->GetPostStepPoint()->SetStepStatus(fGeomBoundary); }
00358 }
00359
00360 void G4ParallelWorldProcess::SwitchMaterial(G4StepPoint* realWorldStepPoint)
00361 {
00362 if(realWorldStepPoint->GetStepStatus()==fWorldBoundary) return;
00363 G4VPhysicalVolume* thePhys = fNewGhostTouchable->GetVolume();
00364 if(thePhys)
00365 {
00366 G4Material* ghostMaterial = thePhys->GetLogicalVolume()->GetMaterial();
00367 if(ghostMaterial)
00368 {
00369 G4Region* ghostRegion = thePhys->GetLogicalVolume()->GetRegion();
00370 G4ProductionCuts* prodCuts =
00371 realWorldStepPoint->GetMaterialCutsCouple()->GetProductionCuts();
00372 if(ghostRegion)
00373 {
00374 G4ProductionCuts* ghostProdCuts = ghostRegion->GetProductionCuts();
00375 if(ghostProdCuts) prodCuts = ghostProdCuts;
00376 }
00377 const G4MaterialCutsCouple* ghostMCCouple =
00378 G4ProductionCutsTable::GetProductionCutsTable()
00379 ->GetMaterialCutsCouple(ghostMaterial,prodCuts);
00380 if(ghostMCCouple)
00381 {
00382 realWorldStepPoint->SetMaterial(ghostMaterial);
00383 realWorldStepPoint->SetMaterialCutsCouple(ghostMCCouple);
00384 *(fpHyperStep->GetPostStepPoint()) = *(fGhostPostStepPoint);
00385 fpHyperStep->GetPostStepPoint()->SetMaterial(ghostMaterial);
00386 fpHyperStep->GetPostStepPoint()->SetMaterialCutsCouple(ghostMCCouple);
00387 }
00388 else
00389 {
00390 G4cout << "!!! MaterialCutsCouple is not found for "
00391 << ghostMaterial->GetName() << "." << G4endl
00392 << " Material in real world ("
00393 << realWorldStepPoint->GetMaterial()->GetName()
00394 << ") is used." << G4endl;
00395 }
00396 }
00397 }
00398 }
00399
00400 G4bool G4ParallelWorldProcess::IsAtRestRequired(G4ParticleDefinition* partDef)
00401 {
00402 G4int pdgCode = partDef->GetPDGEncoding();
00403 if(pdgCode==0)
00404 {
00405 G4String partName = partDef->GetParticleName();
00406 if(partName=="opticalphoton") return false;
00407 if(partName=="geantino") return false;
00408 if(partName=="chargedgeantino") return false;
00409 }
00410 else
00411 {
00412 if(pdgCode==22) return false;
00413 if(pdgCode==11) return false;
00414 if(pdgCode==2212) return false;
00415 if(pdgCode==-12) return false;
00416 if(pdgCode==12) return false;
00417 if(pdgCode==-14) return false;
00418 if(pdgCode==14) return false;
00419 if(pdgCode==-16) return false;
00420 if(pdgCode==16) return false;
00421 }
00422 return true;
00423 }
00424