64 fMax_loop_count(1000),
65 fUseSafetyForOptimisation(true),
66 fZeroStepThreshold( 0.0 ),
67 fDetectorFieldMgr(detectorFieldMgr),
68 fpTrajectoryFilter( 0 ),
69 fNavigator(theNavigator),
70 fCurrentFieldMgr(detectorFieldMgr),
74 fParticleIsLooping(false),
78 fFirstStepInVolume(true),
79 fLastStepInVolume(true),
83 else { fEpsilonStep= 1.0e-5; }
84 fActionThreshold_NoZeroSteps = 2;
85 fSevereActionThreshold_NoZeroSteps = 10;
86 fAbandonThreshold_NoZeroSteps = 50;
87 fFull_CurveLen_of_LastAttempt = -1;
88 fLast_ProposedStepLength = -1;
89 fLargestAcceptableStep = 1000.0 *
meter;
97 G4cout <<
" PiF: Zero Step Threshold set to "
100 G4cout <<
" PiF: Value of kCarTolerance = "
104 fVerbTracePiF =
true;
111 fAllocatedLocator=
true;
115 fIntersectionLocator= vLocator;
116 fAllocatedLocator=
false;
125 if(fAllocatedLocator) {
delete fIntersectionLocator; }
154 if(CurrentProposedStepLength<kCarTolerance)
161 if (fpTrajectoryFilter)
166 fFirstStepInVolume = fNewTrack ?
true : fLastStepInVolume;
167 fLastStepInVolume=
false;
170 if( fVerboseLevel > 2 )
172 G4cout <<
"G4PropagatorInField::ComputeStep() called" <<
G4endl;
173 G4cout <<
" Starting FT: " << pFieldTrack;
174 G4cout <<
" Requested length = " << CurrentProposedStepLength <<
G4endl;
186 G4double TruePathLength = CurrentProposedStepLength;
190 G4bool first_substep =
true;
193 fParticleIsLooping =
false;
209 if( CurrentProposedStepLength >= fLargestAcceptableStep )
215 G4double trialProposedStep = 1.e2 * ( 10.0 *
cm +
217 GetSolid()->DistanceToOut(StartPointA, VelocityUnit) );
218 CurrentProposedStepLength=
std::min( trialProposedStep,
219 fLargestAcceptableStep );
221 epsilon = fCurrentFieldMgr->
GetDeltaOneStep() / CurrentProposedStepLength;
225 if( epsilon < epsilonMin ) epsilon = epsilonMin;
226 if( epsilon > epsilonMax ) epsilon = epsilonMax;
239 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
243 stepTrial= fFull_CurveLen_of_LastAttempt;
244 if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) )
245 stepTrial= fLast_ProposedStepLength;
248 if( (fNoZeroStep < fSevereActionThreshold_NoZeroSteps)
249 && (stepTrial > 100.0*fZeroStepThreshold) )
253 decreaseFactor= 0.25;
261 if( stepTrial > 100.0*fZeroStepThreshold )
262 decreaseFactor = 0.35;
263 else if( stepTrial > 30.0*fZeroStepThreshold )
265 else if( stepTrial > 10.0*fZeroStepThreshold )
266 decreaseFactor= 0.75;
270 stepTrial *= decreaseFactor;
273 G4cerr <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
274 <<
" Decreasing step - in volume " << pPhysVol;
276 G4cerr <<
" with name " << pPhysVol->GetName();
279 stepTrial, pFieldTrack);
281 if( stepTrial == 0.0 )
283 std::ostringstream message;
284 message <<
"Particle abandoned due to lack of progress in field."
286 <<
" Properties : " << pFieldTrack << G4endl
287 <<
" Attempting a zero step = " << stepTrial << G4endl
288 <<
" while attempting to progress after " << fNoZeroStep
289 <<
" trial steps. Will abandon step.";
290 G4Exception(
"G4PropagatorInField::ComputeStep()",
"GeomNav1002",
292 fParticleIsLooping=
true;
295 if( stepTrial < CurrentProposedStepLength )
296 CurrentProposedStepLength = stepTrial;
298 fLast_ProposedStepLength = CurrentProposedStepLength;
300 G4int do_loop_count = 0;
308 if( fVerboseLevel > 4 )
310 G4cout <<
" PiF: Calling Nav/Locate Global Point within-Volume "
318 h_TrialStepSize = CurrentProposedStepLength - StepTaken;
331 fFull_CurveLen_of_LastAttempt = s_length_taken;
339 NewSafety, LinearStepLength,
340 InterSectionPointE );
346 currentSafety = NewSafety;
355 G4bool recalculatedEndPt=
false;
357 G4bool found_intersection = fIntersectionLocator->
358 EstimateIntersectionPoint( SubStepStartState, CurrentState,
359 InterSectionPointE, IntersectPointVelct_G,
360 recalculatedEndPt, fPreviousSafety,
362 intersects = found_intersection;
363 if( found_intersection )
365 End_PointAndTangent= IntersectPointVelct_G;
366 StepTaken = TruePathLength = IntersectPointVelct_G.
GetCurveLength()
374 if( recalculatedEndPt )
380 G4bool shortEnd = endAchieved
389 CurrentState= IntersectPointVelct_G;
390 s_length_taken = stepAchieved;
393 fParticleIsLooping =
true;
400 StepTaken += s_length_taken;
402 if (fpTrajectoryFilter) {
406 first_substep =
false;
409 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
412 CurrentState, CurrentProposedStepLength,
413 NewSafety, do_loop_count, pPhysVol );
415 if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 ))
417 if( do_loop_count == fMax_loop_count-9 )
419 G4cout <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
420 <<
" Difficult track - taking many sub steps." <<
G4endl;
422 printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength,
423 NewSafety, do_loop_count, pPhysVol );
429 }
while( (!intersects )
430 && (!fParticleIsLooping)
431 && (StepTaken + kCarTolerance < CurrentProposedStepLength)
432 && ( do_loop_count < fMax_loop_count ) );
434 if( do_loop_count >= fMax_loop_count )
436 fParticleIsLooping =
true;
438 if ( fParticleIsLooping && (fVerboseLevel > 0) )
448 End_PointAndTangent = CurrentState;
449 TruePathLength = StepTaken;
454 fLastStepInVolume = intersects;
458 pFieldTrack = End_PointAndTangent;
464 - End_PointAndTangent.
GetCurveLength()) > 3.e-4 * TruePathLength )
466 std::ostringstream message;
467 message <<
"Curve length mis-match between original state "
468 <<
"and proposed endpoint of propagation." <<
G4endl
469 <<
" The curve length of the endpoint should be: "
471 <<
" and it is instead: "
473 <<
" A difference of: "
476 <<
" Original state = " << OriginalState <<
G4endl
477 <<
" Proposed state = " << End_PointAndTangent;
483 if( TruePathLength+kCarTolerance >= CurrentProposedStepLength )
492 if( TruePathLength <
std::max( fZeroStepThreshold, 0.5*kCarTolerance ) )
500 if( fNoZeroStep > fAbandonThreshold_NoZeroSteps )
502 fParticleIsLooping =
true;
503 ReportStuckParticle( fNoZeroStep, CurrentProposedStepLength, fFull_CurveLen_of_LastAttempt,
508 return TruePathLength;
523 const G4int verboseLevel=fVerboseLevel;
533 if( ((stepNo == 0) && (verboseLevel <3)) || (verboseLevel >= 3) )
535 oldprec =
G4cout.precision(4);
536 G4cout << std::setw( 6) <<
" "
537 << std::setw( 25) <<
" Current Position and Direction" <<
" "
539 G4cout << std::setw( 5) <<
"Step#"
540 << std::setw(10) <<
" s " <<
" "
541 << std::setw(10) <<
"X(mm)" <<
" "
542 << std::setw(10) <<
"Y(mm)" <<
" "
543 << std::setw(10) <<
"Z(mm)" <<
" "
544 << std::setw( 7) <<
" N_x " <<
" "
545 << std::setw( 7) <<
" N_y " <<
" "
546 << std::setw( 7) <<
" N_z " <<
" " ;
547 G4cout << std::setw( 7) <<
" Delta|N|" <<
" "
548 << std::setw( 9) <<
"StepLen" <<
" "
549 << std::setw(12) <<
"StartSafety" <<
" "
550 << std::setw( 9) <<
"PhsStep" <<
" ";
552 {
G4cout << std::setw(18) <<
"NextVolume" <<
" "; }
553 G4cout.precision(oldprec);
556 if((stepNo == 0) && (verboseLevel <=3))
560 printStatus( StartFT, StartFT, -1.0, safety, -1, startVolume);
562 if( verboseLevel <= 3 )
565 {
G4cout << std::setw( 4) << stepNo <<
" "; }
567 {
G4cout << std::setw( 5) <<
"Start" ; }
568 oldprec =
G4cout.precision(8);
571 G4cout << std::setw(10) << CurrentPosition.
x() <<
" "
572 << std::setw(10) << CurrentPosition.
y() <<
" "
573 << std::setw(10) << CurrentPosition.
z() <<
" ";
575 G4cout << std::setw( 7) << CurrentUnitVelocity.
x() <<
" "
576 << std::setw( 7) << CurrentUnitVelocity.
y() <<
" "
577 << std::setw( 7) << CurrentUnitVelocity.
z() <<
" ";
581 G4cout << std::setw( 9) << step_len <<
" ";
582 G4cout << std::setw(12) << safety <<
" ";
583 if( requestStep != -1.0 )
584 {
G4cout << std::setw( 9) << requestStep <<
" "; }
586 {
G4cout << std::setw( 9) <<
"Init/NotKnown" <<
" "; }
587 if( startVolume != 0)
588 {
G4cout << std::setw(12) << startVolume->
GetName() <<
" "; }
589 G4cout.precision(oldprec);
596 G4cout <<
"Step taken was " << step_len
597 <<
" out of PhysicalStep = " << requestStep <<
G4endl;
599 G4cout <<
"Chord length = " << (CurrentPosition-StartPosition).mag()
617 G4cout <<
" " << std::setw(12) <<
" PiF: NoZeroStep "
618 <<
" " << std::setw(20) <<
" CurrentProposed len "
619 <<
" " << std::setw(18) <<
" Full_curvelen_last"
620 <<
" " << std::setw(18) <<
" last proposed len "
621 <<
" " << std::setw(18) <<
" decrease factor "
622 <<
" " << std::setw(15) <<
" step trial "
625 G4cout <<
" " << std::setw(10) << fNoZeroStep <<
" "
626 <<
" " << std::setw(20) << CurrentProposedStepLength
627 <<
" " << std::setw(18) << fFull_CurveLen_of_LastAttempt
628 <<
" " << std::setw(18) << fLast_ProposedStepLength
629 <<
" " << std::setw(18) << decreaseFactor
630 <<
" " << std::setw(15) << stepTrial
632 G4cout.precision( iprec );
645 std::vector<G4ThreeVector>*
651 if (fpTrajectoryFilter)
666 fpTrajectoryFilter = filter;
673 fParticleIsLooping=
false;
678 0.0,0.0,0.0,0.0,0.0);
679 fFull_CurveLen_of_LastAttempt = -1;
680 fLast_ProposedStepLength = -1;
683 fPreviousSafety= 0.0;
691 currentFieldMgr = fDetectorFieldMgr;
692 if( pCurrentPhysicalVolume)
702 if( pRegionFieldMgr )
703 currentFieldMgr= pRegionFieldMgr;
709 currentFieldMgr = localFieldMgr;
712 fCurrentFieldMgr= currentFieldMgr;
718 return currentFieldMgr;
723 G4int oldval= fVerboseLevel;
724 fVerboseLevel= level;
731 G4cout <<
"Set Driver verbosity to " << fVerboseLevel - 2 <<
G4endl;
740 std::ostringstream message;
741 message <<
" Killing looping particle "
742 <<
" after " << count <<
" field substeps "
743 <<
" totaling " << StepTaken /
mm <<
" mm " ;
746 message <<
" in *volume* " << pPhysVol->
GetName() ;
750 message <<
" in unknown or null volume. " ;
752 G4Exception(
"G4PropagatorInField::ComputeStep()",
"GeomNav1002",
761 std::ostringstream message;
762 message <<
"Particle is stuck; it will be killed." <<
G4endl
763 <<
" Zero progress for " << noZeroSteps <<
" attempted steps."
765 <<
" Proposed Step is " << proposedStep
766 <<
" but Step Taken is "<< lastTriedStep <<
G4endl;
768 message <<
" in volume " << physVol->
GetName() ;
770 message <<
" in unknown or null volume. " ;
void SetEpsilonStep(G4double newEps)
static constexpr double mm
static const G4double kInfinity
G4double GetCurveLength() const
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
CLHEP::Hep3Vector G4ThreeVector
void SetVerboseLevel(G4int newLevel)
virtual void TakeIntermediatePoint(G4ThreeVector newPoint)=0
void PrintStepLengthDiagnostic(G4double currentProposedStepLength, G4double decreaseFactor, G4double stepTrial, const G4FieldTrack &aFieldTrack)
void RefreshIntersectionLocator()
G4double GetSurfaceTolerance() const
const G4ThreeVector & GetMomentumDir() const
G4double GetDeltaOneStep() const
std::vector< G4ThreeVector > * GimmeThePointsAndForgetThem()
G4PropagatorInField(G4Navigator *theNavigator, G4FieldManager *detectorFieldMgr, G4VIntersectionLocator *vLocator=0)
void SetChordFinderFor(G4ChordFinder *fCFinder)
G4Region * GetRegion() const
static constexpr double meter
G4int SetVerboseLevel(G4int verbose)
G4ThreeVector GetPosition() const
G4GLOB_DLL std::ostream G4cout
const G4String & GetName() const
void ReportLoopingParticle(G4int count, double StepTaken, G4VPhysicalVolume *pPhysVol)
G4double GetMaximumEpsilonStep() const
static constexpr double cm
void CreateNewTrajectorySegment()
static constexpr double perMillion
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4FieldManager * GetFieldManager() const
G4double AdvanceChordLimited(G4FieldTrack &yCurrent, G4double stepInitial, G4double epsStep_Relative, const G4ThreeVector latestSafetyOrigin, G4double lasestSafetyRadius)
G4double ComputeStep(G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4double &pNewSafety, G4VPhysicalVolume *pPhysVol=0)
G4double GetDeltaIntersection() const
G4LogicalVolume * GetLogicalVolume() const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void ReportStuckParticle(G4int noZeroSteps, G4double proposedStep, G4double lastTriedStep, G4VPhysicalVolume *physVol)
G4ChordFinder * GetChordFinder()
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static constexpr double millimeter
G4bool IntersectChord(const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint)
void SetTrajectoryFilter(G4VCurvedTrajectoryFilter *filter)
void ClearPropagatorState()
void SetSafetyParametersFor(G4bool UseSafety)
G4FieldManager * GetFieldManager() const
G4ThreeVector GetMomentum() const
G4MagInt_Driver * GetIntegrationDriver()
static constexpr double micrometer
G4VPhysicalVolume * GetWorldVolume() const
void SetEpsilonStepFor(G4double EpsilonStep)
double epsilon(double density, double temperature)
static G4GeometryTolerance * GetInstance()
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
G4GLOB_DLL std::ostream G4cerr
void SetDeltaIntersectionFor(G4double deltaIntersection)
void printStatus(const G4FieldTrack &startFT, const G4FieldTrack ¤tFT, G4double requestStep, G4double safety, G4int step, G4VPhysicalVolume *startVolume)
G4double GetMinimumEpsilonStep() const