Computes the next geometric Step.
121{
124
125
126
127
128 const char* methodName = "G4PropagatorInField::ComputeStep";
129 if (CurrentProposedStepLength<kCarTolerance)
130 {
131 return kInfinity;
132 }
133
134
135
136 if (fpTrajectoryFilter != nullptr)
137 {
138 fpTrajectoryFilter->CreateNewTrajectorySegment();
139 }
140
141 fFirstStepInVolume = fNewTrack ? true : fLastStepInVolume;
142 fLastStepInVolume = false;
143 fNewTrack = false;
144
145 if( fVerboseLevel > 2 )
146 {
148 G4cout <<
" Starting FT: " << pFieldTrack;
149 G4cout <<
" Requested length = " << CurrentProposedStepLength <<
G4endl;
151 if( pPhysVol != nullptr )
152 {
154 }
155 else
156 {
158 }
160 }
161
162
163
165 G4double TruePathLength = CurrentProposedStepLength;
169 G4bool first_substep =
true;
170
172 fParticleIsLooping = false;
173
174
175
176
177
178 if( !fSetFieldMgr )
179 {
181 }
182 fSetFieldMgr = false;
183
184 G4FieldTrack CurrentState(pFieldTrack);
185 G4FieldTrack OriginalState = CurrentState;
186
187
188
189
190 if( CurrentProposedStepLength >= fLargestAcceptableStep )
191 {
193 StartPointA = pFieldTrack.GetPosition();
194 VelocityUnit = pFieldTrack.GetMomentumDir();
195
196 G4double trialProposedStep = fMaxStepSizeMultiplier * ( fMinBigDistance +
197 fNavigator->GetWorldVolume()->GetLogicalVolume()->
198 GetSolid()->DistanceToOut(StartPointA, VelocityUnit) );
199 CurrentProposedStepLength = std::min( trialProposedStep,
200 fLargestAcceptableStep );
201 }
202 epsilon = fCurrentFieldMgr->GetDeltaOneStep() / CurrentProposedStepLength;
203 G4double epsilonMin= fCurrentFieldMgr->GetMinimumEpsilonStep();
204 G4double epsilonMax= fCurrentFieldMgr->GetMaximumEpsilonStep();
208
209
210
211
213
214
215
216 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
217 {
219
220 stepTrial = fFull_CurveLen_of_LastAttempt;
221 if( (stepTrial <= 0.0) && (fLast_ProposedStepLength > 0.0) )
222 {
223 stepTrial = fLast_ProposedStepLength;
224 }
225
227 if( (fNoZeroStep < fSevereActionThreshold_NoZeroSteps)
228 && (stepTrial > 100.0*fZeroStepThreshold) )
229 {
230
231
232 decreaseFactor= 0.25;
233 }
234 else
235 {
236
237
238
239
240 if( stepTrial > 100.0*fZeroStepThreshold ) {
241 decreaseFactor = 0.35;
242 } else if( stepTrial > 30.0*fZeroStepThreshold ) {
243 decreaseFactor= 0.5;
244 } else if( stepTrial > 10.0*fZeroStepThreshold ) {
245 decreaseFactor= 0.75;
246 } else {
247 decreaseFactor= 0.9;
248 }
249 }
250 stepTrial *= decreaseFactor;
251
252#ifdef G4DEBUG_FIELD
253 if( fVerboseLevel > 2
254 || (fNoZeroStep >= fSevereActionThreshold_NoZeroSteps) )
255 {
256 G4cerr <<
" " << methodName
257 << " Decreasing step after " << fNoZeroStep << " zero steps "
258 << " - in volume " << pPhysVol;
259 if( pPhysVol )
261 else
262 G4cerr <<
" i.e. *unknown* volume.";
265 stepTrial, pFieldTrack);
266 }
267#endif
268 if( stepTrial == 0.0 )
269 {
270 std::ostringstream message;
271 message << "Particle abandoned due to lack of progress in field."
273 <<
" Properties : " << pFieldTrack <<
G4endl
274 <<
" Attempting a zero step = " << stepTrial <<
G4endl
275 << " while attempting to progress after " << fNoZeroStep
276 << " trial steps. Will abandon step.";
278 fParticleIsLooping = true;
279 return 0;
280 }
281 if( stepTrial < CurrentProposedStepLength )
282 {
283 CurrentProposedStepLength = stepTrial;
284 }
285 }
286 fLast_ProposedStepLength = CurrentProposedStepLength;
287
288 G4int do_loop_count = 0;
289 do
290 {
291 G4FieldTrack SubStepStartState = CurrentState;
293
294 if(!first_substep)
295 {
296 if( fVerboseLevel > 4 )
297 {
298 G4cout <<
" PiF: Calling Nav/Locate Global Point within-Volume "
300 }
301 fNavigator->LocateGlobalPointWithinVolume( SubStartPoint );
302 }
303
304
305
306 h_TrialStepSize = CurrentProposedStepLength - StepTaken;
307
308 if (canRelaxDeltaChord &&
309 fIncreaseChordDistanceThreshold > 0 &&
310 do_loop_count > fIncreaseChordDistanceThreshold &&
311 do_loop_count % fIncreaseChordDistanceThreshold == 0)
312 {
315 );
316 }
317
318
319
321 CurrentState,
322 h_TrialStepSize,
323 fEpsilonStep,
324 fPreviousSftOrigin,
325 fPreviousSafety );
326
327
328 fFull_CurveLen_of_LastAttempt = s_length_taken;
329
333
334
335
337 NewSafety, LinearStepLength,
338 InterSectionPointE );
339
340
341
342 if( first_substep )
343 {
344 currentSafety = NewSafety;
345 }
346
347 if( intersects )
348 {
349 G4FieldTrack IntersectPointVelct_G(CurrentState);
350
351
352
353 G4bool recalculatedEndPt =
false;
354
355 G4bool found_intersection = fIntersectionLocator->
356 EstimateIntersectionPoint( SubStepStartState, CurrentState,
357 InterSectionPointE, IntersectPointVelct_G,
358 recalculatedEndPt, fPreviousSafety,
359 fPreviousSftOrigin);
360 intersects = found_intersection;
361 if( found_intersection )
362 {
363 End_PointAndTangent= IntersectPointVelct_G;
364 StepTaken = TruePathLength = IntersectPointVelct_G.GetCurveLength()
366 }
367 else
368 {
369
370
371
372 if( recalculatedEndPt )
373 {
374 G4double endAchieved = IntersectPointVelct_G.GetCurveLength();
375 G4double endExpected = CurrentState.GetCurveLength();
376
377
378 G4bool shortEnd = endAchieved
379 < (endExpected*(1.0-CLHEP::perMillion));
380
383
384
385
386
387 CurrentState = IntersectPointVelct_G;
388 s_length_taken = stepAchieved;
389 if( shortEnd )
390 {
391 fParticleIsLooping = true;
392 }
393 }
394 }
395 }
396 if( !intersects )
397 {
398 StepTaken += s_length_taken;
399
400 if (fpTrajectoryFilter != nullptr)
401 {
402 fpTrajectoryFilter->TakeIntermediatePoint(CurrentState.GetPosition());
403 }
404 }
405 first_substep = false;
406
407#ifdef G4DEBUG_FIELD
408 if( fNoZeroStep > fActionThreshold_NoZeroSteps )
409 {
410 if( fNoZeroStep > fSevereActionThreshold_NoZeroSteps )
411 G4cout <<
" Above 'Severe Action' threshold -- for Zero steps. ";
412 else
413 G4cout <<
" Above 'action' threshold -- for Zero steps. ";
414 G4cout <<
" Number of zero steps = " << fNoZeroStep <<
G4endl;
416 CurrentState, CurrentProposedStepLength,
417 NewSafety, do_loop_count, pPhysVol );
418 }
419 if( (fVerboseLevel > 1) && (do_loop_count > fMax_loop_count-10 ))
420 {
421 if( do_loop_count == fMax_loop_count-9 )
422 {
423 G4cout <<
" G4PropagatorInField::ComputeStep(): " <<
G4endl
424 <<
" Difficult track - taking many sub steps." <<
G4endl;
425 printStatus( SubStepStartState, SubStepStartState, CurrentProposedStepLength,
426 NewSafety, 0, pPhysVol );
427 }
428 printStatus( SubStepStartState, CurrentState, CurrentProposedStepLength,
429 NewSafety, do_loop_count, pPhysVol );
430 }
431#endif
432
433 ++do_loop_count;
434
435 } while( (!intersects )
436 && (!fParticleIsLooping)
437 && (StepTaken + kCarTolerance < CurrentProposedStepLength)
438 && ( do_loop_count < fMax_loop_count ) );
439
440 if( do_loop_count >= fMax_loop_count
441 && (StepTaken + kCarTolerance < CurrentProposedStepLength) )
442 {
443 fParticleIsLooping = true;
444 }
445 if ( ( fParticleIsLooping ) && (fVerboseLevel > 0) )
446 {
448 CurrentProposedStepLength, methodName,
449 CurrentState.GetMomentum(), pPhysVol );
450 }
451
452 if( !intersects )
453 {
454
455
456
457 End_PointAndTangent = CurrentState;
458 TruePathLength = StepTaken;
459
460
461
462
463 }
464 fLastStepInVolume = intersects;
465
466
467
468 pFieldTrack = End_PointAndTangent;
469
470#ifdef G4VERBOSE
471
472
474 - End_PointAndTangent.GetCurveLength()) > 3.e-4 * TruePathLength )
475 {
476 std::ostringstream message;
477 message << "Curve length mis-match between original state "
478 <<
"and proposed endpoint of propagation." <<
G4endl
479 << " The curve length of the endpoint should be: "
481 << " and it is instead: "
482 << End_PointAndTangent.GetCurveLength() <<
"." <<
G4endl
483 << " A difference of: "
485 - End_PointAndTangent.GetCurveLength() <<
G4endl
486 <<
" Original state = " << OriginalState <<
G4endl
487 << " Proposed state = " << End_PointAndTangent;
489 }
490#endif
491
492 if( TruePathLength+kCarTolerance >= CurrentProposedStepLength )
493 {
494 fNoZeroStep = 0;
495 }
496 else
497 {
498
499
500
501 if( TruePathLength < std::max( fZeroStepThreshold, 0.5*kCarTolerance ) )
502 {
503 ++fNoZeroStep;
504 }
505 else
506 {
507 fNoZeroStep = 0;
508 }
509 }
510 if( fNoZeroStep > fAbandonThreshold_NoZeroSteps )
511 {
512 fParticleIsLooping = true;
514 fFull_CurveLen_of_LastAttempt, pPhysVol );
515 fNoZeroStep = 0;
516 }
517
519 return TruePathLength;
520}
G4double epsilon(G4double density, G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4GLOB_DLL std::ostream G4cerr
G4double GetDeltaChord() const
void OnComputeStep(const G4FieldTrack *track)
void SetDeltaChord(G4double newval)
G4double AdvanceChordLimited(G4FieldTrack &yCurrent, G4double stepInitial, G4double epsStep_Relative, const G4ThreeVector &latestSafetyOrigin, G4double lasestSafetyRadius)
G4double GetCurveLength() const
void printStatus(const G4FieldTrack &startFT, const G4FieldTrack ¤tFT, G4double requestStep, G4double safety, G4int step, G4VPhysicalVolume *startVolume)
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
void PrintStepLengthDiagnostic(G4double currentProposedStepLength, G4double decreaseFactor, G4double stepTrial, const G4FieldTrack &aFieldTrack)
void ReportStuckParticle(G4int noZeroSteps, G4double proposedStep, G4double lastTriedStep, G4VPhysicalVolume *physVol)
G4ChordFinder * GetChordFinder()
G4bool IntersectChord(const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint)
void ReportLoopingParticle(G4int count, G4double StepTaken, G4double stepRequest, const char *methodName, const G4ThreeVector &momentumVec, G4VPhysicalVolume *physVol)
void SetEpsilonStep(G4double newEps)
const G4String & GetName() const