Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MultiLevelLocator Class Reference

#include <G4MultiLevelLocator.hh>

+ Inheritance diagram for G4MultiLevelLocator:

Public Member Functions

 G4MultiLevelLocator (G4Navigator *theNavigator)
 
 ~G4MultiLevelLocator ()
 
G4bool EstimateIntersectionPoint (const G4FieldTrack &curveStartPointTangent, const G4FieldTrack &curveEndPointTangent, const G4ThreeVector &trialPoint, G4FieldTrack &intersectPointTangent, G4bool &recalculatedEndPoint, G4double &fPreviousSafety, G4ThreeVector &fPreviousSftOrigin)
 
void ReportStatistics ()
 
void SetMaxSteps (unsigned int valMax)
 
void SetWarnSteps (unsigned int valWarn)
 
- Public Member Functions inherited from G4VIntersectionLocator
 G4VIntersectionLocator (G4Navigator *theNavigator)
 
virtual ~G4VIntersectionLocator ()
 
virtual G4bool EstimateIntersectionPoint (const G4FieldTrack &curveStartPointTangent, const G4FieldTrack &curveEndPointTangent, const G4ThreeVector &trialPoint, G4FieldTrack &intersectPointTangent, G4bool &recalculatedEndPoint, G4double &fPreviousSafety, G4ThreeVector &fPreviousSftOrigin)=0
 
void printStatus (const G4FieldTrack &startFT, const G4FieldTrack &currentFT, G4double requestStep, G4double safety, G4int stepNum)
 
G4bool IntersectChord (const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &PreviousSafety, G4ThreeVector &PreviousSftOrigin, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint, G4bool *calledNavigator=nullptr)
 
void SetEpsilonStepFor (G4double EpsilonStep)
 
void SetDeltaIntersectionFor (G4double deltaIntersection)
 
void SetNavigatorFor (G4Navigator *fNavigator)
 
void SetChordFinderFor (G4ChordFinder *fCFinder)
 
void SetVerboseFor (G4int fVerbose)
 
G4int GetVerboseFor ()
 
G4double GetDeltaIntersectionFor ()
 
G4double GetEpsilonStepFor ()
 
G4NavigatorGetNavigatorFor ()
 
G4ChordFinderGetChordFinderFor ()
 
void SetSafetyParametersFor (G4bool UseSafety)
 
void AddAdjustementOfFoundIntersection (G4bool UseCorrection)
 
G4bool GetAdjustementOfFoundIntersection ()
 
void AdjustIntersections (G4bool UseCorrection)
 
G4bool AreIntersectionsAdjusted ()
 
void SetCheckMode (G4bool value)
 
G4bool GetCheckMode ()
 

Additional Inherited Members

- Static Public Member Functions inherited from G4VIntersectionLocator
static void printStatus (const G4FieldTrack &startFT, const G4FieldTrack &currentFT, G4double requestStep, G4double safety, G4int stepNum, std::ostream &oss, G4int verboseLevel)
 
- Protected Member Functions inherited from G4VIntersectionLocator
G4FieldTrack ReEstimateEndpoint (const G4FieldTrack &CurrentStateA, const G4FieldTrack &EstimtdEndStateB, G4double linearDistSq, G4double curveDist)
 
G4bool CheckAndReEstimateEndpoint (const G4FieldTrack &CurrentStartA, const G4FieldTrack &EstimatedEndB, G4FieldTrack &RevisedEndPoint, G4int &errorCode)
 
G4ThreeVector GetSurfaceNormal (const G4ThreeVector &CurrentInt_Point, G4bool &validNormal)
 
G4ThreeVector GetGlobalSurfaceNormal (const G4ThreeVector &CurrentE_Point, G4bool &validNormal)
 
G4bool AdjustmentOfFoundIntersection (const G4ThreeVector &A, const G4ThreeVector &CurrentE_Point, const G4ThreeVector &CurrentF_Point, const G4ThreeVector &MomentumDir, const G4bool IntersectAF, G4ThreeVector &IntersectionPoint, G4double &NewSafety, G4double &fPrevSafety, G4ThreeVector &fPrevSftOrigin)
 
void ReportTrialStep (G4int step_no, const G4ThreeVector &ChordAB_v, const G4ThreeVector &ChordEF_v, const G4ThreeVector &NewMomentumDir, const G4ThreeVector &NormalAtEntry, G4bool validNormal)
 
G4bool LocateGlobalPointWithinVolumeAndCheck (const G4ThreeVector &pos)
 
void LocateGlobalPointWithinVolumeCheckAndReport (const G4ThreeVector &pos, const G4String &CodeLocationInfo, G4int CheckMode)
 
void ReportReversedPoints (std::ostringstream &ossMsg, const G4FieldTrack &StartPointVel, const G4FieldTrack &EndPointVel, G4double NewSafety, G4double epsStep, const G4FieldTrack &CurrentA_PointVelocity, const G4FieldTrack &CurrentB_PointVelocity, const G4FieldTrack &SubStart_PointVelocity, const G4ThreeVector &CurrentE_Point, const G4FieldTrack &ApproxIntersecPointV, G4int sbstp_no, G4int sbstp_no_p, G4int depth)
 
void ReportProgress (std::ostream &oss, const G4FieldTrack &StartPointVel, const G4FieldTrack &EndPointVel, G4int substep_no, const G4FieldTrack &A_PtVel, const G4FieldTrack &B_PtVel, G4double safetyLast, G4int depth=-1)
 
void ReportImmediateHit (const char *MethodName, const G4ThreeVector &StartPosition, const G4ThreeVector &TrialPoint, G4double tolerance, unsigned long int numCalls)
 
- Protected Attributes inherited from G4VIntersectionLocator
G4double kCarTolerance
 
G4int fVerboseLevel = 0
 
G4bool fUseNormalCorrection = false
 
G4bool fCheckMode = false
 
G4bool fiUseSafety = false
 
G4NavigatorfiNavigator
 
G4ChordFinderfiChordFinder = nullptr
 
G4double fiEpsilonStep = -1.0
 
G4double fiDeltaIntersection = -1.0
 
G4NavigatorfHelpingNavigator
 
G4TouchableHistoryfpTouchable = nullptr
 

Detailed Description

Definition at line 47 of file G4MultiLevelLocator.hh.

Constructor & Destructor Documentation

◆ G4MultiLevelLocator()

G4MultiLevelLocator::G4MultiLevelLocator ( G4Navigator theNavigator)

Definition at line 39 of file G4MultiLevelLocator.cc.

40 : G4VIntersectionLocator(theNavigator)
41{
42 // In case of too slow progress in finding Intersection Point
43 // intermediates Points on the Track must be stored.
44 // Initialise the array of Pointers [max_depth+1] to do this
45
46 G4ThreeVector zeroV(0.0,0.0,0.0);
47 for ( auto idepth=0; idepth<max_depth+1; ++idepth )
48 {
49 ptrInterMedFT[ idepth ] = new G4FieldTrack( zeroV, zeroV, 0., 0., 0., 0.);
50 }
51
52 if (fCheckMode)
53 {
54 // Trial values Loose Medium Tight
55 // To happen: Infrequent Occasional Often
56 SetMaxSteps(150); // 300 85 25
57 SetWarnSteps(80); // 250 60 15
58 }
59}
void SetMaxSteps(unsigned int valMax)
void SetWarnSteps(unsigned int valWarn)

◆ ~G4MultiLevelLocator()

G4MultiLevelLocator::~G4MultiLevelLocator ( )

Definition at line 61 of file G4MultiLevelLocator.cc.

62{
63 for ( auto idepth=0; idepth<max_depth+1; ++idepth )
64 {
65 delete ptrInterMedFT[idepth];
66 }
67#ifdef G4DEBUG_FIELD
69#endif
70}

Member Function Documentation

◆ EstimateIntersectionPoint()

G4bool G4MultiLevelLocator::EstimateIntersectionPoint ( const G4FieldTrack curveStartPointTangent,
const G4FieldTrack curveEndPointTangent,
const G4ThreeVector trialPoint,
G4FieldTrack intersectPointTangent,
G4bool recalculatedEndPoint,
G4double fPreviousSafety,
G4ThreeVector fPreviousSftOrigin 
)
virtual

Implements G4VIntersectionLocator.

Definition at line 115 of file G4MultiLevelLocator.cc.

123{
124 // Find Intersection Point ( A, B, E ) of true path AB - start at E.
125 const char* MethodName= "G4MultiLevelLocator::EstimateIntersectionPoint()";
126
127 G4bool found_approximate_intersection = false;
128 G4bool there_is_no_intersection = false;
129
130 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity;
131 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity;
132 G4ThreeVector CurrentE_Point = TrialPoint;
133 G4bool validNormalAtE = false;
134 G4ThreeVector NormalAtEntry;
135
136 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
137 G4bool validIntersectP= true; // Is it current ?
138 G4double NewSafety = 0.0;
139 G4bool last_AF_intersection = false;
140
141 auto integrDriver = GetChordFinderFor()->GetIntegrationDriver();
142 G4bool driverReIntegrates = integrDriver->DoesReIntegrate();
143
144 G4bool first_section = true;
145 recalculatedEndPoint = false;
146 G4bool restoredFullEndpoint = false;
147
148 unsigned int substep_no = 0;
149
150 // Statistics for substeps
151 static G4ThreadLocal unsigned int max_no_seen= 0;
152
153#ifdef G4DEBUG_FIELD
154 unsigned int trigger_substepno_print = 0;
155 const G4double tolerance = 1.0e-8 * CLHEP::mm;
156 unsigned int biggest_depth = 0;
157 // using kInitialisingCL = G4LocatorChangeRecord::kInitialisingCL;
158#endif
159
160 // Log the location, iteration of changes in A,B
161 //----------------------------------------------
162 static G4ThreadLocal G4LocatorChangeLogger endChangeA("StartPointA"),
163 endChangeB("EndPointB"), recApproxPoint("ApproxPoint"),
164 pointH_logger("Trial points 'E': position, normal");
165 unsigned int eventCount = 0;
166
167 if (fCheckMode)
168 {
169 // Clear previous call's data
170 endChangeA.clear();
171 endChangeB.clear();
172 recApproxPoint.clear();
173 pointH_logger.clear();
174
175 // Record the initialisation
176 ++eventCount;
177 endChangeA.AddRecord( G4LocatorChangeRecord::kInitialisingCL, substep_no,
178 eventCount, CurrentA_PointVelocity );
179 endChangeB.AddRecord( G4LocatorChangeRecord::kInitialisingCL, substep_no,
180 eventCount, CurrentB_PointVelocity );
181 }
182
183 //--------------------------------------------------------------------------
184 // Algorithm for the case if progress in founding intersection is too slow.
185 // Process is defined too slow if after N=param_substeps advances on the
186 // path, it will be only 'fraction_done' of the total length.
187 // In this case the remaining length is divided in two half and
188 // the loop is restarted for each half.
189 // If progress is still too slow, the division in two halfs continue
190 // until 'max_depth'.
191 //--------------------------------------------------------------------------
192
193 const G4int param_substeps = 5; // Test value for the maximum number
194 // of substeps
195 const G4double fraction_done = 0.3;
196
197 G4bool Second_half = false; // First half or second half of divided step
198
199 // We need to know this for the 'final_section':
200 // real 'final_section' or first half 'final_section'
201 // In algorithm it is considered that the 'Second_half' is true
202 // and it becomes false only if we are in the first-half of level
203 // depthness or if we are in the first section
204
205 unsigned int depth = 0; // Depth counts subdivisions of initial step made
206 ++fNumCalls;
207
208 NormalAtEntry = GetSurfaceNormal(CurrentE_Point, validNormalAtE);
209
210 if (fCheckMode)
211 {
212 pointH_logger.AddRecord( G4LocatorChangeRecord::kInitialisingCL,
213 substep_no, eventCount,
214 G4FieldTrack( CurrentE_Point,0.,NormalAtEntry,0.,
215 0., 1.,G4ThreeVector(0.),0.,0.) );
216 #if (G4DEBUG_FIELD>1)
217 G4ThreeVector StartPosition = CurveStartPointVelocity.GetPosition();
218 if( (TrialPoint - StartPosition).mag2() < sqr(tolerance))
219 {
220 ReportImmediateHit( MethodName, StartPosition, TrialPoint,
221 tolerance, fNumCalls);
222 }
223 #endif
224 }
225
226 // Intermediates Points on the Track = Subdivided Points must be stored.
227 // Give the initial values to 'InterMedFt'
228 // Important is 'ptrInterMedFT[0]', it saves the 'EndCurvePoint'
229 //
230 *ptrInterMedFT[0] = CurveEndPointVelocity;
231 for ( auto idepth=1; idepth<max_depth+1; ++idepth )
232 {
233 *ptrInterMedFT[idepth] = CurveStartPointVelocity;
234 }
235
236 // Final_section boolean store
237 //
238 G4bool fin_section_depth[max_depth];
239 for ( auto idepth=0; idepth<max_depth; ++idepth )
240 {
241 fin_section_depth[idepth] = true;
242 }
243 // 'SubStartPoint' is needed to calculate the length of the divided step
244 //
245 G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
246
247 do // Loop checking, 07.10.2016, J.Apostolakis
248 {
249 unsigned int substep_no_p = 0;
250 G4bool sub_final_section = false; // the same as final_section,
251 // but for 'sub_section'
252 SubStart_PointVelocity = CurrentA_PointVelocity;
253
254 do // Loop checking, 07.10.2016, J.Apostolakis
255 { // REPEAT param
256
257#ifdef G4DEBUG_FIELD
258 if( CurrentA_PointVelocity.GetCurveLength() >=
259 CurrentB_PointVelocity.GetCurveLength() )
260 {
261 G4cerr << "ERROR> (Start) Point A coincides with or has gone past (end) point B"
262 << "MLL: iters = " << substep_no << G4endl;
263 // G4LocatorChangeRecord::ReportVector(G4cerr, "endPointB", endChangeB );
264 // G4cerr<<"EndPoints A(start) and B(end): combined changes " << G4endl;
265 G4LocatorChangeLogger::ReportEndChanges(G4cerr, endChangeA, endChangeB);
266 }
267#endif
268 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
269 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
270
271 // F = a point on true AB path close to point E
272 // (the closest if possible)
273 //
274 ApproxIntersecPointV = GetChordFinderFor()
275 ->ApproxCurvePointV( CurrentA_PointVelocity,
276 CurrentB_PointVelocity,
277 CurrentE_Point,
279 // The above method is the key & most intuitive part ...
280
281#ifdef G4DEBUG_FIELD
283 substep_no, eventCount, ApproxIntersecPointV ) );
284 G4double lenIntsc= ApproxIntersecPointV.GetCurveLength();
285 G4double lenB = CurrentB_PointVelocity.GetCurveLength();
286 G4double checkVsEnd= lenB - lenIntsc;
287
288 if( lenIntsc > lenB )
289 {
290 std::ostringstream errmsg;
291 errmsg.precision(17);
292 G4double ratio = checkVsEnd / lenB;
293 G4double ratioTol = std::fabs(ratio) / tolerance;
294 errmsg << "Intermediate F point is past end B point" << G4endl
295 << " l( intersection ) = " << lenIntsc << G4endl
296 << " l( endpoint ) = " << lenB << G4endl;
297 errmsg.precision(8);
298 errmsg << " l_end - l_inters = " << checkVsEnd << G4endl
299 << " / l_end = " << ratio << G4endl
300 << " ratio / tolerance = " << ratioTol << G4endl;
301 if( ratioTol < 1.0 )
302 G4Exception(MethodName, "GeomNav0003", JustWarning, errmsg );
303 else
304 G4Exception(MethodName, "GeomNav0003", FatalException, errmsg );
305 }
306#endif
307
308 G4ThreeVector CurrentF_Point= ApproxIntersecPointV.GetPosition();
309
310 // First check whether EF is small - then F is a good approx. point
311 // Calculate the length and direction of the chord AF
312 //
313 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
314
315 G4ThreeVector NewMomentumDir = ApproxIntersecPointV.GetMomentumDir();
316 G4double MomDir_dot_Norm = NewMomentumDir.dot( NormalAtEntry );
317
318#ifdef G4DEBUG_FIELD
319 if( fVerboseLevel > 3 )
320 {
321 G4ThreeVector ChordAB = Point_B - Point_A;
322 G4double ABchord_length = ChordAB.mag();
323 G4double MomDir_dot_ABchord;
324 MomDir_dot_ABchord = (1.0 / ABchord_length)
325 * NewMomentumDir.dot( ChordAB );
326 G4VIntersectionLocator::ReportTrialStep( substep_no, ChordAB,
327 ChordEF_Vector, NewMomentumDir, NormalAtEntry, validNormalAtE );
328 G4cout << " dot( MomentumDir, ABchord_unit ) = "
329 << MomDir_dot_ABchord << G4endl;
330 }
331#endif
332 G4bool adequate_angle =
333 ( MomDir_dot_Norm >= 0.0 ) // Can use ( > -epsilon) instead
334 || (! validNormalAtE ); // Invalid, cannot use this criterion
335 G4double EF_dist2 = ChordEF_Vector.mag2();
336 if ( ( EF_dist2 <= sqr(fiDeltaIntersection) && ( adequate_angle ) )
337 || ( EF_dist2 <= kCarTolerance*kCarTolerance ) )
338 {
339 found_approximate_intersection = true;
340
341 // Create the "point" return value
342 //
343 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
344 IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
345
347 {
348 // Try to Get Correction of IntersectionPoint using SurfaceNormal()
349 //
350 G4ThreeVector IP;
351 G4ThreeVector MomentumDir=ApproxIntersecPointV.GetMomentumDirection();
352 G4bool goodCorrection = AdjustmentOfFoundIntersection(Point_A,
353 CurrentE_Point, CurrentF_Point, MomentumDir,
354 last_AF_intersection, IP, NewSafety,
355 previousSafety, previousSftOrigin );
356 if ( goodCorrection )
357 {
358 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
359 IntersectedOrRecalculatedFT.SetPosition(IP);
360 }
361 }
362 // Note: in order to return a point on the boundary,
363 // we must return E. But it is F on the curve.
364 // So we must "cheat": we are using the position at point E
365 // and the velocity at point F !!!
366 //
367 // This must limit the length we can allow for displacement!
368 }
369 else // E is NOT close enough to the curve (ie point F)
370 {
371 // Check whether any volumes are encountered by the chord AF
372 // ---------------------------------------------------------
373 // First relocate to restore any Voxel etc information
374 // in the Navigator before calling ComputeStep()
375 //
377
378 G4ThreeVector PointG; // Candidate intersection point
379 G4double stepLengthAF;
380 G4bool Intersects_FB = false;
381 G4bool Intersects_AF = IntersectChord( Point_A, CurrentF_Point,
382 NewSafety, previousSafety,
383 previousSftOrigin,
384 stepLengthAF,
385 PointG );
386 last_AF_intersection = Intersects_AF;
387 if( Intersects_AF )
388 {
389 // G is our new Candidate for the intersection point.
390 // It replaces "E" and we will see if it's good enough.
391 CurrentB_PointVelocity = ApproxIntersecPointV; // B <- F
392 CurrentE_Point = PointG; // E <- G
393
394 validIntersectP = true; // 'E' has been updated.
395
396 G4bool validNormalLast;
397 NormalAtEntry = GetSurfaceNormal( PointG, validNormalLast );
398 validNormalAtE = validNormalLast;
399
400 // As we move point B, must take care in case the current
401 // AF has no intersection to try current FB!!
402 fin_section_depth[depth] = false;
403
404 if (fCheckMode)
405 {
406 ++eventCount;
407 endChangeB.push_back(
409 substep_no, eventCount, CurrentB_PointVelocity) );
410 }
411#ifdef G4VERBOSE
412 if( fVerboseLevel > 3 )
413 {
414 G4cout << "G4PiF::LI> Investigating intermediate point"
415 << " at s=" << ApproxIntersecPointV.GetCurveLength()
416 << " on way to full s="
417 << CurveEndPointVelocity.GetCurveLength() << G4endl;
418 }
419#endif
420 }
421 else // not Intersects_AF
422 {
423 // In this case:
424 // There is NO intersection of AF with a volume boundary.
425 // We must continue the search in the segment FB!
426 //
428
429 G4double stepLengthFB;
430 G4ThreeVector PointH;
431
432 // Check whether any volumes are encountered by the chord FB
433 // ---------------------------------------------------------
434
435 Intersects_FB = IntersectChord( CurrentF_Point, Point_B,
436 NewSafety, previousSafety,
437 previousSftOrigin,
438 stepLengthFB,
439 PointH );
440 if( Intersects_FB )
441 {
442 // There is an intersection of FB with a volume boundary
443 // H <- First Intersection of Chord FB
444
445 // H is our new Candidate for the intersection point.
446 // It replaces "E" and we will repeat the test to see if
447 // it is a good enough approximate point for us.
448
449 // Note that F must be in volume volA (the same as A)
450 // (otherwise AF would meet a volume boundary!)
451 // A <- F
452 // E <- H
453 //
454 CurrentA_PointVelocity = ApproxIntersecPointV;
455 CurrentE_Point = PointH;
456
457 validIntersectP = true; // 'E' has been updated.
458
459 G4bool validNormalH;
460 NormalAtEntry = GetSurfaceNormal( PointH, validNormalH );
461 validNormalAtE = validNormalH;
462
463 if (fCheckMode)
464 {
465 ++eventCount;
466 endChangeA.push_back(
468 substep_no, eventCount, CurrentA_PointVelocity) );
469 G4FieldTrack intersectH_pn('0'); // Point and normal
470 // nothing else will be valid
471 intersectH_pn.SetPosition( PointH );
472 intersectH_pn.SetMomentum( NormalAtEntry );
473 pointH_logger.AddRecord(G4LocatorChangeRecord::kIntersectsFB,
474 substep_no, eventCount, intersectH_pn );
475 }
476 }
477 else // not Intersects_FB
478 {
479 if( fin_section_depth[depth] )
480 {
481 // If B is the original endpoint, this means that whatever
482 // volume(s) intersected the original chord, none touch the
483 // smaller chords we have used.
484 // The value of 'IntersectedOrRecalculatedFT' returned is
485 // likely not valid
486
487 // Check on real final_section or SubEndSection
488 //
489 if( ((Second_half)&&(depth==0)) || (first_section) )
490 {
491 there_is_no_intersection = true; // real final_section
492 }
493 else
494 {
495 // end of subsection, not real final section
496 // exit from the and go to the depth-1 level
497 substep_no_p = param_substeps+2; // exit from the loop
498
499 // but 'Second_half' is still true because we need to find
500 // the 'CurrentE_point' for the next loop
501 Second_half = true;
502 sub_final_section = true;
503 }
504 }
505 else
506 {
507 CurrentA_PointVelocity = CurrentB_PointVelocity; // Got to B
508 CurrentB_PointVelocity = (depth==0) ? CurveEndPointVelocity
509 : *ptrInterMedFT[depth] ;
510 SubStart_PointVelocity = CurrentA_PointVelocity;
511 restoredFullEndpoint = true;
512
513 validIntersectP = false; // 'E' has NOT been updated.
514
515 if (fCheckMode)
516 {
517 ++eventCount;
518 endChangeA.push_back(
521 substep_no, eventCount, CurrentA_PointVelocity) );
522 endChangeB.push_back(
525 substep_no, eventCount, CurrentB_PointVelocity) );
526 }
527 }
528 } // Endif (Intersects_FB)
529 } // Endif (Intersects_AF)
530
531 G4int errorEndPt = 0; // Default: no error (if not calling CheckAnd...
532
533 G4bool recalculatedB= false;
534 if( driverReIntegrates )
535 {
536 G4FieldTrack RevisedB_FT = CurrentB_PointVelocity;
537 recalculatedB= CheckAndReEstimateEndpoint(CurrentA_PointVelocity,
538 CurrentB_PointVelocity,
539 RevisedB_FT,
540 errorEndPt );
541 if( recalculatedB )
542 {
543 CurrentB_PointVelocity = RevisedB_FT; // Use it !
544 // Do not invalidate intersection F -- it is still roughly OK.
545 //
546 // The best course would be to invalidate (reset validIntersectP)
547 // BUT if we invalidate it, we must re-estimate it somewhere! E.g.
548 // validIntersectP = false; // 'E' has NOT been updated.
549
550 if ( (fin_section_depth[depth]) // real final section
551 &&( first_section || ((Second_half)&&(depth==0)) ) )
552 {
553 recalculatedEndPoint = true;
554 IntersectedOrRecalculatedFT = RevisedB_FT;
555 // So that we can return it, if it is the endpoint!
556 }
557 // else
558 // Move forward the other points
559 // - or better flag it, so that they are re-computed when next used
560 // [ Implementation: a counter for # of recomputations
561 // => avoids extra work]
562 }
563 // else
564 // Move forward the other points
565 // - or better flag it, so that they are re-computed when next used
566 // [ Implementation: a counter for # of recomputations
567 // => avoids extra work]
568 if (fCheckMode)
569 {
570 ++eventCount;
571 endChangeB.push_back(
573 substep_no, eventCount, RevisedB_FT ) );
574 }
575 }
576 else
577 {
578 if( CurrentB_PointVelocity.GetCurveLength() < CurrentA_PointVelocity.GetCurveLength() )
579 errorEndPt = 2;
580 }
581
582 if( errorEndPt > 1 ) // errorEndPt = 1 is milder, just: len(B)=len(A)
583 {
584 std::ostringstream errmsg;
585 ReportReversedPoints(errmsg,
586 CurveStartPointVelocity, CurveEndPointVelocity,
587 NewSafety, fiEpsilonStep,
588 CurrentA_PointVelocity, CurrentB_PointVelocity,
589 SubStart_PointVelocity, CurrentE_Point,
590 ApproxIntersecPointV, substep_no, substep_no_p, depth);
591 errmsg << G4endl << " * Location: " << MethodName
592 << "- After EndIf(Intersects_AF)" << G4endl;
593 errmsg << " * Bool flags: Recalculated = " << recalculatedB
594 << " Intersects_AF = " << Intersects_AF
595 << " Intersects_FB = " << Intersects_FB << G4endl;
596 errmsg << " * Number of calls to MLL:EIP= " << fNumCalls << G4endl;
597 G4Exception(MethodName, "GeomNav0003", FatalException, errmsg);
598 }
599 if( restoredFullEndpoint )
600 {
601 fin_section_depth[depth] = restoredFullEndpoint;
602 restoredFullEndpoint = false;
603 }
604 } // EndIf ( E is close enough to the curve, ie point F. )
605 // tests ChordAF_Vector.mag() <= maximum_lateral_displacement
606
607#ifdef G4DEBUG_FIELD
608 if( trigger_substepno_print == 0)
609 {
610 trigger_substepno_print= fWarnSteps - 20;
611 }
612
613 if( substep_no >= trigger_substepno_print )
614 {
615 G4cout << "Difficulty in converging in " << MethodName
616 << " Substep no = " << substep_no << G4endl;
617 if( substep_no == trigger_substepno_print )
618 {
619 G4cout << " Start: ";
620 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
621 -1.0, NewSafety, 0 );
622
623 G4cout << " ** Change records: " << G4endl;
624 G4cout << "endPoints A (start) and B (end): combined changes of AB intervals" << G4endl;
625 G4LocatorChangeRecord::ReportEndChanges(G4cout, endChangeA, endChangeB );
626 }
627 G4cout << " Point A: ";
628 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
629 -1.0, NewSafety, substep_no-1 );
630 G4cout << " Point B: ";
631 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
632 -1.0, NewSafety, substep_no );
633 }
634#endif
635 ++substep_no;
636 ++substep_no_p;
637
638 } while ( ( ! found_approximate_intersection )
639 && ( ! there_is_no_intersection )
640 && ( substep_no_p <= param_substeps) ); // UNTIL found or
641 // failed param substep
642
643 if( (!found_approximate_intersection) && (!there_is_no_intersection) )
644 {
645 G4double did_len = std::abs( CurrentA_PointVelocity.GetCurveLength()
646 - SubStart_PointVelocity.GetCurveLength());
647 G4double all_len = std::abs( CurrentB_PointVelocity.GetCurveLength()
648 - SubStart_PointVelocity.GetCurveLength());
649
650 G4double distAB = -1;
651 //
652 // Is progress is too slow, and is it possible to go deeper?
653 // If so, then *halve the step*
654 // ==============
655 if( (did_len < fraction_done*all_len)
656 && (depth<max_depth) && (!sub_final_section) )
657 {
658#ifdef G4DEBUG_FIELD
659 static G4ThreadLocal unsigned int numSplits=0; // For debugging only
660 biggest_depth = std::max(depth, biggest_depth);
661 ++numSplits;
662#endif
663 Second_half = false;
664 ++depth;
665 first_section = false;
666
667 G4double Sub_len = (all_len-did_len)/(2.);
668 G4FieldTrack midPoint = CurrentA_PointVelocity;
669 G4bool fullAdvance=
670 integrDriver->AccurateAdvance(midPoint, Sub_len, fiEpsilonStep);
671
672 ++fNumAdvanceTrials;
673 if( fullAdvance ) { ++fNumAdvanceFull; }
674
675 G4double lenAchieved=
676 midPoint.GetCurveLength()-CurrentA_PointVelocity.GetCurveLength();
677
678 const G4double adequateFraction = (1.0-CLHEP::perThousand);
679 G4bool goodAdvance = (lenAchieved >= adequateFraction * Sub_len);
680 if ( goodAdvance ) { ++fNumAdvanceGood; }
681
682#ifdef G4DEBUG_FIELD
683 else // !goodAdvance
684 {
685 G4cout << "MLL> AdvanceChordLimited not full at depth=" << depth
686 << " total length achieved = " << lenAchieved << " of "
687 << Sub_len << " fraction= ";
688 if (Sub_len != 0.0 ) { G4cout << lenAchieved / Sub_len; }
689 else { G4cout << "DivByZero"; }
690 G4cout << " Good-enough fraction = " << adequateFraction;
691 G4cout << " Number of call to mll = " << fNumCalls
692 << " iteration " << substep_no
693 << " inner = " << substep_no_p << G4endl;
694 G4cout << " Epsilon of integration = " << fiEpsilonStep << G4endl;
695 G4cout << " State at start is = " << CurrentA_PointVelocity
696 << G4endl
697 << " at end (midpoint)= " << midPoint << G4endl;
698 G4cout << " Particle mass = " << midPoint.GetRestMass() << G4endl;
699
700 G4EquationOfMotion *equation = integrDriver->GetEquationOfMotion();
701 ReportFieldValue( CurrentA_PointVelocity, "start", equation );
702 ReportFieldValue( midPoint, "midPoint", equation );
703 G4cout << " Original Start = "
704 << CurveStartPointVelocity << G4endl;
705 G4cout << " Original End = "
706 << CurveEndPointVelocity << G4endl;
707 G4cout << " Original TrialPoint = "
708 << TrialPoint << G4endl;
709 G4cout << " (this is STRICT mode) "
710 << " num Splits= " << numSplits;
711 G4cout << G4endl;
712 }
713#endif
714
715 *ptrInterMedFT[depth] = midPoint;
716 CurrentB_PointVelocity = midPoint;
717
718 if (fCheckMode)
719 {
720 ++eventCount;
721 endChangeB.push_back(
723 substep_no, eventCount, midPoint) );
724 }
725
726 // Adjust 'SubStartPoint' to calculate the 'did_length' in next loop
727 //
728 SubStart_PointVelocity = CurrentA_PointVelocity;
729
730 // Find new trial intersection point needed at start of the loop
731 //
732 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
733 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
734
735 G4ThreeVector PointGe;
737 G4bool Intersects_AB = IntersectChord(Point_A, Point_B,
738 NewSafety, previousSafety,
739 previousSftOrigin, distAB,
740 PointGe);
741 if( Intersects_AB )
742 {
743 last_AF_intersection = Intersects_AB;
744 CurrentE_Point = PointGe;
745 fin_section_depth[depth] = true;
746
747 validIntersectP = true; // 'E' has been updated.
748
749 G4bool validNormalAB;
750 NormalAtEntry = GetSurfaceNormal( PointGe, validNormalAB );
751 validNormalAtE = validNormalAB;
752 }
753 else
754 {
755 // No intersection found for first part of curve
756 // (CurrentA,InterMedPoint[depth]). Go to the second part
757 //
758 Second_half = true;
759
760 validIntersectP= false; // No new 'E' chord intersection found
761 }
762 } // if did_len
763
764 unsigned int levelPops = 0;
765
766 G4bool unfinished = Second_half;
767 while ( unfinished && (depth>0) ) // Loop checking, 07.10.2016, JA
768 {
769 // Second part of curve (InterMed[depth],Intermed[depth-1]))
770 // On the depth-1 level normally we are on the 'second_half'
771
772 ++levelPops;
773
774 // Find new trial intersection point needed at start of the loop
775 //
776 SubStart_PointVelocity = *ptrInterMedFT[depth];
777 CurrentA_PointVelocity = *ptrInterMedFT[depth];
778 CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
779
780 if (fCheckMode)
781 {
782 ++eventCount;
784 substep_no, eventCount, CurrentA_PointVelocity);
785 endChangeA.push_back( chngPop_a );
787 substep_no, eventCount, CurrentB_PointVelocity);
788 endChangeB.push_back( chngPop_b );
789 }
790
791 // Ensure that the new endpoints are not further apart in space
792 // than on the curve due to different errors in the integration
793 //
794 G4int errorEndPt = -1;
795 G4bool recalculatedB= false;
796 if( driverReIntegrates )
797 {
798 // Ensure that the new endpoints are not further apart in space
799 // than on the curve due to different errors in the integration
800 //
801 G4FieldTrack RevisedEndPointFT = CurrentB_PointVelocity;
802 recalculatedB =
803 CheckAndReEstimateEndpoint( CurrentA_PointVelocity,
804 CurrentB_PointVelocity,
805 RevisedEndPointFT,
806 errorEndPt );
807 if( recalculatedB )
808 {
809 CurrentB_PointVelocity = RevisedEndPointFT; // Use it !
810
811 if ( depth == 1 )
812 {
813 recalculatedEndPoint = true;
814 IntersectedOrRecalculatedFT = RevisedEndPointFT;
815 // So that we can return it, if it is the endpoint!
816 }
817 }
818 else
819 {
820 if( CurrentB_PointVelocity.GetCurveLength() < CurrentA_PointVelocity.GetCurveLength() )
821 errorEndPt = 2;
822 }
823
824 if (fCheckMode)
825 {
826 ++eventCount;
827 endChangeB.push_back(
829 substep_no, eventCount, RevisedEndPointFT));
830 }
831 }
832 if( errorEndPt > 1 ) // errorEndPt = 1 is milder, just: len(B)=len(A)
833 {
834 std::ostringstream errmsg;
835 ReportReversedPoints(errmsg,
836 CurveStartPointVelocity, CurveEndPointVelocity,
837 NewSafety, fiEpsilonStep,
838 CurrentA_PointVelocity, CurrentB_PointVelocity,
839 SubStart_PointVelocity, CurrentE_Point,
840 ApproxIntersecPointV, substep_no, substep_no_p, depth);
841 errmsg << " * Location: " << MethodName << "- Second-Half" << G4endl;
842 errmsg << " * Recalculated = " << recalculatedB << G4endl; // false
843 G4Exception(MethodName, "GeomNav0003", FatalException, errmsg);
844 }
845
846 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
847 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
848 G4ThreeVector PointGi;
850 G4bool Intersects_AB = IntersectChord(Point_A, Point_B, NewSafety,
851 previousSafety,
852 previousSftOrigin, distAB,
853 PointGi);
854 if( Intersects_AB )
855 {
856 last_AF_intersection = Intersects_AB;
857 CurrentE_Point = PointGi;
858
859 validIntersectP = true; // 'E' has been updated.
860 NormalAtEntry = GetSurfaceNormal( PointGi, validNormalAtE );
861 }
862 else
863 {
864 validIntersectP = false; // No new 'E' chord intersection found
865 if( depth == 1)
866 {
867 there_is_no_intersection = true;
868 }
869 }
870 depth--;
871 fin_section_depth[depth] = true;
872 unfinished = !validIntersectP;
873 }
874#ifdef G4DEBUG_FIELD
875 if( ! ( validIntersectP || there_is_no_intersection ) )
876 {
877 // What happened ??
878 G4cout << "MLL - WARNING Potential FAILURE: Conditions not met!"
879 << G4endl
880 << " Depth = " << depth << G4endl
881 << " Levels popped = " << levelPops
882 << " Num Substeps= " << substep_no << G4endl;
883 G4cout << " Found intersection= " << found_approximate_intersection
884 << G4endl;
885 G4cout << " Progress report: -- " << G4endl;
887 CurveStartPointVelocity, CurveEndPointVelocity,
888 substep_no, CurrentA_PointVelocity,
889 CurrentB_PointVelocity,
890 NewSafety, depth );
891 G4cout << G4endl;
892 }
893#endif
894 } // if(!found_aproximate_intersection)
895
896 assert( validIntersectP || there_is_no_intersection
897 || found_approximate_intersection);
898
899 } while ( ( ! found_approximate_intersection )
900 && ( ! there_is_no_intersection )
901 && ( substep_no <= fMaxSteps) ); // UNTIL found or failed
902
903 if( substep_no > max_no_seen )
904 {
905 max_no_seen = substep_no;
906#ifdef G4DEBUG_FIELD
907 if( max_no_seen > fWarnSteps )
908 {
909 trigger_substepno_print = max_no_seen-20; // Want to see last 20 steps
910 }
911#endif
912 }
913
914 if( !there_is_no_intersection && !found_approximate_intersection )
915 {
916 if( substep_no >= fMaxSteps)
917 {
918 // Since we cannot go further (yet), we return as far as we have gone
919
920 recalculatedEndPoint = true;
921 IntersectedOrRecalculatedFT = CurrentA_PointVelocity;
922 found_approximate_intersection = false;
923
924 std::ostringstream message;
925 message << G4endl;
926 message << "Convergence is requiring too many substeps: "
927 << substep_no << " ( limit = "<< fMaxSteps << ")"
928 << G4endl
929 << " Abandoning effort to intersect. " << G4endl << G4endl;
930 message << " Number of calls to MLL: " << fNumCalls;
931 message << " iteration = " << substep_no <<G4endl << G4endl;
932
933 message.precision( 12 );
934 G4double done_len = CurrentA_PointVelocity.GetCurveLength();
935 G4double full_len = CurveEndPointVelocity.GetCurveLength();
936 message << " Undertaken only length: " << done_len
937 << " out of " << full_len << " required." << G4endl
938 << " Remaining length = " << full_len - done_len;
939
940 message << " Start and end-point of requested Step:" << G4endl;
941 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
942 -1.0, NewSafety, 0, message, -1 );
943 message << " Start and end-point of current Sub-Step:" << G4endl;
944 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
945 -1.0, NewSafety, substep_no-1, message, -1 );
946 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
947 -1.0, NewSafety, substep_no, message, -1 );
948
949 G4Exception(MethodName, "GeomNav0003", JustWarning, message);
950 }
951 else if( substep_no >= fWarnSteps)
952 {
953 std::ostringstream message;
954 message << "Many substeps while trying to locate intersection."
955 << G4endl
956 << " Undertaken length: "
957 << CurrentB_PointVelocity.GetCurveLength()
958 << " - Needed: " << substep_no << " substeps." << G4endl
959 << " Warning number = " << fWarnSteps
960 << " and maximum substeps = " << fMaxSteps;
961 G4Exception(MethodName, "GeomNav1002", JustWarning, message);
962 }
963 }
964
965 return (!there_is_no_intersection) && found_approximate_intersection;
966 // Success or failure
967}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double mag2() const
double dot(const Hep3Vector &) const
double mag() const
G4FieldTrack ApproxCurvePointV(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4ThreeVector &currentEPoint, G4double epsStep)
G4VIntegrationDriver * GetIntegrationDriver()
G4double GetCurveLength() const
G4ThreeVector GetPosition() const
G4double GetRestMass() const
static std::ostream & ReportEndChanges(std::ostream &os, const G4LocatorChangeLogger &startA, const G4LocatorChangeLogger &endB)
static std::ostream & ReportEndChanges(std::ostream &os, const std::vector< G4LocatorChangeRecord > &startA, const std::vector< G4LocatorChangeRecord > &endB)
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
Definition: G4Navigator.cc:608
virtual G4bool DoesReIntegrate() const =0
G4Navigator * GetNavigatorFor()
G4ChordFinder * GetChordFinderFor()
G4ThreeVector GetSurfaceNormal(const G4ThreeVector &CurrentInt_Point, G4bool &validNormal)
void ReportTrialStep(G4int step_no, const G4ThreeVector &ChordAB_v, const G4ThreeVector &ChordEF_v, const G4ThreeVector &NewMomentumDir, const G4ThreeVector &NormalAtEntry, G4bool validNormal)
G4bool IntersectChord(const G4ThreeVector &StartPointA, const G4ThreeVector &EndPointB, G4double &NewSafety, G4double &PreviousSafety, G4ThreeVector &PreviousSftOrigin, G4double &LinearStepLength, G4ThreeVector &IntersectionPoint, G4bool *calledNavigator=nullptr)
G4bool CheckAndReEstimateEndpoint(const G4FieldTrack &CurrentStartA, const G4FieldTrack &EstimatedEndB, G4FieldTrack &RevisedEndPoint, G4int &errorCode)
void ReportProgress(std::ostream &oss, const G4FieldTrack &StartPointVel, const G4FieldTrack &EndPointVel, G4int substep_no, const G4FieldTrack &A_PtVel, const G4FieldTrack &B_PtVel, G4double safetyLast, G4int depth=-1)
G4double GetEpsilonStepFor()
void ReportImmediateHit(const char *MethodName, const G4ThreeVector &StartPosition, const G4ThreeVector &TrialPoint, G4double tolerance, unsigned long int numCalls)
G4bool GetAdjustementOfFoundIntersection()
void printStatus(const G4FieldTrack &startFT, const G4FieldTrack &currentFT, G4double requestStep, G4double safety, G4int stepNum)
G4bool AdjustmentOfFoundIntersection(const G4ThreeVector &A, const G4ThreeVector &CurrentE_Point, const G4ThreeVector &CurrentF_Point, const G4ThreeVector &MomentumDir, const G4bool IntersectAF, G4ThreeVector &IntersectionPoint, G4double &NewSafety, G4double &fPrevSafety, G4ThreeVector &fPrevSftOrigin)
void ReportReversedPoints(std::ostringstream &ossMsg, const G4FieldTrack &StartPointVel, const G4FieldTrack &EndPointVel, G4double NewSafety, G4double epsStep, const G4FieldTrack &CurrentA_PointVelocity, const G4FieldTrack &CurrentB_PointVelocity, const G4FieldTrack &SubStart_PointVelocity, const G4ThreeVector &CurrentE_Point, const G4FieldTrack &ApproxIntersecPointV, G4int sbstp_no, G4int sbstp_no_p, G4int depth)
T sqr(const T &x)
Definition: templates.hh:128
#define G4ThreadLocal
Definition: tls.hh:77

◆ ReportStatistics()

void G4MultiLevelLocator::ReportStatistics ( )

Definition at line 969 of file G4MultiLevelLocator.cc.

970{
971 G4cout << " Number of calls = " << fNumCalls << G4endl;
972 G4cout << " Number of split level ('advances'): "
973 << fNumAdvanceTrials << G4endl;
974 G4cout << " Number of full advances: "
975 << fNumAdvanceGood << G4endl;
976 G4cout << " Number of good advances: "
977 << fNumAdvanceFull << G4endl;
978}

Referenced by ~G4MultiLevelLocator().

◆ SetMaxSteps()

void G4MultiLevelLocator::SetMaxSteps ( unsigned int  valMax)
inline

Definition at line 71 of file G4MultiLevelLocator.hh.

71{ fMaxSteps= valMax; }

Referenced by G4MultiLevelLocator().

◆ SetWarnSteps()

void G4MultiLevelLocator::SetWarnSteps ( unsigned int  valWarn)
inline

Definition at line 72 of file G4MultiLevelLocator.hh.

72{ fWarnSteps= valWarn; }

Referenced by G4MultiLevelLocator().


The documentation for this class was generated from the following files: