62 G4bool G4CoupledTransportation::fUseMagneticMoment=
false;
69 fTransportEndPosition(0.0, 0.0, 0.0),
70 fTransportEndMomentumDir(0.0, 0.0, 0.0),
71 fTransportEndKineticEnergy(0.0),
72 fTransportEndSpin(0.0, 0.0, 0.0),
73 fMomentumChanged(false),
74 fEndGlobalTimeComputed(false),
75 fCandidateEndGlobalTime(0.0),
76 fParticleIsLooping( false ),
78 fPreviousMassSafety( 0.0 ),
79 fPreviousFullSafety( 0.0 ),
80 fMassGeometryLimitedStep( false ),
81 fAnyGeometryLimitedStep( false ),
82 fEndpointDistance( -1.0 ),
83 fThreshold_Warning_Energy( 100 *
MeV ),
84 fThreshold_Important_Energy( 250 *
MeV ),
85 fThresholdTrials( 10 ),
87 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
88 fVerboseLevel( verbosity )
101 if( fVerboseLevel > 0 )
103 G4cout <<
" G4CoupledTransportation constructor: ----- " <<
G4endl;
104 G4cout <<
" Verbose level is " << fVerboseLevel <<
G4endl;
105 G4cout <<
" Navigator Id obtained in G4CoupledTransportation constructor "
106 << fNavigatorId <<
G4endl;
114 fCurrentTouchableHandle = *pNullTouchableHandle;
118 fGlobalFieldExists= globalFieldMgr ? globalFieldMgr->
GetDetectorField() : 0 ;
127 if( (fVerboseLevel > 0) || (fSumEnergyKilled > 0.0 ) )
129 G4cout <<
" G4CoupledTransportation: Statistics for looping particles " <<
G4endl;
130 G4cout <<
" Sum of energy of loopers killed: " << fSumEnergyKilled <<
G4endl;
131 G4cout <<
" Max energy of loopers killed: " << fMaxEnergyKilled <<
G4endl;
157 fParticleIsLooping = false ;
178 #ifdef G4DEBUG_TRANSPORT
179 if( fVerboseLevel > 1 )
181 G4cout <<
"G4CoupledTransportation::AlongStepGPIL> called in volume "
193 startMassSafety = 0.0;
194 startFullSafety= 0.0;
198 if( MagSqShift <
sqr(fPreviousFullSafety) )
200 G4double mag_shift= std::sqrt(MagSqShift);
201 startMassSafety =
std::max( (fPreviousMassSafety - mag_shift), 0.0);
202 startFullSafety =
std::max( (fPreviousFullSafety - mag_shift), 0.0);
216 fMassGeometryLimitedStep = false ;
217 fAnyGeometryLimitedStep =
false;
228 G4bool fieldExertsForce = false ;
247 if( (particleCharge != 0.0)
248 || (fUseMagneticMoment && (magneticMoment != 0.0) )
249 || (gravityOn && (restMass != 0.0))
252 fieldExertsForce =
true;
258 if( fieldExertsForce )
293 if( equationOfMotion )
299 G4cerr <<
" ERROR > Cannot find valid Equation of motion - Unable to pass Charge, Momentum and Mass " <<
G4endl;
321 fMassGeometryLimitedStep = false ;
322 fAnyGeometryLimitedStep = false ;
323 if( currentMinimumStep > 0 )
329 lengthAlongCurve = fPathFinder->
ComputeStep( aFieldTrack,
345 fMassGeometryLimitedStep = true ;
351 if( fMassGeometryLimitedStep && !fAnyGeometryLimitedStep )
353 G4cerr <<
" Error in determining geometries limiting the step" <<
G4endl;
354 G4cerr <<
" Limiting: mass=" << fMassGeometryLimitedStep
355 <<
" any= " << fAnyGeometryLimitedStep <<
G4endl;
356 G4Exception(
"G4CoupledTransportation::AlongStepGetPhysicalInteractionLength()",
358 "Incompatible conditions - was limited by a geometry?");
368 geometryStepLength =
std::min( lengthAlongCurve, currentMinimumStep);
372 fMomentumChanged = true ;
376 fPreviousSftOrigin = startPosition ;
377 fPreviousMassSafety = newMassSafety ;
378 fPreviousFullSafety = newFullSafety ;
381 #ifdef G4DEBUG_TRANSPORT
382 if( fVerboseLevel > 1 )
384 G4cout <<
"G4Transport:CompStep> "
385 <<
" called the pathfinder for a new step at " << startPosition
386 <<
" and obtained step = " << lengthAlongCurve <<
G4endl;
387 G4cout <<
" New safety (preStep) = " << newMassSafety
388 <<
" versus precalculated = " << startMassSafety <<
G4endl;
393 startMassSafety = newMassSafety ;
394 startFullSafety = newFullSafety ;
397 fTransportEndPosition = endTrackState.
GetPosition() ;
402 geometryStepLength = lengthAlongCurve= 0.0 ;
403 fMomentumChanged = false ;
409 fTransportEndPosition = startPosition;
411 endTrackState= aFieldTrack;
415 if( startMassSafety == 0.0 )
417 fMassGeometryLimitedStep = true ;
418 fAnyGeometryLimitedStep =
true;
424 if( !fieldExertsForce )
426 fParticleIsLooping = false ;
427 fMomentumChanged = false ;
428 fEndGlobalTimeComputed = false ;
434 #ifdef G4DEBUG_TRANSPORT
435 if( fVerboseLevel > 1 )
437 G4cout <<
" G4CT::CS End Position = " << fTransportEndPosition <<
G4endl;
438 G4cout <<
" G4CT::CS End Direction = " << fTransportEndMomentumDir <<
G4endl;
447 fEndGlobalTimeComputed =
true;
457 fEndGlobalTimeComputed =
false;
462 G4double endEnergy= fTransportEndKineticEnergy;
465 G4double absEdiff = std::fabs(startEnergy- endEnergy);
472 if( (fVerboseLevel > 1) && ( absEdiff >
perThousand * endEnergy) )
484 fEndpointDistance = (fTransportEndPosition - startPosition).mag() ;
487 fTransportEndSpin = endTrackState.
GetSpin();
490 safetyProposal= startFullSafety;
495 if( (startFullSafety < fEndpointDistance )
496 && ( particleCharge != 0.0 ) )
514 fPreviousMassSafety = endMassSafety ;
515 fPreviousFullSafety = endFullSafety;
516 fPreviousSftOrigin = fTransportEndPosition ;
520 safetyProposal = endFullSafety + fEndpointDistance;
526 #ifdef G4DEBUG_TRANSPORT
528 G4cout <<
"***Transportation::AlongStepGPIL ** " <<
G4endl ;
529 G4cout <<
" Revised Safety at endpoint " << fTransportEndPosition
530 <<
" give safety values: Mass= " << endMassSafety
531 <<
" All= " << endFullSafety <<
G4endl ;
532 G4cout <<
" Adding endpoint distance " << fEndpointDistance
533 <<
" to obtain pseudo-safety= " << safetyProposal <<
G4endl ;
539 G4cout <<
"***Transportation::AlongStepGPIL ** " <<
G4endl ;
540 G4cout <<
" Quick Safety estimate at endpoint " << fTransportEndPosition
541 <<
" gives safety endpoint value = " << startFullSafety - fEndpointDistance
542 <<
" using start-point value " << startFullSafety
543 <<
" and endpointDistance " << fEndpointDistance <<
G4endl;
548 proposedSafetyForStart= safetyProposal;
551 return geometryStepLength ;
586 if (!fEndGlobalTimeComputed)
593 if( finalVelocity > 0.0 ) { finalInverseVel= 1.0 / finalVelocity; }
595 if( initialVelocity > 0.0 ) { initialInverseVel= 1.0 / initialVelocity; }
598 if (finalVelocity > 0.0)
601 G4double meanInverseVelocity = 0.5 * ( initialInverseVel + finalInverseVel );
602 deltaTime = stepLength * meanInverseVelocity ;
608 deltaTime = stepLength * initialInverseVel ;
613 fCandidateEndGlobalTime = startTime + deltaTime ;
621 deltaTime = fCandidateEndGlobalTime - startTime ;
643 if ( fParticleIsLooping )
645 G4double endEnergy= fTransportEndKineticEnergy;
647 if( (endEnergy < fThreshold_Important_Energy)
648 || (fNoLooperTrials >= fThresholdTrials ) )
655 fSumEnergyKilled += endEnergy;
656 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
659 if((fVerboseLevel > 1) && ( endEnergy > fThreshold_Warning_Energy ))
661 G4cout <<
" G4CoupledTransportation is killing track that is looping or stuck " <<
G4endl
663 <<
" MeV energy." <<
G4endl;
665 if( fVerboseLevel > 0 )
676 if( (fVerboseLevel > 2) )
678 G4cout <<
" ** G4CoupledTransportation::AlongStepDoIt(): Particle looping - " <<
G4endl
679 <<
" Number of consecutive problem step (this track) = " << fNoLooperTrials <<
G4endl
681 <<
" Total no of calls to this method (all tracks) = " << noCalls <<
G4endl;
699 return &fParticleChange ;
724 <<
"**************************************************************" <<
G4endl;
725 G4cerr <<
"Endpoint has moved between value expected from TransportEndPosition "
726 <<
" and value from Track in PostStepDoIt. " << G4endl
727 <<
"Change of " << Quantity <<
" is " << moveVec.
mag() /
mm <<
" mm long, "
728 <<
" and its vector is " << (1.0/
mm) * moveVec <<
" mm " << G4endl
729 <<
"Endpoint of ComputeStep was " << OldVector
730 <<
" and current position to locate is " << NewVector << G4endl;
749 #ifdef G4DEBUG_TRANSPORT
750 if( ( fVerboseLevel > 0 )
751 && ((fTransportEndPosition - track.
GetPosition()).mag2() >= 1.0e-16) )
754 G4cerr <<
" Problem in G4CoupledTransportation::PostStepDoIt " <<
G4endl;
760 if( fVerboseLevel > 0 )
762 G4cout <<
" Calling PathFinder::Locate() from "
763 <<
" G4CoupledTransportation::PostStepDoIt " <<
G4endl;
764 G4cout <<
" fAnyGeometryLimitedStep is " << fAnyGeometryLimitedStep <<
G4endl;
769 if(fAnyGeometryLimitedStep)
779 fCurrentTouchableHandle=
782 #ifdef G4DEBUG_TRANSPORT
783 if( fVerboseLevel > 0 )
785 G4cout <<
"G4CoupledTransportation::PostStepDoIt --- fNavigatorId = "
786 << fNavigatorId <<
G4endl;
788 if( fVerboseLevel > 1 )
791 G4cout <<
"CHECK !!!!!!!!!!! fCurrentTouchableHandle->GetVolume() = " << vol;
792 if( vol ) {
G4cout <<
"Name=" << vol->GetName(); }
800 if( fCurrentTouchableHandle->
GetVolume() == 0 )
804 retCurrentTouchable = fCurrentTouchableHandle ;
812 #ifdef G4DEBUG_TRANSPORT
813 if( fVerboseLevel > 1 )
815 G4cout <<
"G4CoupledTransportation::PostStepDoIt -- "
816 <<
" fAnyGeometryLimitedStep = " << fAnyGeometryLimitedStep
817 <<
" must be false " <<
G4endl;
862 if( pNewMaterialCutsCouple!=0
863 && pNewMaterialCutsCouple->
GetMaterial()!=pNewMaterial )
867 pNewMaterialCutsCouple =
878 return &fParticleChange ;
920 fPreviousMassSafety = 0.0 ;
921 fPreviousFullSafety = 0.0 ;
932 if( fGlobalFieldExists )
946 #ifdef G4DEBUG_TRANSPORT
947 if( fVerboseLevel > 1 )
949 G4cout <<
" Returning touchable handle " << fCurrentTouchableHandle <<
G4endl;
969 static G4ThreadLocal G4int no_warnings= 0, warnModulo=1, moduloFactor= 10, no_large_ediff= 0;
971 if( std::fabs(startEnergy- endEnergy) >
perThousand * endEnergy )
974 if( (no_large_ediff% warnModulo) == 0 )
977 G4cout <<
"WARNING - G4CoupledTransportation::AlongStepGetPIL() "
978 <<
" Energy change in Step is above 1^-3 relative value. " <<
G4endl
979 <<
" Relative change in 'tracking' step = "
980 << std::setw(15) << (endEnergy-startEnergy)/startEnergy <<
G4endl
981 <<
" Starting E= " << std::setw(12) << startEnergy /
MeV <<
" MeV " <<
G4endl
982 <<
" Ending E= " << std::setw(12) << endEnergy /
MeV <<
" MeV " <<
G4endl;
983 G4cout <<
" Energy has been corrected -- however, review"
984 <<
" field propagation parameters for accuracy." <<
G4endl;
985 if( (fVerboseLevel > 2 ) || (no_warnings<4) || (no_large_ediff == warnModulo * moduloFactor) )
987 G4cout <<
" These include EpsilonStepMax(/Min) in G4FieldManager "
988 <<
" which determine fractional error per step for integrated quantities. " << G4endl
989 <<
" Note also the influence of the permitted number of integration steps."
992 G4cerr <<
"ERROR - G4CoupledTransportation::AlongStepGetPIL()" << G4endl
993 <<
" Bad 'endpoint'. Energy change detected"
994 <<
" and corrected. "
995 <<
" Has occurred already "
996 << no_large_ediff <<
" times." <<
G4endl;
997 if( no_large_ediff == warnModulo * moduloFactor )
999 warnModulo *= moduloFactor;
1008 G4bool lastValue= fUseMagneticMoment;
1009 fUseMagneticMoment= useMoment;
1010 G4Transportation::fUseMagneticMoment= useMoment;
void PrepareNewTrack(const G4ThreeVector &position, const G4ThreeVector &direction, G4VPhysicalVolume *massStartVol=0)
static G4PathFinder * GetInstance()
void SetMaterialInTouchable(G4Material *fMaterial)
static constexpr double perMillion
void SetTouchableHandle(const G4TouchableHandle &fTouchable)
const G4ThreeVector & GetPolarization() const
G4double ObtainSafety(G4int navId, G4ThreeVector &globalCenterPoint)
void Locate(const G4ThreeVector &position, const G4ThreeVector &direction, G4bool relativeSearch=true)
G4SafetyHelper * GetSafetyHelper() const
G4double GetLocalTime() const
static constexpr double mm
G4Material * GetMaterial() const
void ReportMove(G4ThreeVector OldVector, G4ThreeVector NewVector, const G4String &Quantity)
void SetMaterialCutsCoupleInTouchable(const G4MaterialCutsCouple *fMaterialCutsCouple)
void StartTracking(G4Track *aTrack)
virtual void SetChargeMomentumMass(G4ChargeState particleCharge, G4double MomentumXc, G4double MassXc2)=0
G4double GetProperTime() const
CLHEP::Hep3Vector G4ThreeVector
G4double GetVelocity() const
G4double GetCurrentSafety() const
G4double GetKineticEnergy() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MagIntegratorStepper * GetStepper() const
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double ¤tSafety, G4GPILSelection *selection)
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData)
void ClearAllChordFindersState()
G4bool DoesGlobalFieldExist()
void ReLocate(const G4ThreeVector &position)
const G4ThreeVector & GetPosition() const
~G4CoupledTransportation()
const G4ThreeVector & GetMomentumDir() const
G4TrackStatus GetTrackStatus() const
G4ThreeVector GetSpin() const
G4Navigator * GetNavigatorForTracking() const
G4TouchableHandle CreateTouchableHandle(G4int navId) const
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
G4ParticleDefinition * GetDefinition() const
G4double GetVelocity() const
void ProposePosition(G4double x, G4double y, G4double z)
G4ReferenceCountedHandle< G4VTouchable > G4TouchableHandle
unsigned int GetNumberGeometriesLimitingStep() const
G4double GetTotalMomentum() const
static G4bool EnableUseMagneticMoment(G4bool useMoment=true)
G4StepPoint * GetPreStepPoint() const
virtual void Initialize(const G4Track &)
virtual void ConfigureForTrack(const G4Track *)
G4double GetKineticEnergy() const
G4EquationOfMotion * GetEquationOfMotion()
G4ThreeVector GetPosition() const
G4GLOB_DLL std::ostream G4cout
void ReportInexactEnergy(G4double startEnergy, G4double endEnergy)
G4int GetCurrentStepNumber() const
const G4String & GetName() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetCharge() const
void ProposeTrueStepLength(G4double truePathLength)
G4double ComputeStep(const G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4int navigatorId, G4int stepNo, G4double &pNewSafety, ELimited &limitedStep, G4FieldTrack &EndState, G4VPhysicalVolume *currentVolume)
void SetProcessSubType(G4int)
G4bool DoesFieldChangeEnergy() const
G4double ComputeSafety(const G4ThreeVector &globalPoint)
G4double GetGlobalTime() const
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
const G4TouchableHandle & GetTouchableHandle() const
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &stepData)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
static G4TransportationManager * GetTransportationManager()
G4FieldManager * GetFieldManager() const
static G4ProductionCutsTable * GetProductionCutsTable()
G4int ActivateNavigator(G4Navigator *aNavigator)
const G4ThreeVector & GetMomentumDirection() const
G4LogicalVolume * GetLogicalVolume() const
void ProposeProperTime(G4double finalProperTime)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4FieldManagerStore * GetInstance()
void SetSensitiveDetectorInTouchable(G4VSensitiveDetector *fSensitiveDetector)
#define fPreviousSftOrigin
G4bool IsParticleLooping() const
G4double GetLabTimeOfFlight() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
virtual G4VPhysicalVolume * GetVolume(G4int depth=0) const
G4bool IsGravityActive() const
void ProposeGlobalTime(G4double t)
G4ChordFinder * GetChordFinder()
G4FieldManager * GetCurrentFieldManager()
void ProposeEnergy(G4double finalEnergy)
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4VPhysicalVolume * GetVolume() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
G4double GetTotalEnergy() const
G4double GetPDGSpin() const
void SetCurrentSafety(G4double val, const G4ThreeVector &pos)
void ClearPropagatorState()
static constexpr double MeV
void ProposeLastStepInVolume(G4bool flag)
static constexpr double perThousand
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double GetPDGMagneticMoment() const
void ProposeTrackStatus(G4TrackStatus status)
const G4Field * GetDetectorField() const
G4MagInt_Driver * GetIntegrationDriver()
void SetMomentumChanged(G4bool b)
G4PropagatorInField * GetPropagatorInField() const
G4ProductionCuts * GetProductionCuts() const
G4VSensitiveDetector * GetSensitiveDetector() const
G4double GetMagneticMoment() const
G4double PostStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4ForceCondition *pForceCond)
void ProposeLocalTime(G4double t)
G4double GetStepLength() const
const G4Material * GetMaterial() const
G4GLOB_DLL std::ostream G4cerr
G4CoupledTransportation(G4int verbosityLevel=0)