43 #include "G4MonopoleTransportation.hh"
44 #include "G4ProductionCutsTable.hh"
45 #include "G4ParticleTable.hh"
46 #include "G4ChordFinder.hh"
47 #include "G4SafetyHelper.hh"
48 #include "G4FieldManagerStore.hh"
49 #include "SimG4Core/Physics/interface/G4Monopole.hh"
52 class G4VSensitiveDetector;
59 static const G4TouchableHandle nullTouchableHandle;
62 G4MonopoleTransportation::G4MonopoleTransportation(
const G4Monopole* mpl,
65 : G4VProcess( G4String(
"MonopoleTransportation"), fTransportation ),
66 fChordFinderSetter(chordFinderSetter),
67 fParticleIsLooping(
false ),
68 fPreviousSftOrigin (0.,0.,0.),
69 fPreviousSafety ( 0.0 ),
70 fThreshold_Warning_Energy( 100 *
MeV ),
71 fThreshold_Important_Energy( 250 *
MeV ),
72 fThresholdTrials( 10 ),
73 fUnimportant_Energy( 1 *
MeV ),
75 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
76 fShortStepOptimisation(
false),
83 G4TransportationManager* transportMgr ;
85 transportMgr = G4TransportationManager::GetTransportationManager() ;
87 fLinearNavigator = transportMgr->GetNavigatorForTracking() ;
91 fFieldPropagator = transportMgr->GetPropagatorInField() ;
93 fpSafetyHelper = transportMgr->GetSafetyHelper();
101 fCurrentTouchableHandle = nullTouchableHandle;
103 fEndGlobalTimeComputed =
false;
104 fCandidateEndGlobalTime = 0;
109 G4MonopoleTransportation::~G4MonopoleTransportation()
111 if( (fVerboseLevel > 0) && (fSumEnergyKilled > 0.0 ) ){
112 G4cout <<
" G4MonopoleTransportation: Statistics for looping particles " << G4endl;
113 G4cout <<
" Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
114 G4cout <<
" Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
125 G4double G4MonopoleTransportation::
126 AlongStepGetPhysicalInteractionLength(
const G4Track& track,
128 G4double currentMinimumStep,
129 G4double& currentSafety,
135 G4FieldManager* fieldMgrX=fFieldPropagator->FindAndSetFieldManager(track.GetVolume());
136 fChordFinderSetter->setStepperAndChordFinder (fieldMgrX, 1);
138 G4double geometryStepLength, newSafety ;
139 fParticleIsLooping =
false ;
150 *selection = CandidateForSelection ;
154 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
155 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection() ;
156 G4ThreeVector startPosition = track.GetPosition() ;
164 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
165 G4double MagSqShift = OriginShift.mag2() ;
166 if( MagSqShift >=
sqr(fPreviousSafety) )
168 currentSafety = 0.0 ;
172 currentSafety = fPreviousSafety -
std::sqrt(MagSqShift) ;
177 G4double particleMagneticCharge = pParticleDef->MagneticCharge() ;
178 G4double particleElectricCharge = pParticle->GetCharge();
180 fGeometryLimitedStep =
false ;
189 G4FieldManager* fieldMgr=0;
190 G4bool fieldExertsForce =
false ;
192 if( (particleMagneticCharge != 0.0) )
194 fieldMgr= fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
197 fieldMgr->ConfigureForTrack( &track );
203 fieldExertsForce = (fieldMgr->GetDetectorField() != 0);
212 if( !fieldExertsForce )
214 G4double linearStepLength ;
215 if( fShortStepOptimisation && (currentMinimumStep <= currentSafety) )
219 geometryStepLength = currentMinimumStep ;
220 fGeometryLimitedStep =
false ;
226 linearStepLength = fLinearNavigator->ComputeStep( startPosition,
232 fPreviousSftOrigin = startPosition ;
233 fPreviousSafety = newSafety ;
238 currentSafety = newSafety ;
240 fGeometryLimitedStep= (linearStepLength <= currentMinimumStep);
241 if( fGeometryLimitedStep )
244 geometryStepLength = linearStepLength ;
249 geometryStepLength = currentMinimumStep ;
252 endpointDistance = geometryStepLength ;
256 fTransportEndPosition = startPosition+geometryStepLength*startMomentumDir ;
260 fTransportEndMomentumDir = startMomentumDir ;
261 fTransportEndKineticEnergy = track.GetKineticEnergy() ;
262 fTransportEndSpin = track.GetPolarization();
263 fParticleIsLooping =
false ;
264 fMomentumChanged =
false ;
265 fEndGlobalTimeComputed =
false ;
270 G4ThreeVector EndUnitMomentum ;
271 G4double lengthAlongCurve ;
272 G4double restMass = pParticleDef->GetPDGMass();
273 G4double momentumMagnitude = pParticle->GetTotalMomentum();
278 G4ChargeState chargeState(particleElectricCharge,
279 pParticleDef->GetPDGSpin(),
282 particleMagneticCharge );
284 G4EquationOfMotion* equationOfMotion =
285 (fFieldPropagator->GetChordFinder()->GetIntegrationDriver()->GetStepper())
286 ->GetEquationOfMotion();
288 equationOfMotion->SetChargeMomentumMass( chargeState,
295 G4ThreeVector
spin = track.GetPolarization() ;
296 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
297 track.GetMomentumDirection(),
299 track.GetKineticEnergy(),
302 track.GetGlobalTime(),
303 track.GetProperTime(),
305 if( currentMinimumStep > 0 )
309 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
312 track.GetVolume() ) ;
313 fGeometryLimitedStep= lengthAlongCurve < currentMinimumStep;
314 if( fGeometryLimitedStep ) {
315 geometryStepLength = lengthAlongCurve ;
317 geometryStepLength = currentMinimumStep ;
322 geometryStepLength = lengthAlongCurve= 0.0 ;
323 fGeometryLimitedStep =
false ;
328 fPreviousSftOrigin = startPosition ;
329 fPreviousSafety = currentSafety ;
334 fTransportEndPosition = aFieldTrack.GetPosition() ;
338 fMomentumChanged =
true ;
339 fTransportEndMomentumDir = aFieldTrack.GetMomentumDir() ;
341 fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy() ;
348 fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
349 fEndGlobalTimeComputed =
true;
416 fTransportEndSpin = aFieldTrack.GetSpin();
417 fParticleIsLooping = fFieldPropagator->IsParticleLooping() ;
418 endpointDistance = (fTransportEndPosition - startPosition).
mag() ;
424 if( currentMinimumStep == 0.0 )
426 if( currentSafety == 0.0 ) fGeometryLimitedStep =
true ;
432 if( currentSafety < endpointDistance )
437 if( particleMagneticCharge != 0.0 ) {
440 fLinearNavigator->ComputeSafety( fTransportEndPosition) ;
441 currentSafety = endSafety ;
442 fPreviousSftOrigin = fTransportEndPosition ;
443 fPreviousSafety = currentSafety ;
444 fpSafetyHelper->SetCurrentSafety( currentSafety, fTransportEndPosition);
449 currentSafety += endpointDistance ;
451 #ifdef G4DEBUG_TRANSPORT
452 G4cout.precision(12) ;
453 G4cout <<
"***G4MonopoleTransportation::AlongStepGPIL ** " << G4endl ;
454 G4cout <<
" Called Navigator->ComputeSafety at " << fTransportEndPosition
455 <<
" and it returned safety= " << endSafety << G4endl ;
456 G4cout <<
" Adding endpoint distance " << endpointDistance
457 <<
" to obtain pseudo-safety= " << currentSafety << G4endl ;
462 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
464 return geometryStepLength ;
472 G4VParticleChange* G4MonopoleTransportation::AlongStepDoIt(
const G4Track& track,
473 const G4Step& stepData )
475 static const G4ParticleDefinition* fOpticalPhoton =
476 G4ParticleTable::GetParticleTable()->FindParticle(
"opticalphoton");
479 static thread_local G4int noCalls=0;
483 fParticleChange.Initialize(track) ;
487 fParticleChange.ProposePosition(fTransportEndPosition) ;
488 fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir) ;
489 fParticleChange.ProposeEnergy(fTransportEndKineticEnergy) ;
490 fParticleChange.SetMomentumChanged(fMomentumChanged) ;
492 fParticleChange.ProposePolarization(fTransportEndSpin);
494 G4double deltaTime = 0.0 ;
500 G4double
startTime = track.GetGlobalTime() ;
502 if (!fEndGlobalTimeComputed)
506 G4double finalVelocity = track.GetVelocity() ;
507 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity() ;
508 G4double stepLength = track.GetStepLength() ;
511 const G4DynamicParticle* fpDynamicParticle = track.GetDynamicParticle();
512 if (fpDynamicParticle->GetDefinition()== fOpticalPhoton)
516 deltaTime = stepLength/finalVelocity ;
518 else if (finalVelocity > 0.0)
520 G4double meanInverseVelocity ;
522 meanInverseVelocity = 0.5
523 * ( 1.0 / initialVelocity + 1.0 / finalVelocity ) ;
524 deltaTime = stepLength * meanInverseVelocity ;
526 else if( initialVelocity > 0.0 )
528 deltaTime = stepLength/initialVelocity ;
530 fCandidateEndGlobalTime = startTime + deltaTime ;
534 deltaTime = fCandidateEndGlobalTime -
startTime ;
537 fParticleChange.ProposeGlobalTime( fCandidateEndGlobalTime ) ;
541 G4double restMass = track.GetDynamicParticle()->GetMass() ;
542 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
544 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
551 if ( fParticleIsLooping )
553 G4double endEnergy= fTransportEndKineticEnergy;
555 if( (endEnergy < fThreshold_Important_Energy)
556 || (fNoLooperTrials >= fThresholdTrials ) ){
559 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
562 fSumEnergyKilled += endEnergy;
563 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
566 if( (fVerboseLevel > 1) ||
567 ( endEnergy > fThreshold_Warning_Energy ) ) {
568 G4cout <<
" G4MonopoleTransportation is killing track that is looping or stuck "
570 <<
" This track has " << track.GetKineticEnergy() /
MeV
571 <<
" MeV energy." << G4endl;
572 G4cout <<
" Number of trials = " << fNoLooperTrials
573 <<
" No of calls to AlongStepDoIt = " << noCalls
582 if( (fVerboseLevel > 2) ){
583 G4cout <<
" G4MonopoleTransportation::AlongStepDoIt(): Particle looping - "
584 <<
" Number of trials = " << fNoLooperTrials
585 <<
" No of calls to = " << noCalls
599 fParticleChange.SetPointerToVectorOfAuxiliaryPoints
600 (fFieldPropagator->GimmeTrajectoryVectorAndForgetIt() );
602 return &fParticleChange ;
611 G4double G4MonopoleTransportation::
612 PostStepGetPhysicalInteractionLength(
const G4Track& track,
614 G4ForceCondition* pForceCond )
618 G4FieldManager* fieldMgr=fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
619 fChordFinderSetter->setStepperAndChordFinder (fieldMgr, 0);
621 *pForceCond = Forced ;
628 G4VParticleChange* G4MonopoleTransportation::PostStepDoIt(
const G4Track& track,
631 G4TouchableHandle retCurrentTouchable ;
637 fParticleChange.ProposeTrackStatus(track.GetTrackStatus()) ;
642 if(fGeometryLimitedStep)
648 fLinearNavigator->SetGeometricallyLimitedStep() ;
650 LocateGlobalPointAndUpdateTouchableHandle( track.GetPosition(),
651 track.GetMomentumDirection(),
652 fCurrentTouchableHandle,
657 if( fCurrentTouchableHandle->GetVolume() == 0 )
659 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
661 retCurrentTouchable = fCurrentTouchableHandle ;
662 fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
668 fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
675 fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
676 retCurrentTouchable = track.GetTouchableHandle() ;
679 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
680 const G4Material* pNewMaterial = 0 ;
681 const G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
685 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
686 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
692 fParticleChange.SetMaterialInTouchable( (G4Material *) pNewMaterial ) ;
693 fParticleChange.SetSensitiveDetectorInTouchable( (G4VSensitiveDetector *) pNewSensitiveDetector ) ;
695 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
698 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
701 if( pNewVol!=0 && pNewMaterialCutsCouple!=0 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
705 pNewMaterialCutsCouple =
706 G4ProductionCutsTable::GetProductionCutsTable()
707 ->GetMaterialCutsCouple(pNewMaterial,
708 pNewMaterialCutsCouple->GetProductionCuts());
710 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
718 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
720 return &fParticleChange ;
727 G4MonopoleTransportation::StartTracking(G4Track* aTrack)
729 G4VProcess::StartTracking(aTrack);
736 fPreviousSafety = 0.0 ;
737 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) ;
747 if( DoesGlobalFieldExist() ) {
748 fFieldPropagator->ClearPropagatorState();
757 G4FieldManagerStore* fieldMgrStore= G4FieldManagerStore::GetInstance();
758 fieldMgrStore->ClearAllChordFindersState();
762 fCurrentTouchableHandle = aTrack->GetTouchableHandle();
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
Square< F >::type sqr(const F &f)
volatile std::atomic< bool > shutdown_flag false