If such an intersection exists, this method calculates the intersection point of the true path of the particle with the surface of the current volume (or of one of its daughters). Should use lateral displacement as measure of convergence.
100{
101
102
103 G4bool found_approximate_intersection =
false;
104 G4bool there_is_no_intersection =
false;
105
106 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity;
107 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity;
109 G4bool validNormalAtE =
false;
111
112 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity);
114 G4bool last_AF_intersection =
false;
115
116
117
118 G4bool first_section =
true;
119 recalculatedEndPoint = false;
120
121 G4bool restoredFullEndpoint =
false;
122
124 G4int substep_no = 0;
125
126
127
128 const G4int max_substeps= 10000;
129 const G4int warn_substeps= 1000;
130
131
132
134
135
136
138
139
140
141
142
143
144
145
146
147
148
149 const G4int param_substeps = 50;
150
152
153 G4bool Second_half =
false;
154
156
157
158
159
160
161
162
164
165#ifdef G4DEBUG_FIELD
167 G4ThreeVector StartPosition = CurveStartPointVelocity.GetPosition();
168 if( (TrialPoint - StartPosition).mag() < tolerance * CLHEP::mm )
169 {
170 G4Exception(
"G4BrentLocator::EstimateIntersectionPoint()",
172 "Intersection point F is exactly at start point A." );
173 }
174#endif
175
176
177
178
179
180 *ptrInterMedFT[0] = CurveEndPointVelocity;
181 for (auto idepth=1; idepth<max_depth+1; ++idepth )
182 {
183 *ptrInterMedFT[idepth] = CurveStartPointVelocity;
184 }
185
186
187 G4bool fin_section_depth[max_depth];
188 for (bool & idepth : fin_section_depth)
189 {
190 idepth = true;
191 }
192
193
194
195 G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
196
197 do
198 {
199 G4int substep_no_p = 0;
200 G4bool sub_final_section =
false;
201
202 SubStart_PointVelocity = CurrentA_PointVelocity;
203
204 do
205 {
208
209
210
211
212 if(substep_no_p==0)
213 {
216 CurrentB_PointVelocity,
217 CurrentE_Point,
219
220 }
221#ifdef G4DEBUG_FIELD
222 if( ApproxIntersecPointV.GetCurveLength() >
224 {
225 G4Exception(
"G4BrentLocator::EstimateIntersectionPoint()",
227 "Intermediate F point is past end B point" );
228 }
229#endif
230
231 G4ThreeVector CurrentF_Point = ApproxIntersecPointV.GetPosition();
232
233
234
235
236 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
237 G4ThreeVector NewMomentumDir = ApproxIntersecPointV.GetMomentumDir();
238 G4double MomDir_dot_Norm = NewMomentumDir.
dot( NormalAtEntry ) ;
239
240#ifdef G4DEBUG_FIELD
242
244 ChordEF_Vector, NewMomentumDir, NormalAtEntry, validNormalAtE );
245#endif
246
248 adequate_angle = ( MomDir_dot_Norm >= 0.0 )
249 || (! validNormalAtE );
253 {
254 found_approximate_intersection = true;
255
256
257
258 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
259 IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
260
262 {
263
264
266 G4ThreeVector MomentumDir=ApproxIntersecPointV.GetMomentumDirection();
268 CurrentE_Point, CurrentF_Point, MomentumDir,
269 last_AF_intersection, IP, NewSafety,
271 if ( goodCorrection )
272 {
273 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
274 IntersectedOrRecalculatedFT.SetPosition(IP);
275 }
276 }
277
278
279
280
281
282
283
284 }
285 else
286 {
287
288
289
290
291
293
296 G4bool usedNavigatorAF =
false;
300 stepLengthAF,
301 PointG,
302 &usedNavigatorAF);
303 last_AF_intersection = Intersects_AF;
304 if( Intersects_AF )
305 {
306
307
308
309
310
311
312 G4FieldTrack EndPoint = ApproxIntersecPointV;
314 CurrentA_PointVelocity, CurrentB_PointVelocity,
315 EndPoint,CurrentE_Point, CurrentF_Point,PointG,
317 CurrentB_PointVelocity = EndPoint;
318 CurrentE_Point = PointG;
319
320
321
322
323
326 validNormalAtE = validNormalLast;
327
328
329
330
331 fin_section_depth[depth] = false;
332#ifdef G4VERBOSE
334 {
335 G4cout <<
"G4PiF::LI> Investigating intermediate point"
336 << " at s=" << ApproxIntersecPointV.GetCurveLength()
337 << " on way to full s="
338 << CurveEndPointVelocity.GetCurveLength() <<
G4endl;
339 }
340#endif
341 }
342 else
343 {
344
345
346
347
349
352 G4bool usedNavigatorFB =
false;
353
354
355
356
360 stepLengthFB,
361 PointH,
362 &usedNavigatorFB);
363 if( Intersects_FB )
364 {
365
366
367
368
369
370
371
372
373
374
375
376
377 G4FieldTrack InterMed = ApproxIntersecPointV;
379 CurrentA_PointVelocity,CurrentB_PointVelocity,
380 InterMed,CurrentE_Point,CurrentF_Point,PointH,
382 CurrentA_PointVelocity = InterMed;
383 CurrentE_Point = PointH;
384
385
386
389 validNormalAtE = validNormalLast;
390 }
391 else
392 {
393
394
395 if( fin_section_depth[depth] )
396 {
397
398
399
400
401
402
403
404
405 if( ((Second_half)&&(depth==0)) || (first_section) )
406 {
407 there_is_no_intersection = true;
408 }
409 else
410 {
411
412
413
414 substep_no_p = param_substeps+2;
415
416
417
418
419 Second_half = true;
420 sub_final_section = true;
421 }
422 }
423 else
424 {
425 if( depth==0 )
426 {
427
428
429 CurrentA_PointVelocity = CurrentB_PointVelocity;
430 CurrentB_PointVelocity = CurveEndPointVelocity;
431 SubStart_PointVelocity = CurrentA_PointVelocity;
434 CurrentB_PointVelocity,
435 CurrentE_Point,
437
438 restoredFullEndpoint = true;
439 ++restartB;
440 }
441 else
442 {
443
444
445 CurrentA_PointVelocity = CurrentB_PointVelocity;
446 CurrentB_PointVelocity = *ptrInterMedFT[depth];
447 SubStart_PointVelocity = CurrentA_PointVelocity;
450 CurrentB_PointVelocity,
451 CurrentE_Point,
453 restoredFullEndpoint = true;
454 ++restartB;
455 }
456 }
457 }
458 }
459
460
461
462
468
469
470
472 {
473
474
475 G4FieldTrack newEndPointFT=
477 CurrentB_PointVelocity,
478 linDistSq,
479 curveDist );
480 G4FieldTrack oldPointVelB = CurrentB_PointVelocity;
481 CurrentB_PointVelocity = newEndPointFT;
482
483 if ( (fin_section_depth[depth])
484 &&( first_section || ((Second_half)&&(depth==0)) ) )
485 {
486 recalculatedEndPoint = true;
487 IntersectedOrRecalculatedFT = newEndPointFT;
488
489 }
490 }
491 if( curveDist < 0.0 )
492 {
494 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
495 -1.0, NewSafety, substep_no );
496 std::ostringstream message;
497 message <<
"Error in advancing propagation." <<
G4endl
498 <<
" Error in advancing propagation." <<
G4endl
499 << " Point A (start) is " << CurrentA_PointVelocity
501 << " Point B (end) is " << CurrentB_PointVelocity
503 <<
" Curve distance is " << curveDist <<
G4endl
505 << "The final curve point is not further along"
506 <<
" than the original!" <<
G4endl;
507
508 if( recalculatedEndPoint )
509 {
510 message << "Recalculation of EndPoint was called with fEpsStep= "
512 }
513 oldprc =
G4cerr.precision(20);
514 message << " Point A (Curve start) is " << CurveStartPointVelocity
516 << " Point B (Curve end) is " << CurveEndPointVelocity
518 << " Point A (Current start) is " << CurrentA_PointVelocity
520 << " Point B (Current end) is " << CurrentB_PointVelocity
522 << " Point S (Sub start) is " << SubStart_PointVelocity
524 << " Point E (Trial Point) is " << CurrentE_Point
526 << " Old Point F(Intersection) is " << CurrentF_Point
528 << " New Point F(Intersection) is " << ApproxIntersecPointV
530 << " LocateIntersection parameters are : Substep no= "
532 << " Substep depth no= "<< substep_no_p << " Depth= "
534 << " Restarted no= "<< restartB << " Epsilon= "
537 G4cerr.precision( oldprc );
538
539 G4Exception(
"G4BrentLocator::EstimateIntersectionPoint()",
541 }
542
543 if( restoredFullEndpoint )
544 {
545 fin_section_depth[depth] = restoredFullEndpoint;
546 restoredFullEndpoint = false;
547 }
548 }
549
550
551#ifdef G4DEBUG_LOCATE_INTERSECTION
552 G4int trigger_substepno_print= warn_substeps - 20 ;
553
554 if( substep_no >= trigger_substepno_print )
555 {
556 G4cout <<
"Difficulty in converging in "
557 << "G4BrentLocator::EstimateIntersectionPoint()"
559 <<
" Substep no = " << substep_no <<
G4endl;
560 if( substep_no == trigger_substepno_print )
561 {
562 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
563 -1.0, NewSafety, 0);
564 }
565 G4cout <<
" State of point A: ";
566 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
567 -1.0, NewSafety, substep_no-1, 0);
568 G4cout <<
" State of point B: ";
569 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
570 -1.0, NewSafety, substep_no);
571 }
572#endif
573 ++substep_no;
574 ++substep_no_p;
575
576 } while ( ( ! found_approximate_intersection )
577 && ( ! there_is_no_intersection )
578 && ( substep_no_p <= param_substeps) );
579
580 first_section = false;
581
582 if( (!found_approximate_intersection) && (!there_is_no_intersection) )
583 {
588
591
592
593
594
595 if ( ( did_len < fraction_done*all_len )
596 && (depth < max_depth) && (!sub_final_section) )
597 {
598 Second_half=false;
599 ++depth;
600
601 G4double Sub_len = (all_len-did_len)/(2.);
602 G4FieldTrack start = CurrentA_PointVelocity;
603 auto integrDriver =
606 *ptrInterMedFT[depth] = start;
607 CurrentB_PointVelocity = *ptrInterMedFT[depth];
608
609
610
611 SubStart_PointVelocity = CurrentA_PointVelocity;
612
613
614
617
622 PointGe);
623 if( Intersects_AB )
624 {
625 last_AF_intersection = Intersects_AB;
626 CurrentE_Point = PointGe;
627 fin_section_depth[depth] = true;
628
629
630
633 validNormalAtE = validNormalAB;
634 }
635 else
636 {
637
638
639
640 Second_half = true;
641 }
642 }
643
644 if( (Second_half)&&(depth!=0) )
645 {
646
647
648
649 Second_half = true;
650
651
652
653 SubStart_PointVelocity = *ptrInterMedFT[depth];
654 CurrentA_PointVelocity = *ptrInterMedFT[depth];
655 CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
656
657
658
665 {
666
667
668 G4FieldTrack newEndPointFT =
670 CurrentB_PointVelocity,
671 linDistSq,
672 curveDist );
673 G4FieldTrack oldPointVelB = CurrentB_PointVelocity;
674 CurrentB_PointVelocity = newEndPointFT;
675 if ( depth==1 )
676 {
677 recalculatedEndPoint = true;
678 IntersectedOrRecalculatedFT = newEndPointFT;
679
680 }
681 }
682
683
690 if( Intersects_AB )
691 {
692 last_AF_intersection = Intersects_AB;
693 CurrentE_Point = PointGe;
694
697 validNormalAtE = validNormalAB;
698 }
699
700 depth--;
701 fin_section_depth[depth]=true;
702 }
703 }
704
705 } while ( ( ! found_approximate_intersection )
706 && ( ! there_is_no_intersection )
707 && ( substep_no <= max_substeps) );
708
709 if( substep_no > max_no_seen )
710 {
711 max_no_seen = substep_no;
712#ifdef G4DEBUG_LOCATE_INTERSECTION
713 if( max_no_seen > warn_substeps )
714 {
715 trigger_substepno_print = max_no_seen-20;
716 }
717#endif
718 }
719
720 if( ( substep_no >= max_substeps)
721 && !there_is_no_intersection
722 && !found_approximate_intersection )
723 {
724 G4cout <<
"ERROR - G4BrentLocator::EstimateIntersectionPoint()" <<
G4endl
725 <<
" Start and end-point of requested Step:" <<
G4endl;
726 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
727 -1.0, NewSafety, 0);
728 G4cout <<
" Start and end-point of current Sub-Step:" <<
G4endl;
729 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
730 -1.0, NewSafety, substep_no-1);
731 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
732 -1.0, NewSafety, substep_no);
733 std::ostringstream message;
734 message <<
"Too many substeps!" <<
G4endl
735 << " Convergence is requiring too many substeps: "
737 <<
" Abandoning effort to intersect. " <<
G4endl
738 << " Found intersection = "
739 << found_approximate_intersection <<
G4endl
740 << " Intersection exists = "
741 << !there_is_no_intersection <<
G4endl;
742 oldprc =
G4cout.precision( 10 );
744 G4double full_len = CurveEndPointVelocity.GetCurveLength();
745 message << " Undertaken only length: " << done_len
746 <<
" out of " << full_len <<
" required." <<
G4endl
747 << " Remaining length = " << full_len - done_len;
748 G4cout.precision( oldprc );
749
750 G4Exception(
"G4BrentLocator::EstimateIntersectionPoint()",
752 }
753 else if( substep_no >= warn_substeps )
754 {
755 oldprc =
G4cout.precision( 10 );
756 std::ostringstream message;
757 message << "Many substeps while trying to locate intersection."
759 << " Undertaken length: "
761 <<
" - Needed: " << substep_no <<
" substeps." <<
G4endl
762 << " Warning level = " << warn_substeps
763 << " and maximum substeps = " << max_substeps;
764 G4Exception(
"G4BrentLocator::EstimateIntersectionPoint()",
766 G4cout.precision( oldprc );
767 }
768 return !there_is_no_intersection;
769}
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define fPreviousSftOrigin
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
double dot(const Hep3Vector &) const
G4FieldTrack ApproxCurvePointV(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4ThreeVector ¤tEPoint, G4double epsStep)
G4FieldTrack ApproxCurvePointS(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4FieldTrack &ApproxCurveV, const G4ThreeVector ¤tEPoint, const G4ThreeVector ¤tFPoint, const G4ThreeVector &PointG, G4bool first, G4double epsStep)
G4VIntegrationDriver * GetIntegrationDriver()
G4double GetCurveLength() const
G4ThreeVector GetPosition() const
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
virtual G4bool AccurateAdvance(G4FieldTrack &track, G4double hstep, G4double eps, G4double hinitial=0)=0
G4double fiDeltaIntersection
G4Navigator * GetNavigatorFor()
G4ChordFinder * GetChordFinderFor()
G4ThreeVector GetSurfaceNormal(const G4ThreeVector &CurrentInt_Point, G4bool &validNormal)
static void printStatus(const G4FieldTrack &startFT, const G4FieldTrack ¤tFT, G4double requestStep, G4double safety, G4int stepNum, std::ostream &oss, G4int verboseLevel)
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()
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)