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"
51 class G4VSensitiveDetector;
58 static const G4TouchableHandle nullTouchableHandle;
61 G4MonopoleTransportation::G4MonopoleTransportation(
const G4Monopole* mpl,
64 : G4VProcess( G4String(
"MonopoleTransportation"), fTransportation ),
65 fFieldBuilder(fieldBuilder),
66 fParticleIsLooping(
false ),
67 fPreviousSftOrigin (0.,0.,0.),
68 fPreviousSafety ( 0.0 ),
69 fThreshold_Warning_Energy( 100 *
MeV ),
70 fThreshold_Important_Energy( 250 *
MeV ),
71 fThresholdTrials( 10 ),
72 fUnimportant_Energy( 1 *
MeV ),
74 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
75 fShortStepOptimisation(
false),
82 G4TransportationManager* transportMgr ;
84 transportMgr = G4TransportationManager::GetTransportationManager() ;
86 fLinearNavigator = transportMgr->GetNavigatorForTracking() ;
90 fFieldPropagator = transportMgr->GetPropagatorInField() ;
92 fpSafetyHelper = transportMgr->GetSafetyHelper();
100 fCurrentTouchableHandle = nullTouchableHandle;
102 fEndGlobalTimeComputed =
false;
103 fCandidateEndGlobalTime = 0;
108 G4MonopoleTransportation::~G4MonopoleTransportation()
110 if( (fVerboseLevel > 0) && (fSumEnergyKilled > 0.0 ) ){
111 G4cout <<
" G4MonopoleTransportation: Statistics for looping particles " << G4endl;
112 G4cout <<
" Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
113 G4cout <<
" Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
124 G4double G4MonopoleTransportation::
125 AlongStepGetPhysicalInteractionLength(
const G4Track& track,
127 G4double currentMinimumStep,
128 G4double& currentSafety,
134 G4FieldManager* fieldMgrX=fFieldPropagator->FindAndSetFieldManager(track.GetVolume());
135 fFieldBuilder->setStepperAndChordFinder (fieldMgrX, 1);
137 G4double geometryStepLength, newSafety ;
138 fParticleIsLooping =
false ;
149 *selection = CandidateForSelection ;
153 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
154 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection() ;
155 G4ThreeVector startPosition = track.GetPosition() ;
163 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
164 G4double MagSqShift = OriginShift.mag2() ;
165 if( MagSqShift >=
sqr(fPreviousSafety) )
167 currentSafety = 0.0 ;
171 currentSafety = fPreviousSafety -
std::sqrt(MagSqShift) ;
176 G4double particleMagneticCharge = pParticleDef->MagneticCharge() ;
177 G4double particleElectricCharge = pParticle->GetCharge();
179 fGeometryLimitedStep =
false ;
188 G4FieldManager* fieldMgr=0;
189 G4bool fieldExertsForce =
false ;
191 if( (particleMagneticCharge != 0.0) )
193 fieldMgr= fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
196 fieldMgr->ConfigureForTrack( &track );
202 fieldExertsForce = (fieldMgr->GetDetectorField() != 0);
211 if( !fieldExertsForce )
213 G4double linearStepLength ;
214 if( fShortStepOptimisation && (currentMinimumStep <= currentSafety) )
218 geometryStepLength = currentMinimumStep ;
219 fGeometryLimitedStep =
false ;
225 linearStepLength = fLinearNavigator->ComputeStep( startPosition,
231 fPreviousSftOrigin = startPosition ;
232 fPreviousSafety = newSafety ;
237 currentSafety = newSafety ;
239 fGeometryLimitedStep= (linearStepLength <= currentMinimumStep);
240 if( fGeometryLimitedStep )
243 geometryStepLength = linearStepLength ;
248 geometryStepLength = currentMinimumStep ;
251 endpointDistance = geometryStepLength ;
255 fTransportEndPosition = startPosition+geometryStepLength*startMomentumDir ;
259 fTransportEndMomentumDir = startMomentumDir ;
260 fTransportEndKineticEnergy = track.GetKineticEnergy() ;
261 fTransportEndSpin = track.GetPolarization();
262 fParticleIsLooping =
false ;
263 fMomentumChanged =
false ;
264 fEndGlobalTimeComputed =
false ;
269 G4ThreeVector EndUnitMomentum ;
270 G4double lengthAlongCurve ;
271 G4double restMass = pParticleDef->GetPDGMass();
272 G4double momentumMagnitude = pParticle->GetTotalMomentum();
277 G4ChargeState chargeState(particleElectricCharge,
278 pParticleDef->GetPDGSpin(),
281 particleMagneticCharge );
283 G4EquationOfMotion* equationOfMotion =
284 (fFieldPropagator->GetChordFinder()->GetIntegrationDriver()->GetStepper())
285 ->GetEquationOfMotion();
287 equationOfMotion->SetChargeMomentumMass( chargeState,
294 G4ThreeVector
spin = track.GetPolarization() ;
295 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
296 track.GetMomentumDirection(),
298 track.GetKineticEnergy(),
301 track.GetGlobalTime(),
302 track.GetProperTime(),
304 if( currentMinimumStep > 0 )
308 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
311 track.GetVolume() ) ;
312 fGeometryLimitedStep= lengthAlongCurve < currentMinimumStep;
313 if( fGeometryLimitedStep ) {
314 geometryStepLength = lengthAlongCurve ;
316 geometryStepLength = currentMinimumStep ;
321 geometryStepLength = lengthAlongCurve= 0.0 ;
322 fGeometryLimitedStep =
false ;
327 fPreviousSftOrigin = startPosition ;
328 fPreviousSafety = currentSafety ;
333 fTransportEndPosition = aFieldTrack.GetPosition() ;
337 fMomentumChanged =
true ;
338 fTransportEndMomentumDir = aFieldTrack.GetMomentumDir() ;
340 fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy() ;
347 fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
348 fEndGlobalTimeComputed =
true;
415 fTransportEndSpin = aFieldTrack.GetSpin();
416 fParticleIsLooping = fFieldPropagator->IsParticleLooping() ;
417 endpointDistance = (fTransportEndPosition - startPosition).
mag() ;
423 if( currentMinimumStep == 0.0 )
425 if( currentSafety == 0.0 ) fGeometryLimitedStep =
true ;
431 if( currentSafety < endpointDistance )
436 if( particleMagneticCharge != 0.0 ) {
439 fLinearNavigator->ComputeSafety( fTransportEndPosition) ;
440 currentSafety = endSafety ;
441 fPreviousSftOrigin = fTransportEndPosition ;
442 fPreviousSafety = currentSafety ;
443 fpSafetyHelper->SetCurrentSafety( currentSafety, fTransportEndPosition);
448 currentSafety += endpointDistance ;
450 #ifdef G4DEBUG_TRANSPORT
451 G4cout.precision(12) ;
452 G4cout <<
"***G4MonopoleTransportation::AlongStepGPIL ** " << G4endl ;
453 G4cout <<
" Called Navigator->ComputeSafety at " << fTransportEndPosition
454 <<
" and it returned safety= " << endSafety << G4endl ;
455 G4cout <<
" Adding endpoint distance " << endpointDistance
456 <<
" to obtain pseudo-safety= " << currentSafety << G4endl ;
461 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
463 return geometryStepLength ;
471 G4VParticleChange* G4MonopoleTransportation::AlongStepDoIt(
const G4Track& track,
472 const G4Step& stepData )
474 static const G4ParticleDefinition* fOpticalPhoton =
475 G4ParticleTable::GetParticleTable()->FindParticle(
"opticalphoton");
478 static G4int noCalls=0;
482 fParticleChange.Initialize(track) ;
486 fParticleChange.ProposePosition(fTransportEndPosition) ;
487 fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir) ;
488 fParticleChange.ProposeEnergy(fTransportEndKineticEnergy) ;
489 fParticleChange.SetMomentumChanged(fMomentumChanged) ;
491 fParticleChange.ProposePolarization(fTransportEndSpin);
493 G4double deltaTime = 0.0 ;
499 G4double
startTime = track.GetGlobalTime() ;
501 if (!fEndGlobalTimeComputed)
505 G4double finalVelocity = track.GetVelocity() ;
506 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity() ;
507 G4double stepLength = track.GetStepLength() ;
510 const G4DynamicParticle* fpDynamicParticle = track.GetDynamicParticle();
511 if (fpDynamicParticle->GetDefinition()== fOpticalPhoton)
515 deltaTime = stepLength/finalVelocity ;
517 else if (finalVelocity > 0.0)
519 G4double meanInverseVelocity ;
521 meanInverseVelocity = 0.5
522 * ( 1.0 / initialVelocity + 1.0 / finalVelocity ) ;
523 deltaTime = stepLength * meanInverseVelocity ;
525 else if( initialVelocity > 0.0 )
527 deltaTime = stepLength/initialVelocity ;
529 fCandidateEndGlobalTime = startTime + deltaTime ;
533 deltaTime = fCandidateEndGlobalTime -
startTime ;
536 fParticleChange.ProposeGlobalTime( fCandidateEndGlobalTime ) ;
540 G4double restMass = track.GetDynamicParticle()->GetMass() ;
541 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
543 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
550 if ( fParticleIsLooping )
552 G4double endEnergy= fTransportEndKineticEnergy;
554 if( (endEnergy < fThreshold_Important_Energy)
555 || (fNoLooperTrials >= fThresholdTrials ) ){
558 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
561 fSumEnergyKilled += endEnergy;
562 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
565 if( (fVerboseLevel > 1) ||
566 ( endEnergy > fThreshold_Warning_Energy ) ) {
567 G4cout <<
" G4MonopoleTransportation is killing track that is looping or stuck "
569 <<
" This track has " << track.GetKineticEnergy() /
MeV
570 <<
" MeV energy." << G4endl;
571 G4cout <<
" Number of trials = " << fNoLooperTrials
572 <<
" No of calls to AlongStepDoIt = " << noCalls
581 if( (fVerboseLevel > 2) ){
582 G4cout <<
" G4MonopoleTransportation::AlongStepDoIt(): Particle looping - "
583 <<
" Number of trials = " << fNoLooperTrials
584 <<
" No of calls to = " << noCalls
598 fParticleChange.SetPointerToVectorOfAuxiliaryPoints
599 (fFieldPropagator->GimmeTrajectoryVectorAndForgetIt() );
601 return &fParticleChange ;
610 G4double G4MonopoleTransportation::
611 PostStepGetPhysicalInteractionLength(
const G4Track& track,
613 G4ForceCondition* pForceCond )
617 G4FieldManager* fieldMgr=fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
618 fFieldBuilder->setStepperAndChordFinder (fieldMgr, 0);
620 *pForceCond = Forced ;
627 G4VParticleChange* G4MonopoleTransportation::PostStepDoIt(
const G4Track& track,
630 G4TouchableHandle retCurrentTouchable ;
636 fParticleChange.ProposeTrackStatus(track.GetTrackStatus()) ;
641 if(fGeometryLimitedStep)
647 fLinearNavigator->SetGeometricallyLimitedStep() ;
649 LocateGlobalPointAndUpdateTouchableHandle( track.GetPosition(),
650 track.GetMomentumDirection(),
651 fCurrentTouchableHandle,
656 if( fCurrentTouchableHandle->GetVolume() == 0 )
658 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
660 retCurrentTouchable = fCurrentTouchableHandle ;
661 fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
667 fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
674 fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
675 retCurrentTouchable = track.GetTouchableHandle() ;
678 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
679 const G4Material* pNewMaterial = 0 ;
680 const G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
684 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
685 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
691 fParticleChange.SetMaterialInTouchable( (G4Material *) pNewMaterial ) ;
692 fParticleChange.SetSensitiveDetectorInTouchable( (G4VSensitiveDetector *) pNewSensitiveDetector ) ;
694 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
697 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
700 if( pNewVol!=0 && pNewMaterialCutsCouple!=0 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
704 pNewMaterialCutsCouple =
705 G4ProductionCutsTable::GetProductionCutsTable()
706 ->GetMaterialCutsCouple(pNewMaterial,
707 pNewMaterialCutsCouple->GetProductionCuts());
709 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
717 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
719 return &fParticleChange ;
726 G4MonopoleTransportation::StartTracking(G4Track* aTrack)
728 G4VProcess::StartTracking(aTrack);
735 fPreviousSafety = 0.0 ;
736 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) ;
746 if( DoesGlobalFieldExist() ) {
747 fFieldPropagator->ClearPropagatorState();
756 static G4FieldManagerStore* fieldMgrStore= G4FieldManagerStore::GetInstance();
757 fieldMgrStore->ClearAllChordFindersState();
761 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