58 : fDetectorFieldMgr(detectorFieldMgr),
59 fNavigator(theNavigator),
60 fCurrentFieldMgr(detectorFieldMgr),
64 fEpsilonStep = (fDetectorFieldMgr !=
nullptr)
66 fLargestAcceptableStep = 1000.0 * meter;
70 fZeroStepThreshold = std::max( 1.0e5 * kCarTolerance, 1.0e-1 * micrometer );
73 G4cout <<
" PiF: Zero Step Threshold set to "
74 << fZeroStepThreshold / millimeter
76 G4cout <<
" PiF: Value of kCarTolerance = "
77 << kCarTolerance / millimeter
84 if ( vLocator ==
nullptr )
87 fAllocatedLocator =
true;
91 fIntersectionLocator = vLocator;
92 fAllocatedLocator =
false;
101 if(fAllocatedLocator) {
delete fIntersectionLocator; }
123 G4bool canRelaxDeltaChord)
131 const char* methodName =
"G4PropagatorInField::ComputeStep";
132 if (CurrentProposedStepLength<kCarTolerance)
139 if (fpTrajectoryFilter)
144 fFirstStepInVolume = fNewTrack ? true : fLastStepInVolume;
145 fLastStepInVolume =
false;
148 if( fVerboseLevel > 2 )
151 G4cout <<
" Starting FT: " << pFieldTrack;
152 G4cout <<
" Requested length = " << CurrentProposedStepLength <<
G4endl;
164 G4double TruePathLength = CurrentProposedStepLength;
168 G4bool first_substep =
true;
171 fParticleIsLooping =
false;
181 fSetFieldMgr =
false;
189 if( CurrentProposedStepLength >= fLargestAcceptableStep )
195 G4double trialProposedStep = 1.e2 * ( 10.0 * cm +
197 GetSolid()->DistanceToOut(StartPointA, VelocityUnit) );
198 CurrentProposedStepLength = std::min( trialProposedStep,
199 fLargestAcceptableStep );
215 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
219 stepTrial = fFull_CurveLen_of_LastAttempt;
220 if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) )
222 stepTrial = fLast_ProposedStepLength;
226 if( (fNoZeroStep < fSevereActionThreshold_NoZeroSteps)
227 && (stepTrial > 100.0*fZeroStepThreshold) )
231 decreaseFactor= 0.25;
239 if( stepTrial > 100.0*fZeroStepThreshold )
240 decreaseFactor = 0.35;
241 else if( stepTrial > 30.0*fZeroStepThreshold )
243 else if( stepTrial > 10.0*fZeroStepThreshold )
244 decreaseFactor= 0.75;
248 stepTrial *= decreaseFactor;
251 if( fVerboseLevel > 2
252 || (fNoZeroStep >= fSevereActionThreshold_NoZeroSteps) )
254 G4cerr <<
" " << methodName
255 <<
" Decreasing step after " << fNoZeroStep <<
" zero steps "
256 <<
" - in volume " << pPhysVol;
258 G4cerr <<
" with name " << pPhysVol->GetName();
260 G4cerr <<
" i.e. *unknown* volume.";
263 stepTrial, pFieldTrack);
266 if( stepTrial == 0.0 )
268 std::ostringstream message;
269 message <<
"Particle abandoned due to lack of progress in field."
271 <<
" Properties : " << pFieldTrack <<
G4endl
272 <<
" Attempting a zero step = " << stepTrial <<
G4endl
273 <<
" while attempting to progress after " << fNoZeroStep
274 <<
" trial steps. Will abandon step.";
276 fParticleIsLooping =
true;
279 if( stepTrial < CurrentProposedStepLength )
281 CurrentProposedStepLength = stepTrial;
284 fLast_ProposedStepLength = CurrentProposedStepLength;
286 G4int do_loop_count = 0;
294 if( fVerboseLevel > 4 )
296 G4cout <<
" PiF: Calling Nav/Locate Global Point within-Volume "
304 h_TrialStepSize = CurrentProposedStepLength - StepTaken;
306 if (canRelaxDeltaChord &&
307 fIncreaseChordDistanceThreshold > 0 &&
308 do_loop_count > fIncreaseChordDistanceThreshold &&
309 do_loop_count % fIncreaseChordDistanceThreshold == 0)
326 fFull_CurveLen_of_LastAttempt = s_length_taken;
335 NewSafety, LinearStepLength,
336 InterSectionPointE );
342 currentSafety = NewSafety;
351 G4bool recalculatedEndPt =
false;
353 G4bool found_intersection = fIntersectionLocator->
354 EstimateIntersectionPoint( SubStepStartState, CurrentState,
355 InterSectionPointE, IntersectPointVelct_G,
356 recalculatedEndPt, fPreviousSafety,
358 intersects = found_intersection;
359 if( found_intersection )
361 End_PointAndTangent= IntersectPointVelct_G;
362 StepTaken = TruePathLength = IntersectPointVelct_G.
GetCurveLength()
370 if( recalculatedEndPt )
376 G4bool shortEnd = endAchieved
377 < (endExpected*(1.0-CLHEP::perMillion));
385 CurrentState = IntersectPointVelct_G;
386 s_length_taken = stepAchieved;
389 fParticleIsLooping =
true;
396 StepTaken += s_length_taken;
398 if (fpTrajectoryFilter)
403 first_substep =
false;
406 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
408 if( fNoZeroStep > fSevereActionThreshold_NoZeroSteps )
409 G4cout <<
" Above 'Severe Action' threshold -- for Zero steps. ";
411 G4cout <<
" Above 'action' threshold -- for Zero steps. ";
412 G4cout <<
" Number of zero steps = " << fNoZeroStep <<
G4endl;
414 CurrentState, CurrentProposedStepLength,
415 NewSafety, do_loop_count, pPhysVol );
417 if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 ))
419 if( do_loop_count == fMax_loop_count-9 )
421 G4cout <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
422 <<
" Difficult track - taking many sub steps." <<
G4endl;
423 printStatus( SubStepStartState, SubStepStartState, CurrentProposedStepLength,
424 NewSafety, 0, pPhysVol );
426 printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength,
427 NewSafety, do_loop_count, pPhysVol );
433 }
while( (!intersects )
434 && (!fParticleIsLooping)
435 && (StepTaken + kCarTolerance < CurrentProposedStepLength)
436 && ( do_loop_count < fMax_loop_count ) );
438 if( do_loop_count >= fMax_loop_count
439 && (StepTaken + kCarTolerance < CurrentProposedStepLength) )
441 fParticleIsLooping =
true;
443 if ( ( fParticleIsLooping ) && (fVerboseLevel > 0) )
446 CurrentProposedStepLength, methodName,
455 End_PointAndTangent = CurrentState;
456 TruePathLength = StepTaken;
462 fLastStepInVolume = intersects;
466 pFieldTrack = End_PointAndTangent;
472 - End_PointAndTangent.
GetCurveLength()) > 3.e-4 * TruePathLength )
474 std::ostringstream message;
475 message <<
"Curve length mis-match between original state "
476 <<
"and proposed endpoint of propagation." <<
G4endl
477 <<
" The curve length of the endpoint should be: "
479 <<
" and it is instead: "
481 <<
" A difference of: "
484 <<
" Original state = " << OriginalState <<
G4endl
485 <<
" Proposed state = " << End_PointAndTangent;
490 if( TruePathLength+kCarTolerance >= CurrentProposedStepLength )
499 if( TruePathLength < std::max( fZeroStepThreshold, 0.5*kCarTolerance ) )
508 if( fNoZeroStep > fAbandonThreshold_NoZeroSteps )
510 fParticleIsLooping =
true;
512 fFull_CurveLen_of_LastAttempt, pPhysVol );
517 return TruePathLength;
531 const G4int verboseLevel = fVerboseLevel;
541 if( ((stepNo == 0) && (verboseLevel <3)) || (verboseLevel >= 3) )
543 oldprec =
G4cout.precision(4);
544 G4cout << std::setw( 5) <<
"Step#"
545 << std::setw(10) <<
" s " <<
" "
546 << std::setw(10) <<
"X(mm)" <<
" "
547 << std::setw(10) <<
"Y(mm)" <<
" "
548 << std::setw(10) <<
"Z(mm)" <<
" "
549 << std::setw( 7) <<
" N_x " <<
" "
550 << std::setw( 7) <<
" N_y " <<
" "
551 << std::setw( 7) <<
" N_z " <<
" " ;
552 G4cout << std::setw( 7) <<
" Delta|N|" <<
" "
553 << std::setw( 9) <<
"StepLen" <<
" "
554 << std::setw(12) <<
"StartSafety" <<
" "
555 << std::setw( 9) <<
"PhsStep" <<
" ";
556 if( startVolume !=
nullptr )
557 {
G4cout << std::setw(18) <<
"NextVolume" <<
" "; }
558 G4cout.precision(oldprec);
561 if((stepNo == 0) && (verboseLevel <=3))
565 printStatus( StartFT, StartFT, -1.0, safety, -1, startVolume);
567 if( verboseLevel <= 3 )
570 {
G4cout << std::setw( 4) << stepNo <<
" "; }
572 {
G4cout << std::setw( 5) <<
"Start" ; }
573 oldprec =
G4cout.precision(8);
576 G4cout << std::setw(10) << CurrentPosition.
x() <<
" "
577 << std::setw(10) << CurrentPosition.
y() <<
" "
578 << std::setw(10) << CurrentPosition.
z() <<
" ";
580 G4cout << std::setw( 7) << CurrentUnitVelocity.
x() <<
" "
581 << std::setw( 7) << CurrentUnitVelocity.
y() <<
" "
582 << std::setw( 7) << CurrentUnitVelocity.
z() <<
" ";
586 G4cout << std::setw( 9) << step_len <<
" ";
587 G4cout << std::setw(12) << safety <<
" ";
588 if( requestStep != -1.0 )
589 {
G4cout << std::setw( 9) << requestStep <<
" "; }
591 {
G4cout << std::setw( 9) <<
"Init/NotKnown" <<
" "; }
592 if( startVolume != 0)
593 {
G4cout << std::setw(12) << startVolume->
GetName() <<
" "; }
594 G4cout.precision(oldprec);
601 G4cout <<
"Step taken was " << step_len
602 <<
" out of PhysicalStep = " << requestStep <<
G4endl;
604 G4cout <<
"Chord length = " << (CurrentPosition-StartPosition).mag()
621 G4cout <<
" " << std::setw(12) <<
" PiF: NoZeroStep "
622 <<
" " << std::setw(20) <<
" CurrentProposed len "
623 <<
" " << std::setw(18) <<
" Full_curvelen_last"
624 <<
" " << std::setw(18) <<
" last proposed len "
625 <<
" " << std::setw(18) <<
" decrease factor "
626 <<
" " << std::setw(15) <<
" step trial "
629 G4cout <<
" " << std::setw(10) << fNoZeroStep <<
" "
630 <<
" " << std::setw(20) << CurrentProposedStepLength
631 <<
" " << std::setw(18) << fFull_CurveLen_of_LastAttempt
632 <<
" " << std::setw(18) << fLast_ProposedStepLength
633 <<
" " << std::setw(18) << decreaseFactor
634 <<
" " << std::setw(15) << stepTrial
636 G4cout.precision( iprec );
648std::vector<G4ThreeVector>*
654 if (fpTrajectoryFilter !=
nullptr)
669 fpTrajectoryFilter = filter;
678 fParticleIsLooping =
false;
681 fSetFieldMgr =
false;
682 fEpsilonStep= 1.0e-5;
686 0.0,0.0,0.0,0.0,0.0);
687 fFull_CurveLen_of_LastAttempt = -1;
688 fLast_ProposedStepLength = -1;
691 fPreviousSafety= 0.0;
703 currentFieldMgr = fDetectorFieldMgr;
704 if( pCurrentPhysicalVolume !=
nullptr )
706 G4FieldManager *pRegionFieldMgr =
nullptr, *localFieldMgr =
nullptr;
709 if( pLogicalVol !=
nullptr )
714 if( pRegion !=
nullptr )
717 if( pRegionFieldMgr !=
nullptr )
719 currentFieldMgr= pRegionFieldMgr;
726 if ( localFieldMgr !=
nullptr )
728 currentFieldMgr = localFieldMgr;
732 fCurrentFieldMgr = currentFieldMgr;
738 return currentFieldMgr;
745 G4int oldval = fVerboseLevel;
746 fVerboseLevel = level;
753 G4cout <<
"Set Driver verbosity to " << fVerboseLevel - 2 <<
G4endl;
763 const char* methodName,
767 std::ostringstream message;
768 G4double fraction = StepTaken / StepRequested;
769 message <<
" Unfinished integration of track (likely looping particle) "
770 <<
" of momentum " << momentumVec <<
" ( magnitude = "
772 <<
" after " << count <<
" field substeps "
773 <<
" totaling " << std::setprecision(12) << StepTaken / mm <<
" mm "
774 <<
" out of requested step " << std::setprecision(12)
775 << StepRequested / mm <<
" mm ";
776 message <<
" a fraction of ";
778 if( fraction > 0.99 )
784 if (fraction > 0.97 ) { prec = 5; }
786 message << std::setprecision(prec)
787 << 100. * StepTaken / StepRequested <<
" % " <<
G4endl ;
790 message <<
" in volume " << pPhysVol->
GetName() ;
792 if( material !=
nullptr )
793 message <<
" with material " << material->
GetName()
795 << material->GetDensity() / ( g/(cm*cm*cm) ) <<
" g / cm^3 ) ";
799 message <<
" in unknown (null) volume. " ;
811 std::ostringstream message;
812 message <<
"Particle is stuck; it will be killed." <<
G4endl
813 <<
" Zero progress for " << noZeroSteps <<
" attempted steps."
815 <<
" Proposed Step is " << proposedStep
816 <<
" but Step Taken is "<< lastTriedStep <<
G4endl;
817 if( physVol !=
nullptr )
818 message <<
" in volume " << physVol->
GetName() ;
820 message <<
" in unknown or null volume. " ;
G4double epsilon(G4double density, G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
G4double GetDeltaChord() const
G4VIntegrationDriver * GetIntegrationDriver()
void SetDeltaChord(G4double newval)
G4double AdvanceChordLimited(G4FieldTrack &yCurrent, G4double stepInitial, G4double epsStep_Relative, const G4ThreeVector &latestSafetyOrigin, G4double lasestSafetyRadius)
G4double GetMinimumEpsilonStep() const
G4double GetMaximumEpsilonStep() const
G4double GetDeltaOneStep() const
G4double GetDeltaIntersection() const
const G4ThreeVector & GetMomentumDir() const
G4double GetCurveLength() const
G4ThreeVector GetPosition() const
G4ThreeVector GetMomentum() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4Region * GetRegion() const
G4Material * GetMaterial() const
G4FieldManager * GetFieldManager() const
const G4String & GetName() const
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
G4VPhysicalVolume * GetWorldVolume() const
void printStatus(const G4FieldTrack &startFT, const G4FieldTrack ¤tFT, G4double requestStep, G4double safety, G4int step, G4VPhysicalVolume *startVolume)
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
G4int SetVerboseLevel(G4int verbose)
void PrintStepLengthDiagnostic(G4double currentProposedStepLength, G4double decreaseFactor, G4double stepTrial, const G4FieldTrack &aFieldTrack)
G4PropagatorInField(G4Navigator *theNavigator, G4FieldManager *detectorFieldMgr, G4VIntersectionLocator *vLocator=nullptr)
void ReportStuckParticle(G4int noZeroSteps, G4double proposedStep, G4double lastTriedStep, G4VPhysicalVolume *physVol)
G4ChordFinder * GetChordFinder()
void ClearPropagatorState()
void RefreshIntersectionLocator()
void ReportLoopingParticle(G4int count, G4double StepTaken, G4double stepRequest, const char *methodName, G4ThreeVector momentumVec, G4VPhysicalVolume *physVol)
G4bool IntersectChord(const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint)
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
void SetTrajectoryFilter(G4VCurvedTrajectoryFilter *filter)
G4double ComputeStep(G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4double &pNewSafety, G4VPhysicalVolume *pPhysVol=nullptr, G4bool canRelaxDeltaChord=false)
void SetEpsilonStep(G4double newEps)
G4FieldManager * GetFieldManager() const
std::vector< G4ThreeVector > * GimmeThePointsAndForgetThem()
void CreateNewTrajectorySegment()
virtual void TakeIntermediatePoint(G4ThreeVector newPoint)=0
virtual void SetVerboseLevel(G4int level)=0
void SetDeltaIntersectionFor(G4double deltaIntersection)
void SetSafetyParametersFor(G4bool UseSafety)
void SetChordFinderFor(G4ChordFinder *fCFinder)
void SetEpsilonStepFor(G4double EpsilonStep)
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const