Geant4-11
G4BrentLocator.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// class G4BrentLocator implementation
27//
28// 27.10.08 - Tatiana Nikitina.
29// 04.10.11 - John Apostolakis, revised convergence to use Surface Normal
30// ---------------------------------------------------------------------------
31
32#include <iomanip>
33
34#include "G4BrentLocator.hh"
35#include "G4ios.hh"
36
38 : G4VIntersectionLocator(theNavigator)
39{
40 // In case of too slow progress in finding Intersection Point
41 // intermediates Points on the Track must be stored.
42 // Initialise the array of Pointers [max_depth+1] to do this
43
44 G4ThreeVector zeroV(0.0,0.0,0.0);
45 for (auto idepth=0; idepth<max_depth+1; ++idepth )
46 {
47 ptrInterMedFT[ idepth ] = new G4FieldTrack( zeroV, zeroV, 0., 0., 0., 0.);
48 }
49}
50
52{
53 for ( auto idepth=0; idepth<max_depth+1; ++idepth )
54 {
55 delete ptrInterMedFT[idepth];
56 }
57}
58
59// --------------------------------------------------------------------------
60// G4bool G4PropagatorInField::LocateIntersectionPoint(
61// const G4FieldTrack& CurveStartPointVelocity, // A
62// const G4FieldTrack& CurveEndPointVelocity, // B
63// const G4ThreeVector& TrialPoint, // E
64// G4FieldTrack& IntersectedOrRecalculated // Output
65// G4bool& recalculated) // Out
66// --------------------------------------------------------------------------
67//
68// Function that returns the intersection of the true path with the surface
69// of the current volume (either the external one or the inner one with one
70// of the daughters:
71//
72// A = Initial point
73// B = another point
74//
75// Both A and B are assumed to be on the true path:
76//
77// E is the first point of intersection of the chord AB with
78// a volume other than A (on the surface of A or of a daughter)
79//
80// Convention of Use :
81// i) If it returns "true", then IntersectionPointVelocity is set
82// to the approximate intersection point.
83// ii) If it returns "false", no intersection was found.
84// The validity of IntersectedOrRecalculated depends on 'recalculated'
85// a) if latter is false, then IntersectedOrRecalculated is invalid.
86// b) if latter is true, then IntersectedOrRecalculated is
87// the new endpoint, due to a re-integration.
88// --------------------------------------------------------------------------
89// NOTE: implementation taken from G4PropagatorInField
90// New second order locator is added
91//
93 const G4FieldTrack& CurveStartPointVelocity, // A
94 const G4FieldTrack& CurveEndPointVelocity, // B
95 const G4ThreeVector& TrialPoint, // E
96 G4FieldTrack& IntersectedOrRecalculatedFT, // Output
97 G4bool& recalculatedEndPoint, // Out
98 G4double& fPreviousSafety, // In/Out
100
101{
102 // Find Intersection Point ( A, B, E ) of true path AB - start at E.
103
104 G4bool found_approximate_intersection = false;
105 G4bool there_is_no_intersection = false;
106
107 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity;
108 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity;
109 G4ThreeVector CurrentE_Point = TrialPoint;
110 G4bool validNormalAtE = false;
111 G4ThreeVector NormalAtEntry;
112
113 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
114 G4double NewSafety = 0.0;
115 G4bool last_AF_intersection = false;
116
117 // G4bool final_section= true; // Shows whether current section is last
118 // (i.e. B=full end)
119 G4bool first_section = true;
120 recalculatedEndPoint = false;
121
122 G4bool restoredFullEndpoint = false;
123
124 G4int oldprc; // cout, cerr precision
125 G4int substep_no = 0;
126
127 // Limits for substep number
128 //
129 const G4int max_substeps= 10000; // Test 120 (old value 100 )
130 const G4int warn_substeps= 1000; // 100
131
132 // Statistics for substeps
133 //
134 static G4ThreadLocal G4int max_no_seen= -1;
135
136 // Counter for restarting Bintermed
137 //
138 G4int restartB = 0;
139
140 //--------------------------------------------------------------------------
141 // Algorithm for the case if progress in founding intersection is too slow.
142 // Process is defined too slow if after N=param_substeps advances on the
143 // path, it will be only 'fraction_done' of the total length.
144 // In this case the remaining length is divided in two half and
145 // the loop is restarted for each half.
146 // If progress is still too slow, the division in two halfs continue
147 // until 'max_depth'.
148 //--------------------------------------------------------------------------
149
150 const G4int param_substeps = 50; // Test value for the maximum number
151 // of substeps
152 const G4double fraction_done = 0.3;
153
154 G4bool Second_half = false; // First half or second half of divided step
155
156 NormalAtEntry = GetSurfaceNormal(CurrentE_Point, validNormalAtE);
157
158 // We need to know this for the 'final_section':
159 // real 'final_section' or first half 'final_section'
160 // In algorithm it is considered that the 'Second_half' is true
161 // and it becomes false only if we are in the first-half of level
162 // depthness or if we are in the first section
163
164 G4int depth = 0; // Depth counts how many subdivisions of initial step made
165
166#ifdef G4DEBUG_FIELD
167 const G4double tolerance = 1.0e-8;
168 G4ThreeVector StartPosition = CurveStartPointVelocity.GetPosition();
169 if( (TrialPoint - StartPosition).mag() < tolerance * CLHEP::mm )
170 {
171 G4Exception("G4BrentLocator::EstimateIntersectionPoint()",
172 "GeomNav1002", JustWarning,
173 "Intersection point F is exactly at start point A." );
174 }
175#endif
176
177 // Intermediates Points on the Track = Subdivided Points must be stored.
178 // Give the initial values to 'InterMedFt'
179 // Important is 'ptrInterMedFT[0]', it saves the 'EndCurvePoint'
180 //
181 *ptrInterMedFT[0] = CurveEndPointVelocity;
182 for (auto idepth=1; idepth<max_depth+1; ++idepth )
183 {
184 *ptrInterMedFT[idepth] = CurveStartPointVelocity;
185 }
186
187 //Final_section boolean store
188 G4bool fin_section_depth[max_depth];
189 for (auto idepth=0; idepth<max_depth; ++idepth )
190 {
191 fin_section_depth[idepth] = true;
192 }
193
194 // 'SubStartPoint' is needed to calculate the length of the divided step
195 //
196 G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
197
198 do // Loop checking, 07.10.2016, J.Apostolakis
199 {
200 G4int substep_no_p = 0;
201 G4bool sub_final_section = false; // the same as final_section,
202 // but for 'sub_section'
203 SubStart_PointVelocity = CurrentA_PointVelocity;
204
205 do // Loop checking, 07.10.2016, J.Apostolakis
206 { // REPEAT param
207 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
208 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
209
210 // F = a point on true AB path close to point E
211 // (the closest if possible)
212 //
213 if(substep_no_p==0)
214 {
215 ApproxIntersecPointV = GetChordFinderFor()
216 ->ApproxCurvePointV( CurrentA_PointVelocity,
217 CurrentB_PointVelocity,
218 CurrentE_Point,
220 // The above method is the key & most intuitive part ...
221 }
222#ifdef G4DEBUG_FIELD
223 if( ApproxIntersecPointV.GetCurveLength() >
224 CurrentB_PointVelocity.GetCurveLength() * (1.0 + tolerance) )
225 {
226 G4Exception("G4BrentLocator::EstimateIntersectionPoint()",
227 "GeomNav0003", FatalException,
228 "Intermediate F point is past end B point" );
229 }
230#endif
231
232 G4ThreeVector CurrentF_Point = ApproxIntersecPointV.GetPosition();
233
234 // First check whether EF is small - then F is a good approx. point
235 // Calculate the length and direction of the chord AF
236 //
237 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
238 G4ThreeVector NewMomentumDir = ApproxIntersecPointV.GetMomentumDir();
239 G4double MomDir_dot_Norm = NewMomentumDir.dot( NormalAtEntry ) ;
240
241#ifdef G4DEBUG_FIELD
242 G4ThreeVector ChordAB = Point_B - Point_A;
243
244 G4VIntersectionLocator::ReportTrialStep( substep_no, ChordAB,
245 ChordEF_Vector, NewMomentumDir, NormalAtEntry, validNormalAtE );
246#endif
247
248 G4bool adequate_angle;
249 adequate_angle = ( MomDir_dot_Norm >= 0.0 ) // Can use -epsilon instead.
250 || (! validNormalAtE ); // Makes criterion invalid
251 G4double EF_dist2 = ChordEF_Vector.mag2();
252 if ( ( EF_dist2 <= sqr(fiDeltaIntersection) && ( adequate_angle ) )
253 || ( EF_dist2 <= kCarTolerance*kCarTolerance ) )
254 {
255 found_approximate_intersection = true;
256
257 // Create the "point" return value
258 //
259 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
260 IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
261
263 {
264 // Try to Get Correction of IntersectionPoint using SurfaceNormal()
265 //
266 G4ThreeVector IP;
267 G4ThreeVector MomentumDir=ApproxIntersecPointV.GetMomentumDirection();
268 G4bool goodCorrection = AdjustmentOfFoundIntersection( Point_A,
269 CurrentE_Point, CurrentF_Point, MomentumDir,
270 last_AF_intersection, IP, NewSafety,
272 if ( goodCorrection )
273 {
274 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
275 IntersectedOrRecalculatedFT.SetPosition(IP);
276 }
277 }
278
279 // Note: in order to return a point on the boundary,
280 // we must return E. But it is F on the curve.
281 // So we must "cheat": we are using the position at point E
282 // and the velocity at point F !!!
283 //
284 // This must limit the length we can allow for displacement!
285 }
286 else // E is NOT close enough to the curve (ie point F)
287 {
288 // Check whether any volumes are encountered by the chord AF
289 // ---------------------------------------------------------
290 // First relocate to restore any Voxel etc information
291 // in the Navigator before calling ComputeStep()
292 //
294
295 G4ThreeVector PointG; // Candidate intersection point
296 G4double stepLengthAF;
297 G4bool usedNavigatorAF = false;
298 G4bool Intersects_AF = IntersectChord( Point_A, CurrentF_Point,
299 NewSafety,fPreviousSafety,
301 stepLengthAF,
302 PointG,
303 &usedNavigatorAF);
304 last_AF_intersection = Intersects_AF;
305 if( Intersects_AF )
306 {
307 // G is our new Candidate for the intersection point.
308 // It replaces "E" and we will repeat the test to see if
309 // it is a good enough approximate point for us.
310 // B <- F
311 // E <- G
312 //
313 G4FieldTrack EndPoint = ApproxIntersecPointV;
314 ApproxIntersecPointV = GetChordFinderFor()->ApproxCurvePointS(
315 CurrentA_PointVelocity, CurrentB_PointVelocity,
316 EndPoint,CurrentE_Point, CurrentF_Point,PointG,
317 true, GetEpsilonStepFor() );
318 CurrentB_PointVelocity = EndPoint;
319 CurrentE_Point = PointG;
320
321 // Need to recalculate the Exit Normal at the new PointG
322 // Know that a call was made to Navigator::ComputeStep in
323 // IntersectChord above.
324 //
325 G4bool validNormalLast;
326 NormalAtEntry = GetSurfaceNormal( PointG, validNormalLast );
327 validNormalAtE = validNormalLast;
328
329 // By moving point B, must take care if current
330 // AF has no intersection to try current FB!!
331 //
332 fin_section_depth[depth] = false;
333#ifdef G4VERBOSE
334 if( fVerboseLevel > 3 )
335 {
336 G4cout << "G4PiF::LI> Investigating intermediate point"
337 << " at s=" << ApproxIntersecPointV.GetCurveLength()
338 << " on way to full s="
339 << CurveEndPointVelocity.GetCurveLength() << G4endl;
340 }
341#endif
342 }
343 else // not Intersects_AF
344 {
345 // In this case:
346 // There is NO intersection of AF with a volume boundary.
347 // We must continue the search in the segment FB!
348 //
350
351 G4double stepLengthFB;
352 G4ThreeVector PointH;
353 G4bool usedNavigatorFB = false;
354
355 // Check whether any volumes are encountered by the chord FB
356 // ---------------------------------------------------------
357
358 G4bool Intersects_FB = IntersectChord( CurrentF_Point, Point_B,
359 NewSafety,fPreviousSafety,
361 stepLengthFB,
362 PointH,
363 &usedNavigatorFB);
364 if( Intersects_FB )
365 {
366 // There is an intersection of FB with a volume boundary
367 // H <- First Intersection of Chord FB
368
369 // H is our new Candidate for the intersection point.
370 // It replaces "E" and we will repeat the test to see if
371 // it is a good enough approximate point for us.
372
373 // Note that F must be in volume volA (the same as A)
374 // (otherwise AF would meet a volume boundary!)
375 // A <- F
376 // E <- H
377 //
378 G4FieldTrack InterMed = ApproxIntersecPointV;
379 ApproxIntersecPointV = GetChordFinderFor()->ApproxCurvePointS(
380 CurrentA_PointVelocity,CurrentB_PointVelocity,
381 InterMed,CurrentE_Point,CurrentF_Point,PointH,
382 false,GetEpsilonStepFor());
383 CurrentA_PointVelocity = InterMed;
384 CurrentE_Point = PointH;
385
386 // Need to recalculate the Exit Normal at the new PointG
387 //
388 G4bool validNormalLast;
389 NormalAtEntry = GetSurfaceNormal( PointH, validNormalLast );
390 validNormalAtE = validNormalLast;
391 }
392 else // not Intersects_FB
393 {
394 // There is NO intersection of FB with a volume boundary
395
396 if( fin_section_depth[depth] )
397 {
398 // If B is the original endpoint, this means that whatever
399 // volume(s) intersected the original chord, none touch the
400 // smaller chords we have used.
401 // The value of 'IntersectedOrRecalculatedFT' returned is
402 // likely not valid
403
404 // Check on real final_section or SubEndSection
405 //
406 if( ((Second_half)&&(depth==0)) || (first_section) )
407 {
408 there_is_no_intersection = true; // real final_section
409 }
410 else
411 {
412 // end of subsection, not real final section
413 // exit from the and go to the depth-1 level
414
415 substep_no_p = param_substeps+2; // exit from the loop
416
417 // but 'Second_half' is still true because we need to find
418 // the 'CurrentE_point' for the next loop
419 //
420 Second_half = true;
421 sub_final_section = true;
422 }
423 }
424 else
425 {
426 if( depth==0 )
427 {
428 // We must restore the original endpoint
429 //
430 CurrentA_PointVelocity = CurrentB_PointVelocity; // Got to B
431 CurrentB_PointVelocity = CurveEndPointVelocity;
432 SubStart_PointVelocity = CurrentA_PointVelocity;
433 ApproxIntersecPointV = GetChordFinderFor()
434 ->ApproxCurvePointV( CurrentA_PointVelocity,
435 CurrentB_PointVelocity,
436 CurrentE_Point,
438
439 restoredFullEndpoint = true;
440 ++restartB; // counter
441 }
442 else
443 {
444 // We must restore the depth endpoint
445 //
446 CurrentA_PointVelocity = CurrentB_PointVelocity; // Got to B
447 CurrentB_PointVelocity = *ptrInterMedFT[depth];
448 SubStart_PointVelocity = CurrentA_PointVelocity;
449 ApproxIntersecPointV = GetChordFinderFor()
450 ->ApproxCurvePointV( CurrentA_PointVelocity,
451 CurrentB_PointVelocity,
452 CurrentE_Point,
454 restoredFullEndpoint = true;
455 ++restartB; // counter
456 }
457 }
458 } // Endif (Intersects_FB)
459 } // Endif (Intersects_AF)
460
461 // Ensure that the new endpoints are not further apart in space
462 // than on the curve due to different errors in the integration
463 //
464 G4double linDistSq, curveDist;
465 linDistSq = ( CurrentB_PointVelocity.GetPosition()
466 - CurrentA_PointVelocity.GetPosition() ).mag2();
467 curveDist = CurrentB_PointVelocity.GetCurveLength()
468 - CurrentA_PointVelocity.GetCurveLength();
469
470 // Change this condition for very strict parameters of propagation
471 //
472 if( curveDist*curveDist*(1+2* GetEpsilonStepFor()) < linDistSq )
473 {
474 // Re-integrate to obtain a new B
475 //
476 G4FieldTrack newEndPointFT=
477 ReEstimateEndpoint( CurrentA_PointVelocity,
478 CurrentB_PointVelocity,
479 linDistSq, // to avoid recalculation
480 curveDist );
481 G4FieldTrack oldPointVelB = CurrentB_PointVelocity;
482 CurrentB_PointVelocity = newEndPointFT;
483
484 if ( (fin_section_depth[depth]) // real final section
485 &&( first_section || ((Second_half)&&(depth==0)) ) )
486 {
487 recalculatedEndPoint = true;
488 IntersectedOrRecalculatedFT = newEndPointFT;
489 // So that we can return it, if it is the endpoint!
490 }
491 }
492 if( curveDist < 0.0 )
493 {
494 fVerboseLevel = 5; // Print out a maximum of information
495 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
496 -1.0, NewSafety, substep_no );
497 std::ostringstream message;
498 message << "Error in advancing propagation." << G4endl
499 << " Error in advancing propagation." << G4endl
500 << " Point A (start) is " << CurrentA_PointVelocity
501 << G4endl
502 << " Point B (end) is " << CurrentB_PointVelocity
503 << G4endl
504 << " Curve distance is " << curveDist << G4endl
505 << G4endl
506 << "The final curve point is not further along"
507 << " than the original!" << G4endl;
508
509 if( recalculatedEndPoint )
510 {
511 message << "Recalculation of EndPoint was called with fEpsStep= "
513 }
514 oldprc = G4cerr.precision(20);
515 message << " Point A (Curve start) is " << CurveStartPointVelocity
516 << G4endl
517 << " Point B (Curve end) is " << CurveEndPointVelocity
518 << G4endl
519 << " Point A (Current start) is " << CurrentA_PointVelocity
520 << G4endl
521 << " Point B (Current end) is " << CurrentB_PointVelocity
522 << G4endl
523 << " Point S (Sub start) is " << SubStart_PointVelocity
524 << G4endl
525 << " Point E (Trial Point) is " << CurrentE_Point
526 << G4endl
527 << " Old Point F(Intersection) is " << CurrentF_Point
528 << G4endl
529 << " New Point F(Intersection) is " << ApproxIntersecPointV
530 << G4endl
531 << " LocateIntersection parameters are : Substep no= "
532 << substep_no << G4endl
533 << " Substep depth no= "<< substep_no_p << " Depth= "
534 << depth << G4endl
535 << " Restarted no= "<< restartB << " Epsilon= "
536 << GetEpsilonStepFor() <<" DeltaInters= "
538 G4cerr.precision( oldprc );
539
540 G4Exception("G4BrentLocator::EstimateIntersectionPoint()",
541 "GeomNav0003", FatalException, message);
542 }
543
544 if( restoredFullEndpoint )
545 {
546 fin_section_depth[depth] = restoredFullEndpoint;
547 restoredFullEndpoint = false;
548 }
549 } // EndIf ( E is close enough to the curve, ie point F. )
550 // tests ChordAF_Vector.mag() <= maximum_lateral_displacement
551
552#ifdef G4DEBUG_LOCATE_INTERSECTION
553 G4int trigger_substepno_print= warn_substeps - 20 ;
554
555 if( substep_no >= trigger_substepno_print )
556 {
557 G4cout << "Difficulty in converging in "
558 << "G4BrentLocator::EstimateIntersectionPoint()"
559 << G4endl
560 << " Substep no = " << substep_no << G4endl;
561 if( substep_no == trigger_substepno_print )
562 {
563 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
564 -1.0, NewSafety, 0);
565 }
566 G4cout << " State of point A: ";
567 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
568 -1.0, NewSafety, substep_no-1, 0);
569 G4cout << " State of point B: ";
570 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
571 -1.0, NewSafety, substep_no);
572 }
573#endif
574 ++substep_no;
575 ++substep_no_p;
576
577 } while ( ( ! found_approximate_intersection )
578 && ( ! there_is_no_intersection )
579 && ( substep_no_p <= param_substeps) ); // UNTIL found or
580 // failed param substep
581 first_section = false;
582
583 if( (!found_approximate_intersection) && (!there_is_no_intersection) )
584 {
585 G4double did_len = std::abs( CurrentA_PointVelocity.GetCurveLength()
586 - SubStart_PointVelocity.GetCurveLength());
587 G4double all_len = std::abs( CurrentB_PointVelocity.GetCurveLength()
588 - SubStart_PointVelocity.GetCurveLength());
589
590 G4double stepLengthAB;
591 G4ThreeVector PointGe;
592
593 // Check if progress is too slow and if it possible to go deeper,
594 // then halve the step if so
595 //
596 if ( ( did_len < fraction_done*all_len )
597 && (depth < max_depth) && (!sub_final_section) )
598 {
599 Second_half=false;
600 ++depth;
601
602 G4double Sub_len = (all_len-did_len)/(2.);
603 G4FieldTrack start = CurrentA_PointVelocity;
604 auto integrDriver =
606 integrDriver->AccurateAdvance(start, Sub_len, GetEpsilonStepFor());
607 *ptrInterMedFT[depth] = start;
608 CurrentB_PointVelocity = *ptrInterMedFT[depth];
609
610 // Adjust 'SubStartPoint' to calculate the 'did_length' in next loop
611 //
612 SubStart_PointVelocity = CurrentA_PointVelocity;
613
614 // Find new trial intersection point needed at start of the loop
615 //
616 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
617 G4ThreeVector SubE_point = CurrentB_PointVelocity.GetPosition();
618
620 G4bool Intersects_AB = IntersectChord(Point_A, SubE_point,
621 NewSafety, fPreviousSafety,
622 fPreviousSftOrigin,stepLengthAB,
623 PointGe);
624 if( Intersects_AB )
625 {
626 last_AF_intersection = Intersects_AB;
627 CurrentE_Point = PointGe;
628 fin_section_depth[depth] = true;
629
630 // Need to recalculate the Exit Normal at the new PointG
631 //
632 G4bool validNormalAB;
633 NormalAtEntry = GetSurfaceNormal( PointGe, validNormalAB );
634 validNormalAtE = validNormalAB;
635 }
636 else
637 {
638 // No intersection found for first part of curve
639 // (CurrentA,InterMedPoint[depth]). Go to the second part
640 //
641 Second_half = true;
642 }
643 } // if did_len
644
645 if( (Second_half)&&(depth!=0) )
646 {
647 // Second part of curve (InterMed[depth],Intermed[depth-1]) )
648 // On the depth-1 level normally we are on the 'second_half'
649
650 Second_half = true;
651
652 // Find new trial intersection point needed at start of the loop
653 //
654 SubStart_PointVelocity = *ptrInterMedFT[depth];
655 CurrentA_PointVelocity = *ptrInterMedFT[depth];
656 CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
657 // Ensure that the new endpoints are not further apart in space
658 // than on the curve due to different errors in the integration
659 //
660 G4double linDistSq, curveDist;
661 linDistSq = ( CurrentB_PointVelocity.GetPosition()
662 - CurrentA_PointVelocity.GetPosition() ).mag2();
663 curveDist = CurrentB_PointVelocity.GetCurveLength()
664 - CurrentA_PointVelocity.GetCurveLength();
665 if( curveDist*curveDist*(1+2*GetEpsilonStepFor() ) < linDistSq )
666 {
667 // Re-integrate to obtain a new B
668 //
669 G4FieldTrack newEndPointFT =
670 ReEstimateEndpoint( CurrentA_PointVelocity,
671 CurrentB_PointVelocity,
672 linDistSq, // to avoid recalculation
673 curveDist );
674 G4FieldTrack oldPointVelB = CurrentB_PointVelocity;
675 CurrentB_PointVelocity = newEndPointFT;
676 if ( depth==1 )
677 {
678 recalculatedEndPoint = true;
679 IntersectedOrRecalculatedFT = newEndPointFT;
680 // So that we can return it, if it is the endpoint!
681 }
682 }
683
684
685 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
686 G4ThreeVector SubE_point = CurrentB_PointVelocity.GetPosition();
688 G4bool Intersects_AB = IntersectChord(Point_A, SubE_point, NewSafety,
690 fPreviousSftOrigin,stepLengthAB, PointGe);
691 if( Intersects_AB )
692 {
693 last_AF_intersection = Intersects_AB;
694 CurrentE_Point = PointGe;
695
696 G4bool validNormalAB;
697 NormalAtEntry = GetSurfaceNormal( PointGe, validNormalAB );
698 validNormalAtE = validNormalAB;
699 }
700
701 depth--;
702 fin_section_depth[depth]=true;
703 }
704 } // if(!found_aproximate_intersection)
705
706 } while ( ( ! found_approximate_intersection )
707 && ( ! there_is_no_intersection )
708 && ( substep_no <= max_substeps) ); // UNTIL found or failed
709
710 if( substep_no > max_no_seen )
711 {
712 max_no_seen = substep_no;
713#ifdef G4DEBUG_LOCATE_INTERSECTION
714 if( max_no_seen > warn_substeps )
715 {
716 trigger_substepno_print = max_no_seen-20; // Want to see last 20 steps
717 }
718#endif
719 }
720
721 if( ( substep_no >= max_substeps)
722 && !there_is_no_intersection
723 && !found_approximate_intersection )
724 {
725 G4cout << "ERROR - G4BrentLocator::EstimateIntersectionPoint()" << G4endl
726 << " Start and end-point of requested Step:" << G4endl;
727 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
728 -1.0, NewSafety, 0);
729 G4cout << " Start and end-point of current Sub-Step:" << G4endl;
730 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
731 -1.0, NewSafety, substep_no-1);
732 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
733 -1.0, NewSafety, substep_no);
734 std::ostringstream message;
735 message << "Too many substeps!" << G4endl
736 << " Convergence is requiring too many substeps: "
737 << substep_no << G4endl
738 << " Abandoning effort to intersect. " << G4endl
739 << " Found intersection = "
740 << found_approximate_intersection << G4endl
741 << " Intersection exists = "
742 << !there_is_no_intersection << G4endl;
743 oldprc = G4cout.precision( 10 );
744 G4double done_len = CurrentA_PointVelocity.GetCurveLength();
745 G4double full_len = CurveEndPointVelocity.GetCurveLength();
746 message << " Undertaken only length: " << done_len
747 << " out of " << full_len << " required." << G4endl
748 << " Remaining length = " << full_len - done_len;
749 G4cout.precision( oldprc );
750
751 G4Exception("G4BrentLocator::EstimateIntersectionPoint()",
752 "GeomNav0003", FatalException, message);
753 }
754 else if( substep_no >= warn_substeps )
755 {
756 oldprc= G4cout.precision( 10 );
757 std::ostringstream message;
758 message << "Many substeps while trying to locate intersection."
759 << G4endl
760 << " Undertaken length: "
761 << CurrentB_PointVelocity.GetCurveLength()
762 << " - Needed: " << substep_no << " substeps." << G4endl
763 << " Warning level = " << warn_substeps
764 << " and maximum substeps = " << max_substeps;
765 G4Exception("G4BrentLocator::EstimateIntersectionPoint()",
766 "GeomNav1002", JustWarning, message);
767 G4cout.precision( oldprc );
768 }
769 return !there_is_no_intersection; // Success or failure
770}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
#define fPreviousSftOrigin
#define fPreviousSafety
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
static const G4int max_depth
G4BrentLocator(G4Navigator *theNavigator)
G4FieldTrack * ptrInterMedFT[max_depth+1]
G4bool EstimateIntersectionPoint(const G4FieldTrack &curveStartPointTangent, const G4FieldTrack &curveEndPointTangent, const G4ThreeVector &trialPoint, G4FieldTrack &intersectPointTangent, G4bool &recalculatedEndPoint, G4double &fPreviousSafety, G4ThreeVector &fPreviousSftOrigin)
G4FieldTrack ApproxCurvePointV(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4ThreeVector &currentEPoint, G4double epsStep)
G4FieldTrack ApproxCurvePointS(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4FieldTrack &ApproxCurveV, const G4ThreeVector &currentEPoint, const G4ThreeVector &currentFPoint, const G4ThreeVector &PointG, G4bool first, G4double epsStep)
G4VIntegrationDriver * GetIntegrationDriver()
const G4ThreeVector & GetMomentumDir() const
G4double GetCurveLength() const
G4ThreeVector GetMomentumDirection() const
G4ThreeVector GetPosition() const
void SetPosition(G4ThreeVector nPos)
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
Definition: G4Navigator.cc:614
virtual G4bool AccurateAdvance(G4FieldTrack &track, G4double hstep, G4double eps, G4double hinitial=0)=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)
G4double GetEpsilonStepFor()
G4FieldTrack ReEstimateEndpoint(const G4FieldTrack &CurrentStateA, const G4FieldTrack &EstimtdEndStateB, G4double linearDistSq, G4double curveDist)
G4bool GetAdjustementOfFoundIntersection()
G4double GetDeltaIntersectionFor()
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)
static constexpr double mm
Definition: SystemOfUnits.h:96
T sqr(const T &x)
Definition: templates.hh:128
#define G4ThreadLocal
Definition: tls.hh:77