44 #include "G4MonopoleTransportation.hh"
45 #include "G4ProductionCutsTable.hh"
46 #include "G4ParticleTable.hh"
47 #include "G4ChordFinder.hh"
48 #include "G4SafetyHelper.hh"
49 #include "G4FieldManagerStore.hh"
50 #include "SimG4Core/Physics/interface/G4Monopole.hh"
52 class G4VSensitiveDetector;
58 G4MonopoleTransportation::G4MonopoleTransportation(
const G4Monopole* mpl,
61 : G4VProcess( G4String(
"MonopoleTransportation"), fTransportation ),
62 fFieldBuilder(fieldBuilder),
63 fParticleIsLooping(
false ),
64 fPreviousSftOrigin (0.,0.,0.),
65 fPreviousSafety ( 0.0 ),
66 fThreshold_Warning_Energy( 100 * MeV ),
67 fThreshold_Important_Energy( 250 * MeV ),
68 fThresholdTrials( 10 ),
69 fUnimportant_Energy( 1 * MeV ),
71 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
72 fShortStepOptimisation(
false),
79 G4TransportationManager* transportMgr ;
81 transportMgr = G4TransportationManager::GetTransportationManager() ;
83 fLinearNavigator = transportMgr->GetNavigatorForTracking() ;
87 fFieldPropagator = transportMgr->GetPropagatorInField() ;
89 fpSafetyHelper = transportMgr->GetSafetyHelper();
97 static G4TouchableHandle nullTouchableHandle;
98 fCurrentTouchableHandle = nullTouchableHandle;
100 fEndGlobalTimeComputed =
false;
101 fCandidateEndGlobalTime = 0;
106 G4MonopoleTransportation::~G4MonopoleTransportation()
108 if( (fVerboseLevel > 0) && (fSumEnergyKilled > 0.0 ) ){
109 G4cout <<
" G4MonopoleTransportation: Statistics for looping particles " << G4endl;
110 G4cout <<
" Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
111 G4cout <<
" Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
122 G4double G4MonopoleTransportation::
123 AlongStepGetPhysicalInteractionLength(
const G4Track&
track,
125 G4double currentMinimumStep,
126 G4double& currentSafety,
132 G4FieldManager* fieldMgrX=fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
133 fFieldBuilder->setStepperAndChordFinder (fieldMgrX, 1);
135 G4double geometryStepLength, newSafety ;
136 fParticleIsLooping =
false ;
147 *selection = CandidateForSelection ;
151 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
152 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection() ;
153 G4ThreeVector startPosition = track.GetPosition() ;
161 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
162 G4double MagSqShift = OriginShift.mag2() ;
163 if( MagSqShift >=
sqr(fPreviousSafety) )
165 currentSafety = 0.0 ;
169 currentSafety = fPreviousSafety -
std::sqrt(MagSqShift) ;
174 G4double particleMagneticCharge = pParticleDef->MagneticCharge() ;
175 G4double particleElectricCharge = pParticle->GetCharge();
177 fGeometryLimitedStep =
false ;
186 G4FieldManager* fieldMgr=0;
187 G4bool fieldExertsForce =
false ;
189 if( (particleMagneticCharge != 0.0) )
191 fieldMgr= fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
194 fieldMgr->ConfigureForTrack( &track );
200 fieldExertsForce = (fieldMgr->GetDetectorField() != 0);
209 if( !fieldExertsForce )
211 G4double linearStepLength ;
212 if( fShortStepOptimisation && (currentMinimumStep <= currentSafety) )
216 geometryStepLength = currentMinimumStep ;
217 fGeometryLimitedStep =
false ;
223 linearStepLength = fLinearNavigator->ComputeStep( startPosition,
229 fPreviousSftOrigin = startPosition ;
230 fPreviousSafety = newSafety ;
235 currentSafety = newSafety ;
237 fGeometryLimitedStep= (linearStepLength <= currentMinimumStep);
238 if( fGeometryLimitedStep )
241 geometryStepLength = linearStepLength ;
246 geometryStepLength = currentMinimumStep ;
249 endpointDistance = geometryStepLength ;
253 fTransportEndPosition = startPosition+geometryStepLength*startMomentumDir ;
257 fTransportEndMomentumDir = startMomentumDir ;
258 fTransportEndKineticEnergy = track.GetKineticEnergy() ;
259 fTransportEndSpin = track.GetPolarization();
260 fParticleIsLooping =
false ;
261 fMomentumChanged =
false ;
262 fEndGlobalTimeComputed =
false ;
267 G4ThreeVector EndUnitMomentum ;
268 G4double lengthAlongCurve ;
269 G4double restMass = pParticleDef->GetPDGMass() ;
271 fFieldPropagator->SetChargeMomentumMass( particleMagneticCharge,
272 particleElectricCharge,
279 G4ThreeVector
spin = track.GetPolarization() ;
280 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
281 track.GetMomentumDirection(),
283 track.GetKineticEnergy(),
286 track.GetGlobalTime(),
287 track.GetProperTime(),
289 if( currentMinimumStep > 0 )
293 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
296 track.GetVolume() ) ;
297 fGeometryLimitedStep= lengthAlongCurve < currentMinimumStep;
298 if( fGeometryLimitedStep ) {
299 geometryStepLength = lengthAlongCurve ;
301 geometryStepLength = currentMinimumStep ;
306 geometryStepLength = lengthAlongCurve= 0.0 ;
307 fGeometryLimitedStep =
false ;
312 fPreviousSftOrigin = startPosition ;
313 fPreviousSafety = currentSafety ;
318 fTransportEndPosition = aFieldTrack.GetPosition() ;
322 fMomentumChanged =
true ;
323 fTransportEndMomentumDir = aFieldTrack.GetMomentumDir() ;
325 fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy() ;
332 fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
333 fEndGlobalTimeComputed =
true;
400 fTransportEndSpin = aFieldTrack.GetSpin();
401 fParticleIsLooping = fFieldPropagator->IsParticleLooping() ;
402 endpointDistance = (fTransportEndPosition - startPosition).
mag() ;
408 if( currentMinimumStep == 0.0 )
410 if( currentSafety == 0.0 ) fGeometryLimitedStep =
true ;
416 if( currentSafety < endpointDistance )
421 if( particleMagneticCharge != 0.0 ) {
424 fLinearNavigator->ComputeSafety( fTransportEndPosition) ;
425 currentSafety = endSafety ;
426 fPreviousSftOrigin = fTransportEndPosition ;
427 fPreviousSafety = currentSafety ;
428 fpSafetyHelper->SetCurrentSafety( currentSafety, fTransportEndPosition);
433 currentSafety += endpointDistance ;
435 #ifdef G4DEBUG_TRANSPORT
436 G4cout.precision(12) ;
437 G4cout <<
"***G4MonopoleTransportation::AlongStepGPIL ** " << G4endl ;
438 G4cout <<
" Called Navigator->ComputeSafety at " << fTransportEndPosition
439 <<
" and it returned safety= " << endSafety << G4endl ;
440 G4cout <<
" Adding endpoint distance " << endpointDistance
441 <<
" to obtain pseudo-safety= " << currentSafety << G4endl ;
446 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
448 return geometryStepLength ;
456 G4VParticleChange* G4MonopoleTransportation::AlongStepDoIt(
const G4Track& track,
457 const G4Step& stepData )
459 static G4int noCalls=0;
460 static const G4ParticleDefinition* fOpticalPhoton =
461 G4ParticleTable::GetParticleTable()->FindParticle(
"opticalphoton");
465 fParticleChange.Initialize(track) ;
469 fParticleChange.ProposePosition(fTransportEndPosition) ;
470 fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir) ;
471 fParticleChange.ProposeEnergy(fTransportEndKineticEnergy) ;
472 fParticleChange.SetMomentumChanged(fMomentumChanged) ;
474 fParticleChange.ProposePolarization(fTransportEndSpin);
476 G4double deltaTime = 0.0 ;
482 G4double startTime = track.GetGlobalTime() ;
484 if (!fEndGlobalTimeComputed)
488 G4double finalVelocity = track.GetVelocity() ;
489 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity() ;
490 G4double stepLength = track.GetStepLength() ;
493 const G4DynamicParticle* fpDynamicParticle = track.GetDynamicParticle();
494 if (fpDynamicParticle->GetDefinition()== fOpticalPhoton)
498 deltaTime = stepLength/finalVelocity ;
500 else if (finalVelocity > 0.0)
502 G4double meanInverseVelocity ;
504 meanInverseVelocity = 0.5
505 * ( 1.0 / initialVelocity + 1.0 / finalVelocity ) ;
506 deltaTime = stepLength * meanInverseVelocity ;
508 else if( initialVelocity > 0.0 )
510 deltaTime = stepLength/initialVelocity ;
512 fCandidateEndGlobalTime = startTime + deltaTime ;
516 deltaTime = fCandidateEndGlobalTime - startTime ;
519 fParticleChange.ProposeGlobalTime( fCandidateEndGlobalTime ) ;
523 G4double restMass = track.GetDynamicParticle()->GetMass() ;
524 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
526 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
533 if ( fParticleIsLooping )
535 G4double endEnergy= fTransportEndKineticEnergy;
537 if( (endEnergy < fThreshold_Important_Energy)
538 || (fNoLooperTrials >= fThresholdTrials ) ){
541 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
544 fSumEnergyKilled += endEnergy;
545 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
548 if( (fVerboseLevel > 1) ||
549 ( endEnergy > fThreshold_Warning_Energy ) ) {
550 G4cout <<
" G4MonopoleTransportation is killing track that is looping or stuck "
552 <<
" This track has " << track.GetKineticEnergy() / MeV
553 <<
" MeV energy." << G4endl;
554 G4cout <<
" Number of trials = " << fNoLooperTrials
555 <<
" No of calls to AlongStepDoIt = " << noCalls
564 if( (fVerboseLevel > 2) ){
565 G4cout <<
" G4MonopoleTransportation::AlongStepDoIt(): Particle looping - "
566 <<
" Number of trials = " << fNoLooperTrials
567 <<
" No of calls to = " << noCalls
581 fParticleChange.SetPointerToVectorOfAuxiliaryPoints
582 (fFieldPropagator->GimmeTrajectoryVectorAndForgetIt() );
584 return &fParticleChange ;
593 G4double G4MonopoleTransportation::
594 PostStepGetPhysicalInteractionLength(
const G4Track& track,
596 G4ForceCondition* pForceCond )
600 G4FieldManager* fieldMgr=fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
601 fFieldBuilder->setStepperAndChordFinder (fieldMgr, 0);
603 *pForceCond = Forced ;
610 G4VParticleChange* G4MonopoleTransportation::PostStepDoIt(
const G4Track& track,
613 G4TouchableHandle retCurrentTouchable ;
619 fParticleChange.ProposeTrackStatus(track.GetTrackStatus()) ;
624 if(fGeometryLimitedStep)
630 fLinearNavigator->SetGeometricallyLimitedStep() ;
632 LocateGlobalPointAndUpdateTouchableHandle( track.GetPosition(),
633 track.GetMomentumDirection(),
634 fCurrentTouchableHandle,
639 if( fCurrentTouchableHandle->GetVolume() == 0 )
641 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
643 retCurrentTouchable = fCurrentTouchableHandle ;
644 fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
650 fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
657 fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
658 retCurrentTouchable = track.GetTouchableHandle() ;
661 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
662 const G4Material* pNewMaterial = 0 ;
663 const G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
667 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
668 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
674 fParticleChange.SetMaterialInTouchable( (G4Material *) pNewMaterial ) ;
675 fParticleChange.SetSensitiveDetectorInTouchable( (G4VSensitiveDetector *) pNewSensitiveDetector ) ;
677 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
680 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
683 if( pNewVol!=0 && pNewMaterialCutsCouple!=0 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
687 pNewMaterialCutsCouple =
688 G4ProductionCutsTable::GetProductionCutsTable()
689 ->GetMaterialCutsCouple(pNewMaterial,
690 pNewMaterialCutsCouple->GetProductionCuts());
692 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
700 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
702 return &fParticleChange ;
709 G4MonopoleTransportation::StartTracking(G4Track* aTrack)
711 G4VProcess::StartTracking(aTrack);
718 fPreviousSafety = 0.0 ;
719 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) ;
729 if( DoesGlobalFieldExist() ) {
730 fFieldPropagator->ClearPropagatorState();
739 static G4FieldManagerStore* fieldMgrStore= G4FieldManagerStore::GetInstance();
740 fieldMgrStore->ClearAllChordFindersState();
744 fCurrentTouchableHandle = aTrack->GetTouchableHandle();
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
Square< F >::type sqr(const F &f)