120 G4bool& recalculatedEndPoint,
125 const char* MethodName=
"G4MultiLevelLocator::EstimateIntersectionPoint()";
127 G4bool found_approximate_intersection =
false;
128 G4bool there_is_no_intersection =
false;
130 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity;
131 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity;
133 G4bool validNormalAtE =
false;
136 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity);
137 G4bool validIntersectP=
true;
139 G4bool last_AF_intersection =
false;
144 G4bool first_section =
true;
145 recalculatedEndPoint =
false;
146 G4bool restoredFullEndpoint =
false;
148 unsigned int substep_no = 0;
154 unsigned int trigger_substepno_print = 0;
155 const G4double tolerance = 1.0e-8 * CLHEP::mm;
156 unsigned int biggest_depth = 0;
163 endChangeB(
"EndPointB"), recApproxPoint(
"ApproxPoint"),
164 pointH_logger(
"Trial points 'E': position, normal");
165 unsigned int eventCount = 0;
172 recApproxPoint.clear();
173 pointH_logger.clear();
178 eventCount, CurrentA_PointVelocity );
180 eventCount, CurrentB_PointVelocity );
193 const G4int param_substeps = 5;
197 G4bool Second_half =
false;
205 unsigned int depth = 0;
213 substep_no, eventCount,
216 #if (G4DEBUG_FIELD>1)
218 if( (TrialPoint - StartPosition).mag2() <
sqr(tolerance))
221 tolerance, fNumCalls);
230 *ptrInterMedFT[0] = CurveEndPointVelocity;
231 for (
auto idepth=1; idepth<max_depth+1; ++idepth )
233 *ptrInterMedFT[idepth] = CurveStartPointVelocity;
239 for (
bool & idepth : fin_section_depth)
245 G4FieldTrack SubStart_PointVelocity = CurveStartPointVelocity;
249 unsigned int substep_no_p = 0;
250 G4bool sub_final_section =
false;
252 SubStart_PointVelocity = CurrentA_PointVelocity;
263 G4double distAB = (Point_B - Point_A).mag();
266 G4cerr <<
"ERROR> (Start) Point A coincides with or has gone past (end) point B"
267 <<
"MLL: iters = " << substep_no <<
G4endl;
269 G4cerr <<
" Difference = " << distAB - curv_lenAB
270 <<
" exceeds limit of relative dist (10*epsilon)= " << 10*
fiEpsilonStep
273 G4cerr <<
" Len A, B = " << lenA <<
" " << lenB <<
G4endl
274 <<
" Position A: " << Point_A <<
G4endl
275 <<
" Position B: " << Point_B <<
G4endl;
285 if( !validIntersectP )
288 errmsg <<
"Assertion FAILURE - invalid (stale) Interection point. Substep: "
289 << substep_no <<
" call: " << fNumCalls <<
G4endl;
294 G4Exception(
"G4MultiLevelLocator::EstimateIntersectionPoint",
"GeomNav0004",
303 CurrentB_PointVelocity,
310 substep_no, eventCount, ApproxIntersecPointV ) );
312 G4double checkVsEnd= lenB - lenIntsc;
314 if( lenIntsc > lenB )
316 std::ostringstream errmsg;
317 errmsg.precision(17);
319 G4double ratioTol = std::fabs(ratio) / tolerance;
320 errmsg <<
"Intermediate F point is past end B point" <<
G4endl
321 <<
" l( intersection ) = " << lenIntsc <<
G4endl
322 <<
" l( endpoint ) = " << lenB <<
G4endl;
324 errmsg <<
" l_end - l_inters = " << checkVsEnd <<
G4endl
325 <<
" / l_end = " << ratio <<
G4endl
326 <<
" ratio / tolerance = " << ratioTol <<
G4endl;
339 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
342 G4double MomDir_dot_Norm = NewMomentumDir.
dot( NormalAtEntry );
350 MomDir_dot_ABchord = (1.0 / ABchord_length)
351 * NewMomentumDir.
dot( ChordAB );
353 ChordEF_Vector, NewMomentumDir, NormalAtEntry, validNormalAtE );
354 G4cout <<
" dot( MomentumDir, ABchord_unit ) = "
355 << MomDir_dot_ABchord <<
G4endl;
359 ( MomDir_dot_Norm >= 0.0 )
360 || (! validNormalAtE );
365 found_approximate_intersection =
true;
369 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
370 IntersectedOrRecalculatedFT.
SetPosition( CurrentE_Point );
379 CurrentE_Point, CurrentF_Point, MomentumDir,
380 last_AF_intersection, IP, NewSafety,
381 previousSafety, previousSftOrigin );
382 if ( goodCorrection )
384 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
406 G4bool Intersects_FB =
false;
408 NewSafety, previousSafety,
412 last_AF_intersection = Intersects_AF;
417 CurrentB_PointVelocity = ApproxIntersecPointV;
418 CurrentE_Point = PointG;
420 validIntersectP =
true;
424 validNormalAtE = validNormalLast;
428 fin_section_depth[depth] =
false;
433 endChangeB.push_back(
435 substep_no, eventCount, CurrentB_PointVelocity) );
440 G4cout <<
"G4PiF::LI> Investigating intermediate point"
442 <<
" on way to full s="
462 NewSafety, previousSafety,
480 CurrentA_PointVelocity = ApproxIntersecPointV;
481 CurrentE_Point = PointH;
483 validIntersectP =
true;
487 validNormalAtE = validNormalH;
492 endChangeA.push_back(
494 substep_no, eventCount, CurrentA_PointVelocity) );
500 substep_no, eventCount, intersectH_pn );
505 validIntersectP =
false;
506 if( fin_section_depth[depth] )
516 if( ((Second_half)&&(depth==0)) || (first_section) )
518 there_is_no_intersection =
true;
524 substep_no_p = param_substeps+2;
529 sub_final_section =
true;
534 CurrentA_PointVelocity = CurrentB_PointVelocity;
535 CurrentB_PointVelocity = (depth==0) ? CurveEndPointVelocity
536 : *ptrInterMedFT[depth] ;
537 SubStart_PointVelocity = CurrentA_PointVelocity;
538 restoredFullEndpoint =
true;
540 validIntersectP =
false;
545 endChangeA.push_back(
548 substep_no, eventCount, CurrentA_PointVelocity) );
549 endChangeB.push_back(
552 substep_no, eventCount, CurrentB_PointVelocity) );
558 G4int errorEndPt = 0;
560 G4bool recalculatedB=
false;
561 if( driverReIntegrates )
565 CurrentB_PointVelocity,
570 CurrentB_PointVelocity = RevisedB_FT;
577 if ( (fin_section_depth[depth])
578 &&( first_section || ((Second_half)&&(depth==0)) ) )
580 recalculatedEndPoint =
true;
581 IntersectedOrRecalculatedFT = RevisedB_FT;
593 endChangeB.push_back(
595 substep_no, eventCount, RevisedB_FT ) );
609 std::ostringstream errmsg;
612 CurveStartPointVelocity, CurveEndPointVelocity,
614 CurrentA_PointVelocity, CurrentB_PointVelocity,
615 SubStart_PointVelocity, CurrentE_Point,
616 ApproxIntersecPointV, substep_no, substep_no_p, depth);
623 errmsg <<
G4endl <<
" * Location: " << MethodName
624 <<
"- After EndIf(Intersects_AF)" <<
G4endl;
625 errmsg <<
" * Bool flags: Recalculated = " << recalculatedB
626 <<
" Intersects_AF = " << Intersects_AF
627 <<
" Intersects_FB = " << Intersects_FB <<
G4endl;
628 errmsg <<
" * Number of calls to MLL:EIP= " << fNumCalls <<
G4endl;
631 if( restoredFullEndpoint )
633 fin_section_depth[depth] = restoredFullEndpoint;
634 restoredFullEndpoint =
false;
640 if( trigger_substepno_print == 0)
642 trigger_substepno_print= fWarnSteps - 20;
645 if( substep_no >= trigger_substepno_print )
647 G4cout <<
"Difficulty in converging in " << MethodName
648 <<
" Substep no = " << substep_no <<
G4endl;
649 if( substep_no == trigger_substepno_print )
652 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
653 -1.0, NewSafety, 0 );
657 G4cout <<
" ** For more information enable 'check mode' in G4MultiLevelLocator "
658 <<
"-- (it saves and can output change records) " <<
G4endl;
662 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
663 -1.0, NewSafety, substep_no-1 );
665 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
666 -1.0, NewSafety, substep_no );
672 }
while ( ( ! found_approximate_intersection )
673 && ( ! there_is_no_intersection )
675 && ( substep_no_p <= param_substeps) );
678 if( (!found_approximate_intersection) && (!there_is_no_intersection) )
690 if( (did_len < fraction_done*all_len)
691 && (depth<
max_depth) && (!sub_final_section) )
695 biggest_depth = std::max(depth, biggest_depth);
700 first_section =
false;
702 G4double Sub_len = (all_len-did_len)/(2.);
705 integrDriver->AccurateAdvance(midPoint, Sub_len,
fiEpsilonStep);
708 if( fullAdvance ) { ++fNumAdvanceFull; }
713 const G4double adequateFraction = (1.0-CLHEP::perThousand);
714 G4bool goodAdvance = (lenAchieved >= adequateFraction * Sub_len);
715 if ( goodAdvance ) { ++fNumAdvanceGood; }
720 G4cout <<
"MLL> AdvanceChordLimited not full at depth=" << depth
721 <<
" total length achieved = " << lenAchieved <<
" of "
722 << Sub_len <<
" fraction= ";
723 if (Sub_len != 0.0 ) {
G4cout << lenAchieved / Sub_len; }
724 else {
G4cout <<
"DivByZero"; }
725 G4cout <<
" Good-enough fraction = " << adequateFraction;
726 G4cout <<
" Number of call to mll = " << fNumCalls
727 <<
" iteration " << substep_no
728 <<
" inner = " << substep_no_p <<
G4endl;
730 G4cout <<
" State at start is = " << CurrentA_PointVelocity
732 <<
" at end (midpoint)= " << midPoint <<
G4endl;
736 ReportFieldValue( CurrentA_PointVelocity,
"start", equation );
737 ReportFieldValue( midPoint,
"midPoint", equation );
738 G4cout <<
" Original Start = "
739 << CurveStartPointVelocity <<
G4endl;
740 G4cout <<
" Original End = "
741 << CurveEndPointVelocity <<
G4endl;
742 G4cout <<
" Original TrialPoint = "
744 G4cout <<
" (this is STRICT mode) "
745 <<
" num Splits= " << numSplits;
750 *ptrInterMedFT[depth] = midPoint;
751 CurrentB_PointVelocity = midPoint;
756 endChangeB.push_back(
758 substep_no, eventCount, midPoint) );
763 SubStart_PointVelocity = CurrentA_PointVelocity;
773 NewSafety, previousSafety,
774 previousSftOrigin, distAB,
778 last_AF_intersection = Intersects_AB;
779 CurrentE_Point = PointGe;
780 fin_section_depth[depth] =
true;
782 validIntersectP =
true;
786 validNormalAtE = validNormalAB;
795 validIntersectP=
false;
799 G4bool unfinished = Second_half;
800 while ( unfinished && (depth>0) )
807 SubStart_PointVelocity = *ptrInterMedFT[depth];
808 CurrentA_PointVelocity = *ptrInterMedFT[depth];
809 CurrentB_PointVelocity = *ptrInterMedFT[depth-1];
815 substep_no, eventCount, CurrentA_PointVelocity);
816 endChangeA.push_back( chngPop_a );
818 substep_no, eventCount, CurrentB_PointVelocity);
819 endChangeB.push_back( chngPop_b );
825 G4int errorEndPt = -1;
826 G4bool recalculatedB=
false;
827 if( driverReIntegrates )
832 G4FieldTrack RevisedEndPointFT = CurrentB_PointVelocity;
835 CurrentB_PointVelocity,
840 CurrentB_PointVelocity = RevisedEndPointFT;
844 recalculatedEndPoint =
true;
845 IntersectedOrRecalculatedFT = RevisedEndPointFT;
861 endChangeB.push_back(
863 substep_no, eventCount, RevisedEndPointFT));
868 std::ostringstream errmsg;
870 CurveStartPointVelocity, CurveEndPointVelocity,
872 CurrentA_PointVelocity, CurrentB_PointVelocity,
873 SubStart_PointVelocity, CurrentE_Point,
874 ApproxIntersecPointV, substep_no, substep_no_p, depth);
875 errmsg <<
" * Location: " << MethodName <<
"- Second-Half" <<
G4endl;
876 errmsg <<
" * Recalculated = " << recalculatedB <<
G4endl;
886 previousSftOrigin, distAB,
890 last_AF_intersection = Intersects_AB;
891 CurrentE_Point = PointGi;
893 validIntersectP =
true;
898 validIntersectP =
false;
901 there_is_no_intersection =
true;
905 fin_section_depth[depth] =
true;
906 unfinished = !validIntersectP;
909 if( ! ( validIntersectP || there_is_no_intersection ) )
912 G4cout <<
"MLL - WARNING Potential FAILURE: Conditions not met!"
914 <<
" Depth = " << depth <<
G4endl
915 <<
" Num Substeps= " << substep_no <<
G4endl;
916 G4cout <<
" Found intersection= " << found_approximate_intersection
920 CurveStartPointVelocity, CurveEndPointVelocity,
921 substep_no, CurrentA_PointVelocity,
922 CurrentB_PointVelocity,
929 assert( validIntersectP || there_is_no_intersection
930 || found_approximate_intersection);
932 }
while ( ( ! found_approximate_intersection )
933 && ( ! there_is_no_intersection )
934 && ( substep_no <= fMaxSteps) );
936 if( substep_no > max_no_seen )
938 max_no_seen = substep_no;
940 if( max_no_seen > fWarnSteps )
942 trigger_substepno_print = max_no_seen-20;
947 if( !there_is_no_intersection && !found_approximate_intersection )
949 if( substep_no >= fMaxSteps)
953 recalculatedEndPoint =
true;
954 IntersectedOrRecalculatedFT = CurrentA_PointVelocity;
955 found_approximate_intersection =
false;
957 std::ostringstream message;
959 message <<
"Convergence is requiring too many substeps: "
960 << substep_no <<
" ( limit = "<< fMaxSteps <<
")"
962 <<
" Abandoning effort to intersect. " <<
G4endl <<
G4endl;
963 message <<
" Number of calls to MLL: " << fNumCalls;
964 message <<
" iteration = " << substep_no <<
G4endl <<
G4endl;
966 message.precision( 12 );
969 message <<
" Undertaken only length: " << done_len
970 <<
" out of " << full_len <<
" required." <<
G4endl
971 <<
" Remaining length = " << full_len - done_len;
973 message <<
" Start and end-point of requested Step:" <<
G4endl;
974 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
975 -1.0, NewSafety, 0, message, -1 );
976 message <<
" Start and end-point of current Sub-Step:" <<
G4endl;
977 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
978 -1.0, NewSafety, substep_no-1, message, -1 );
979 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
980 -1.0, NewSafety, substep_no, message, -1 );
984 else if( substep_no >= fWarnSteps)
986 std::ostringstream message;
987 message <<
"Many substeps while trying to locate intersection."
989 <<
" Undertaken length: "
991 <<
" - Needed: " << substep_no <<
" substeps." <<
G4endl
992 <<
" Warning number = " << fWarnSteps
993 <<
" and maximum substeps = " << fMaxSteps;
998 return (!there_is_no_intersection) && found_approximate_intersection;