63 fMax_loop_count(1000),
64 fUseSafetyForOptimisation(true),
65 fZeroStepThreshold( 0.0 ),
66 fDetectorFieldMgr(detectorFieldMgr),
67 fpTrajectoryFilter( 0 ),
68 fNavigator(theNavigator),
69 fCurrentFieldMgr(detectorFieldMgr),
71 fCharge(0.0), fInitialMomentumModulus(0.0), fMass(0.0),
74 fParticleIsLooping(false),
79 else { fEpsilonStep= 1.0e-5; }
80 fActionThreshold_NoZeroSteps = 2;
81 fSevereActionThreshold_NoZeroSteps = 10;
82 fAbandonThreshold_NoZeroSteps = 50;
83 fFull_CurveLen_of_LastAttempt = -1;
84 fLast_ProposedStepLength = -1;
85 fLargestAcceptableStep = 1000.0 * meter;
90 fZeroStepThreshold= std::max( 1.0e5 * kCarTolerance, 1.0e-1 * micrometer );
93 G4cout <<
" PiF: Zero Step Threshold set to "
94 << fZeroStepThreshold / millimeter
96 G4cout <<
" PiF: Value of kCarTolerance = "
97 << kCarTolerance / millimeter
104 fAllocatedLocator=
true;
106 fIntersectionLocator=vLocator;
107 fAllocatedLocator=
false;
114 if(fAllocatedLocator)
delete fIntersectionLocator;
140 if(CurrentProposedStepLength<kCarTolerance)
147 if (fpTrajectoryFilter)
155 G4double TruePathLength = CurrentProposedStepLength;
159 G4bool first_substep =
true;
162 fParticleIsLooping =
false;
184 if( CurrentProposedStepLength >= fLargestAcceptableStep )
190 G4double trialProposedStep = 1.e2 * ( 10.0 * cm +
192 GetSolid()->DistanceToOut(StartPointA, VelocityUnit) );
193 CurrentProposedStepLength= std::min( trialProposedStep,
194 fLargestAcceptableStep );
196 epsilon = fCurrentFieldMgr->
GetDeltaOneStep() / CurrentProposedStepLength;
200 if( epsilon < epsilonMin ) epsilon = epsilonMin;
201 if( epsilon > epsilonMax ) epsilon = epsilonMax;
209 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
213 stepTrial= fFull_CurveLen_of_LastAttempt;
214 if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) )
215 stepTrial= fLast_ProposedStepLength;
218 if( (fNoZeroStep < fSevereActionThreshold_NoZeroSteps)
219 && (stepTrial > 100.0*fZeroStepThreshold) )
223 decreaseFactor= 0.25;
231 if( stepTrial > 100.0*fZeroStepThreshold )
232 decreaseFactor = 0.35;
233 else if( stepTrial > 30.0*fZeroStepThreshold )
235 else if( stepTrial > 10.0*fZeroStepThreshold )
236 decreaseFactor= 0.75;
240 stepTrial *= decreaseFactor;
243 G4cout <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
244 <<
" Decreasing step - "
245 <<
" decreaseFactor= " << std::setw(8) << decreaseFactor
246 <<
" stepTrial = " << std::setw(18) << stepTrial <<
" "
247 <<
" fZeroStepThreshold = " << fZeroStepThreshold <<
G4endl;
249 stepTrial, pFieldTrack);
251 if( stepTrial == 0.0 )
253 std::ostringstream message;
254 message <<
"Particle abandoned due to lack of progress in field."
256 <<
" Properties : " << pFieldTrack <<
G4endl
257 <<
" Attempting a zero step = " << stepTrial <<
G4endl
258 <<
" while attempting to progress after " << fNoZeroStep
259 <<
" trial steps. Will abandon step.";
260 G4Exception(
"G4PropagatorInField::ComputeStep()",
"GeomNav1002",
262 fParticleIsLooping=
true;
265 if( stepTrial < CurrentProposedStepLength )
266 CurrentProposedStepLength = stepTrial;
268 fLast_ProposedStepLength = CurrentProposedStepLength;
270 G4int do_loop_count = 0;
276 if( !first_substep) {
282 h_TrialStepSize = CurrentProposedStepLength - StepTaken;
295 fFull_CurveLen_of_LastAttempt = s_length_taken;
303 NewSafety, LinearStepLength,
304 InterSectionPointE );
308 if( first_substep ) {
309 currentSafety = NewSafety;
318 G4bool recalculatedEndPt=
false;
320 G4bool found_intersection = fIntersectionLocator->
321 EstimateIntersectionPoint( SubStepStartState, CurrentState,
322 InterSectionPointE, IntersectPointVelct_G,
323 recalculatedEndPt,fPreviousSafety,fPreviousSftOrigin);
324 intersects = intersects && found_intersection;
325 if( found_intersection ) {
326 End_PointAndTangent= IntersectPointVelct_G;
327 StepTaken = TruePathLength = IntersectPointVelct_G.
GetCurveLength()
331 if( recalculatedEndPt ){
332 CurrentState= IntersectPointVelct_G;
338 StepTaken += s_length_taken;
340 if (fpTrajectoryFilter) {
344 first_substep =
false;
347 if( fNoZeroStep > fActionThreshold_NoZeroSteps ) {
349 CurrentState, CurrentProposedStepLength,
350 NewSafety, do_loop_count, pPhysVol );
352 if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 )) {
353 if( do_loop_count == fMax_loop_count-9 ){
354 G4cout <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
355 <<
" Difficult track - taking many sub steps." <<
G4endl;
357 printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength,
358 NewSafety, do_loop_count, pPhysVol );
364 }
while( (!intersects )
365 && (StepTaken + kCarTolerance < CurrentProposedStepLength)
366 && ( do_loop_count < fMax_loop_count ) );
368 if( do_loop_count >= fMax_loop_count )
370 fParticleIsLooping =
true;
372 if ( fVerboseLevel > 0 )
374 G4cout <<
" G4PropagateInField::ComputeStep(): " <<
G4endl
375 <<
" Killing looping particle "
377 <<
" after " << do_loop_count <<
" field substeps "
378 <<
" totaling " << StepTaken / mm <<
" mm " ;
382 G4cout <<
" in unknown or null volume. " ;
392 End_PointAndTangent = CurrentState;
393 TruePathLength = StepTaken;
398 pFieldTrack = End_PointAndTangent;
404 - End_PointAndTangent.
GetCurveLength()) > 3.e-4 * TruePathLength )
406 std::ostringstream message;
407 message <<
"Curve length mis-match between original state "
408 <<
"and proposed endpoint of propagation." <<
G4endl
409 <<
" The curve length of the endpoint should be: "
411 <<
" and it is instead: "
413 <<
" A difference of: "
416 <<
" Original state = " << OriginalState <<
G4endl
417 <<
" Proposed state = " << End_PointAndTangent;
427 if( ( (TruePathLength < fZeroStepThreshold)
428 && ( TruePathLength+kCarTolerance < CurrentProposedStepLength )
430 || ( TruePathLength < 0.5*kCarTolerance )
439 if( fNoZeroStep > fAbandonThreshold_NoZeroSteps )
441 fParticleIsLooping =
true;
442 std::ostringstream message;
443 message <<
"Particle is stuck; it will be killed." <<
G4endl
444 <<
" Zero progress for " << fNoZeroStep <<
" attempted steps."
446 <<
" Proposed Step is " << CurrentProposedStepLength
447 <<
" but Step Taken is "<< fFull_CurveLen_of_LastAttempt <<
G4endl
448 <<
" For Particle with Charge = " << fCharge
449 <<
" Momentum = "<< fInitialMomentumModulus
450 <<
" Mass = " << fMass <<
G4endl;
452 message <<
" in volume " << pPhysVol->
GetName() ;
454 message <<
" in unknown or null volume. " ;
460 return TruePathLength;
475 const G4int verboseLevel=fVerboseLevel;
485 if( ((stepNo == 0) && (verboseLevel <3)) || (verboseLevel >= 3) )
487 oldprec =
G4cout.precision(4);
488 G4cout << std::setw( 6) <<
" "
489 << std::setw( 25) <<
" Current Position and Direction" <<
" "
491 G4cout << std::setw( 5) <<
"Step#"
492 << std::setw(10) <<
" s " <<
" "
493 << std::setw(10) <<
"X(mm)" <<
" "
494 << std::setw(10) <<
"Y(mm)" <<
" "
495 << std::setw(10) <<
"Z(mm)" <<
" "
496 << std::setw( 7) <<
" N_x " <<
" "
497 << std::setw( 7) <<
" N_y " <<
" "
498 << std::setw( 7) <<
" N_z " <<
" " ;
499 G4cout << std::setw( 7) <<
" Delta|N|" <<
" "
500 << std::setw( 9) <<
"StepLen" <<
" "
501 << std::setw(12) <<
"StartSafety" <<
" "
502 << std::setw( 9) <<
"PhsStep" <<
" ";
504 {
G4cout << std::setw(18) <<
"NextVolume" <<
" "; }
505 G4cout.precision(oldprec);
508 if((stepNo == 0) && (verboseLevel <=3))
512 printStatus( StartFT, StartFT, -1.0, safety, -1, startVolume);
514 if( verboseLevel <= 3 )
517 {
G4cout << std::setw( 4) << stepNo <<
" "; }
519 {
G4cout << std::setw( 5) <<
"Start" ; }
520 oldprec =
G4cout.precision(8);
523 G4cout << std::setw(10) << CurrentPosition.
x() <<
" "
524 << std::setw(10) << CurrentPosition.
y() <<
" "
525 << std::setw(10) << CurrentPosition.
z() <<
" ";
527 G4cout << std::setw( 7) << CurrentUnitVelocity.
x() <<
" "
528 << std::setw( 7) << CurrentUnitVelocity.
y() <<
" "
529 << std::setw( 7) << CurrentUnitVelocity.
z() <<
" ";
533 G4cout << std::setw( 9) << step_len <<
" ";
534 G4cout << std::setw(12) << safety <<
" ";
535 if( requestStep != -1.0 )
536 {
G4cout << std::setw( 9) << requestStep <<
" "; }
538 {
G4cout << std::setw( 9) <<
"Init/NotKnown" <<
" "; }
539 if( startVolume != 0)
540 {
G4cout << std::setw(12) << startVolume->
GetName() <<
" "; }
541 G4cout.precision(oldprec);
548 G4cout <<
"Step taken was " << step_len
549 <<
" out of PhysicalStep = " << requestStep <<
G4endl;
551 G4cout <<
"Chord length = " << (CurrentPosition-StartPosition).mag()
569 G4cout <<
" " << std::setw(12) <<
" PiF: NoZeroStep "
570 <<
" " << std::setw(20) <<
" CurrentProposed len "
571 <<
" " << std::setw(18) <<
" Full_curvelen_last"
572 <<
" " << std::setw(18) <<
" last proposed len "
573 <<
" " << std::setw(18) <<
" decrease factor "
574 <<
" " << std::setw(15) <<
" step trial "
577 G4cout <<
" " << std::setw(10) << fNoZeroStep <<
" "
578 <<
" " << std::setw(20) << CurrentProposedStepLength
579 <<
" " << std::setw(18) << fFull_CurveLen_of_LastAttempt
580 <<
" " << std::setw(18) << fLast_ProposedStepLength
581 <<
" " << std::setw(18) << decreaseFactor
582 <<
" " << std::setw(15) << stepTrial
584 G4cout.precision( iprec );
597std::vector<G4ThreeVector>*
603 if (fpTrajectoryFilter)
616 fpTrajectoryFilter = filter;
623 fParticleIsLooping=
false;
628 0.0,0.0,0.0,0.0,0.0);
629 fFull_CurveLen_of_LastAttempt = -1;
630 fLast_ProposedStepLength = -1;
633 fPreviousSafety= 0.0;
641 currentFieldMgr = fDetectorFieldMgr;
642 if( pCurrentPhysicalVolume)
652 if( pRegionFieldMgr )
653 currentFieldMgr= pRegionFieldMgr;
659 currentFieldMgr = localFieldMgr;
662 fCurrentFieldMgr= currentFieldMgr;
667 return currentFieldMgr;
672 G4int oldval= fVerboseLevel;
673 fVerboseLevel= level;
680 G4cout <<
"Set Driver verbosity to " << fVerboseLevel - 2 <<
G4endl;
CLHEP::Hep3Vector G4ThreeVector
G4DLLIMPORT std::ostream G4cout
void SetChargeMomentumMass(G4double pCharge, G4double pMomentum, G4double pMass)
G4double AdvanceChordLimited(G4FieldTrack &yCurrent, G4double stepInitial, G4double epsStep_Relative, const G4ThreeVector latestSafetyOrigin, G4double lasestSafetyRadius)
G4MagInt_Driver * GetIntegrationDriver()
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
G4FieldManager * GetFieldManager() const
void SetVerboseLevel(G4int newLevel)
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)
G4double ComputeStep(G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4double &pNewSafety, G4VPhysicalVolume *pPhysVol=0)
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
G4int SetVerboseLevel(G4int verbose)
void PrintStepLengthDiagnostic(G4double currentProposedStepLength, G4double decreaseFactor, G4double stepTrial, const G4FieldTrack &aFieldTrack)
G4ChordFinder * GetChordFinder()
void ClearPropagatorState()
void RefreshIntersectionLocator()
G4bool IntersectChord(const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint)
G4PropagatorInField(G4Navigator *theNavigator, G4FieldManager *detectorFieldMgr, G4VIntersectionLocator *vLocator=0)
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
void SetTrajectoryFilter(G4VCurvedTrajectoryFilter *filter)
void SetEpsilonStep(G4double newEps)
G4FieldManager * GetFieldManager() const
std::vector< G4ThreeVector > * GimmeThePointsAndForgetThem()
void CreateNewTrajectorySegment()
virtual void TakeIntermediatePoint(G4ThreeVector newPoint)=0
void SetDeltaIntersectionFor(G4double deltaIntersection)
void SetSafetyParametersFor(G4bool UseSafety)
void SetChordFinderFor(G4ChordFinder *fCFinder)
void SetEpsilonStepFor(G4double EpsilonStep)
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)