Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // class G4BrentLocator implementation 27 // 28 // 27.10.08 - Tatiana Nikitina. 29 // 04.10.11 - John Apostolakis, revised conver 30 // ------------------------------------------- 31 32 #include <iomanip> 33 34 #include "G4BrentLocator.hh" 35 #include "G4ios.hh" 36 37 G4BrentLocator::G4BrentLocator(G4Navigator *th 38 : G4VIntersectionLocator(theNavigator) 39 { 40 // In case of too slow progress in finding I 41 // intermediates Points on the Track must be 42 // Initialise the array of Pointers [max_dep 43 44 G4ThreeVector zeroV(0.0,0.0,0.0); 45 for (auto & idepth : ptrInterMedFT) 46 { 47 idepth = new G4FieldTrack( zeroV, zeroV, 0 48 } 49 } 50 51 G4BrentLocator::~G4BrentLocator() 52 { 53 for (auto & idepth : ptrInterMedFT) 54 { 55 delete idepth; 56 } 57 } 58 59 // ------------------------------------------- 60 // G4bool G4PropagatorInField::LocateIntersect 61 // const G4FieldTrack& CurveStart 62 // const G4FieldTrack& CurveEndPo 63 // const G4ThreeVector& TrialPoint 64 // G4FieldTrack& Intersecte 65 // G4bool& recalculat 66 // ------------------------------------------- 67 // 68 // Function that returns the intersection of t 69 // of the current volume (either the external 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 76 // 77 // E is the first point of intersection of 78 // a volume other than A (on the surface 79 // 80 // Convention of Use : 81 // i) If it returns "true", then Intersect 82 // to the approximate intersection poin 83 // ii) If it returns "false", no intersecti 84 // The validity of IntersectedOrRecalcu 85 // a) if latter is false, then Intersec 86 // b) if latter is true, then Intersec 87 // the new endpoint, due to a re-int 88 // ------------------------------------------- 89 // NOTE: implementation taken from G4Propagato 90 // New second order locator is added 91 // 92 G4bool G4BrentLocator::EstimateIntersectionPoi 93 const G4FieldTrack& CurveStart 94 const G4FieldTrack& CurveEndPo 95 const G4ThreeVector& TrialPoint 96 G4FieldTrack& Intersecte 97 G4bool& recalculat 98 G4double& fPreviousS 99 G4ThreeVector& fPreviousS 100 101 { 102 // Find Intersection Point ( A, B, E ) of t 103 104 G4bool found_approximate_intersection = fals 105 G4bool there_is_no_intersection = fals 106 107 G4FieldTrack CurrentA_PointVelocity = Curve 108 G4FieldTrack CurrentB_PointVelocity = Curve 109 G4ThreeVector CurrentE_Point = TrialPoint; 110 G4bool validNormalAtE = false; 111 G4ThreeVector NormalAtEntry; 112 113 G4FieldTrack ApproxIntersecPointV(CurveEndP 114 G4double NewSafety = 0.0; 115 G4bool last_AF_intersection = false; 116 117 // G4bool final_section= true; // Shows whe 118 // (i.e. B=f 119 G4bool first_section = true; 120 recalculatedEndPoint = false; 121 122 G4bool restoredFullEndpoint = false; 123 124 G4long oldprc; // cout, cerr precision 125 G4int substep_no = 0; 126 127 // Limits for substep number 128 // 129 const G4int max_substeps= 10000; // Test 130 const G4int warn_substeps= 1000; // 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 fo 142 // Process is defined too slow if after N=p 143 // path, it will be only 'fraction_done' of 144 // In this case the remaining length is div 145 // the loop is restarted for each half. 146 // If progress is still too slow, the divis 147 // until 'max_depth'. 148 //------------------------------------------ 149 150 const G4int param_substeps = 50; // Test val 151 // of subst 152 const G4double fraction_done = 0.3; 153 154 G4bool Second_half = false; // First hal 155 156 NormalAtEntry = GetSurfaceNormal(CurrentE_Po 157 158 // We need to know this for the 'final_secti 159 // real 'final_section' or first half 'final 160 // In algorithm it is considered that the 'S 161 // and it becomes false only if we are in th 162 // depthness or if we are in the first secti 163 164 G4int depth = 0; // Depth counts how many su 165 166 #ifdef G4DEBUG_FIELD 167 const G4double tolerance = 1.0e-8; 168 G4ThreeVector StartPosition = CurveStartPoi 169 if( (TrialPoint - StartPosition).mag() < tol 170 { 171 G4Exception("G4BrentLocator::EstimateInte 172 "GeomNav1002", JustWarning, 173 "Intersection point F is exac 174 } 175 #endif 176 177 // Intermediates Points on the Track = Subdi 178 // Give the initial values to 'InterMedFt' 179 // Important is 'ptrInterMedFT[0]', it saves 180 // 181 *ptrInterMedFT[0] = CurveEndPointVelocity; 182 for (auto idepth=1; idepth<max_depth+1; ++id 183 { 184 *ptrInterMedFT[idepth] = CurveStartPointVe 185 } 186 187 //Final_section boolean store 188 G4bool fin_section_depth[max_depth]; 189 for (bool & idepth : fin_section_depth) 190 { 191 idepth = true; 192 } 193 194 // 'SubStartPoint' is needed to calculate th 195 // 196 G4FieldTrack SubStart_PointVelocity = CurveS 197 198 do // Loop checking, 07.10.2016, J.Apostol 199 { 200 G4int substep_no_p = 0; 201 G4bool sub_final_section = false; // the s 202 // but f 203 SubStart_PointVelocity = CurrentA_PointVel 204 205 do // Loop checking, 07.10.2016, J.Apost 206 { // REPEAT param 207 G4ThreeVector Point_A = CurrentA_PointVe 208 G4ThreeVector Point_B = CurrentB_PointVe 209 210 // F = a point on true AB path close to 211 // (the closest if possible) 212 // 213 if(substep_no_p==0) 214 { 215 ApproxIntersecPointV = GetChordFinderF 216 ->ApproxCurvePo 217 218 219 220 // The above method is the key & mo 221 } 222 #ifdef G4DEBUG_FIELD 223 if( ApproxIntersecPointV.GetCurveLength( 224 CurrentB_PointVelocity.GetCurveLengt 225 { 226 G4Exception("G4BrentLocator::EstimateI 227 "GeomNav0003", FatalExcept 228 "Intermediate F point is p 229 } 230 #endif 231 232 G4ThreeVector CurrentF_Point = ApproxInt 233 234 // First check whether EF is small - the 235 // Calculate the length and direction of 236 // 237 G4ThreeVector ChordEF_Vector = CurrentF 238 G4ThreeVector NewMomentumDir = ApproxIn 239 G4double MomDir_dot_Norm = NewMome 240 241 #ifdef G4DEBUG_FIELD 242 G4ThreeVector ChordAB = Point_B - Point 243 244 G4VIntersectionLocator::ReportTrialStep( 245 ChordEF_Vector, NewMomentumDir, 246 #endif 247 248 G4bool adequate_angle; 249 adequate_angle = ( MomDir_dot_Norm >= 0 250 || (! validNormalAtE ); 251 G4double EF_dist2 = ChordEF_Vector.mag2( 252 if ( ( EF_dist2 <= sqr(fiDeltaIntersecti 253 || ( EF_dist2 <= kCarTolerance*kCarTol 254 { 255 found_approximate_intersection = true; 256 257 // Create the "point" return value 258 // 259 IntersectedOrRecalculatedFT = ApproxIn 260 IntersectedOrRecalculatedFT.SetPositio 261 262 if ( GetAdjustementOfFoundIntersection 263 { 264 // Try to Get Correction of Intersec 265 // 266 G4ThreeVector IP; 267 G4ThreeVector MomentumDir=ApproxInte 268 G4bool goodCorrection = AdjustmentOf 269 CurrentE_P 270 last_AF_in 271 fPreviousS 272 if ( goodCorrection ) 273 { 274 IntersectedOrRecalculatedFT = Appr 275 IntersectedOrRecalculatedFT.SetPos 276 } 277 } 278 279 // Note: in order to return a point on 280 // we must return E. But it is F 281 // So we must "cheat": we are us 282 // and the velocity at point F ! 283 // 284 // This must limit the length we can a 285 } 286 else // E is NOT close enough to the cu 287 { 288 // Check whether any volumes are encou 289 // ----------------------------------- 290 // First relocate to restore any Voxel 291 // in the Navigator before calling Com 292 // 293 GetNavigatorFor()->LocateGlobalPointWi 294 295 G4ThreeVector PointG; // Candidate i 296 G4double stepLengthAF; 297 G4bool usedNavigatorAF = false; 298 G4bool Intersects_AF = IntersectChord( 299 300 301 302 303 304 last_AF_intersection = Intersects_AF; 305 if( Intersects_AF ) 306 { 307 // G is our new Candidate for the in 308 // It replaces "E" and we will repe 309 // it is a good enough approximate p 310 // B <- F 311 // E <- G 312 // 313 G4FieldTrack EndPoint = ApproxInters 314 ApproxIntersecPointV = GetChordFinde 315 CurrentA_Poin 316 EndPoint,Curr 317 true, GetEpsi 318 CurrentB_PointVelocity = EndPoint; 319 CurrentE_Point = PointG; 320 321 // Need to recalculate the Exit Norm 322 // Know that a call was made to Navi 323 // IntersectChord above. 324 // 325 G4bool validNormalLast; 326 NormalAtEntry = GetSurfaceNormal( P 327 validNormalAtE = validNormalLast; 328 329 // By moving point B, must take care 330 // AF has no intersection to try cur 331 // 332 fin_section_depth[depth] = false; 333 #ifdef G4VERBOSE 334 if( fVerboseLevel > 3 ) 335 { 336 G4cout << "G4PiF::LI> Investigatin 337 << " at s=" << ApproxInters 338 << " on way to full s=" 339 << CurveEndPointVelocity.Ge 340 } 341 #endif 342 } 343 else // not Intersects_AF 344 { 345 // In this case: 346 // There is NO intersection of AF wi 347 // We must continue the search in th 348 // 349 GetNavigatorFor()->LocateGlobalPoint 350 351 G4double stepLengthFB; 352 G4ThreeVector PointH; 353 G4bool usedNavigatorFB = false; 354 355 // Check whether any volumes are enc 356 // --------------------------------- 357 358 G4bool Intersects_FB = IntersectChor 359 360 361 362 363 364 if( Intersects_FB ) 365 { 366 // There is an intersection of FB 367 // H <- First Intersection of Chor 368 369 // H is our new Candidate for the 370 // It replaces "E" and we will re 371 // it is a good enough approximate 372 373 // Note that F must be in volume v 374 // (otherwise AF would meet a volu 375 // A <- F 376 // E <- H 377 // 378 G4FieldTrack InterMed = ApproxInte 379 ApproxIntersecPointV = GetChordFin 380 CurrentA_PointVeloci 381 InterMed,CurrentE_Po 382 false,GetEpsilonStep 383 CurrentA_PointVelocity = InterMed; 384 CurrentE_Point = PointH; 385 386 // Need to recalculate the Exit No 387 // 388 G4bool validNormalLast; 389 NormalAtEntry = GetSurfaceNormal( 390 validNormalAtE = validNormalLast; 391 } 392 else // not Intersects_FB 393 { 394 // There is NO intersection of FB 395 396 if( fin_section_depth[depth] ) 397 { 398 // If B is the original endpoint 399 // volume(s) intersected the ori 400 // smaller chords we have used. 401 // The value of 'IntersectedOrRe 402 // likely not valid 403 404 // Check on real final_section o 405 // 406 if( ((Second_half)&&(depth==0)) 407 { 408 there_is_no_intersection = tru 409 } 410 else 411 { 412 // end of subsection, not real 413 // exit from the and go to the 414 415 substep_no_p = param_substeps+ 416 417 // but 'Second_half' is still 418 // the 'CurrentE_point' for th 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 origina 429 // 430 CurrentA_PointVelocity = Curre 431 CurrentB_PointVelocity = Curve 432 SubStart_PointVelocity = Curre 433 ApproxIntersecPointV = GetChor 434 ->ApproxCurvePo 435 436 437 438 439 restoredFullEndpoint = true; 440 ++restartB; // counter 441 } 442 else 443 { 444 // We must restore the depth e 445 // 446 CurrentA_PointVelocity = Curre 447 CurrentB_PointVelocity = *ptr 448 SubStart_PointVelocity = Curre 449 ApproxIntersecPointV = GetChor 450 ->ApproxCurvePo 451 452 453 454 restoredFullEndpoint = true; 455 ++restartB; // counter 456 } 457 } 458 } // Endif (Intersects_FB) 459 } // Endif (Intersects_AF) 460 461 // Ensure that the new endpoints are n 462 // than on the curve due to different 463 // 464 G4double linDistSq, curveDist; 465 linDistSq = ( CurrentB_PointVelocity.G 466 - CurrentA_PointVelocity.G 467 curveDist = CurrentB_PointVelocity.Get 468 - CurrentA_PointVelocity.G 469 470 // Change this condition for very stri 471 // 472 if( curveDist*curveDist*(1+2* GetEpsil 473 { 474 // Re-integrate to obtain a new B 475 // 476 G4FieldTrack newEndPointFT= 477 ReEstimateEndpoint( CurrentA 478 CurrentB 479 linDistS 480 curveDis 481 G4FieldTrack oldPointVelB = CurrentB 482 CurrentB_PointVelocity = newEndPoint 483 484 if ( (fin_section_depth[depth]) 485 &&( first_section || ((Second_ha 486 { 487 recalculatedEndPoint = true; 488 IntersectedOrRecalculatedFT = newE 489 // So that we can return it, if 490 } 491 } 492 if( curveDist < 0.0 ) 493 { 494 fVerboseLevel = 5; // Print out a ma 495 printStatus( CurrentA_PointVelocity, 496 -1.0, NewSafety, subst 497 std::ostringstream message; 498 message << "Error in advancing propa 499 << " Error in advanci 500 << " Point A (start) 501 << G4endl 502 << " Point B (end) 503 << G4endl 504 << " Curve distance i 505 << G4endl 506 << "The final curve point is 507 << " than the original!" << 508 509 if( recalculatedEndPoint ) 510 { 511 message << "Recalculation of EndPo 512 << GetEpsilonStepFor() << 513 } 514 oldprc = G4cerr.precision(20); 515 message << " Point A (Curve start) 516 << G4endl 517 << " Point B (Curve end) 518 << G4endl 519 << " Point A (Current start) 520 << G4endl 521 << " Point B (Current end) 522 << G4endl 523 << " Point S (Sub start) 524 << G4endl 525 << " Point E (Trial Point) 526 << G4endl 527 << " Old Point F(Intersectio 528 << G4endl 529 << " New Point F(Intersectio 530 << G4endl 531 << " LocateIntersecti 532 << substep_no << G4endl 533 << " Substep depth no 534 << depth << G4endl 535 << " Restarted no= "< 536 << GetEpsilonStepFor() <<" D 537 << GetDeltaIntersectionFor() 538 G4cerr.precision( oldprc ); 539 540 G4Exception("G4BrentLocator::Estimat 541 "GeomNav0003", FatalExce 542 } 543 544 if( restoredFullEndpoint ) 545 { 546 fin_section_depth[depth] = restoredF 547 restoredFullEndpoint = false; 548 } 549 } // EndIf ( E is close enough to the cu 550 // tests ChordAF_Vector.mag() <= maxim 551 552 #ifdef G4DEBUG_LOCATE_INTERSECTION 553 G4int trigger_substepno_print= warn_subs 554 555 if( substep_no >= trigger_substepno_prin 556 { 557 G4cout << "Difficulty in converging in 558 << "G4BrentLocator::EstimateInt 559 << G4endl 560 << " Substep no = " << subst 561 if( substep_no == trigger_substepno_pr 562 { 563 printStatus( CurveStartPointVelocity 564 -1.0, NewSafety, 0); 565 } 566 G4cout << " State of point A: "; 567 printStatus( CurrentA_PointVelocity, C 568 -1.0, NewSafety, substep_ 569 G4cout << " State of point B: "; 570 printStatus( CurrentA_PointVelocity, C 571 -1.0, NewSafety, substep_ 572 } 573 #endif 574 ++substep_no; 575 ++substep_no_p; 576 577 } while ( ( ! found_approximate_intersect 578 && ( ! there_is_no_intersection ) 579 && ( substep_no_p <= param_substep 580 581 first_section = false; 582 583 if( (!found_approximate_intersection) && ( 584 { 585 G4double did_len = std::abs( CurrentA_Po 586 - SubStart_PointVelocit 587 G4double all_len = std::abs( CurrentB_Po 588 - SubStart_PointVelocit 589 590 G4double stepLengthAB; 591 G4ThreeVector PointGe; 592 593 // Check if progress is too slow and if 594 // then halve the step if so 595 // 596 if ( ( did_len < fraction_done*all_len ) 597 && (depth < max_depth) && (!sub_final_ 598 { 599 Second_half=false; 600 ++depth; 601 602 G4double Sub_len = (all_len-did_len)/( 603 G4FieldTrack start = CurrentA_PointVel 604 auto integrDriver = 605 GetChordFinderFor()-> 606 integrDriver->AccurateAdvance(start, S 607 *ptrInterMedFT[depth] = start; 608 CurrentB_PointVelocity = *ptrInterMedF 609 610 // Adjust 'SubStartPoint' to calculate 611 // 612 SubStart_PointVelocity = CurrentA_Poin 613 614 // Find new trial intersection point n 615 // 616 G4ThreeVector Point_A = CurrentA_Point 617 G4ThreeVector SubE_point = CurrentB_Po 618 619 GetNavigatorFor()->LocateGlobalPointWi 620 G4bool Intersects_AB = IntersectChord( 621 622 623 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 Norm 631 // 632 G4bool validNormalAB; 633 NormalAtEntry = GetSurfaceNormal( Po 634 validNormalAtE = validNormalAB; 635 } 636 else 637 { 638 // No intersection found for first p 639 // (CurrentA,InterMedPoint[depth]). 640 // 641 Second_half = true; 642 } 643 } // if did_len 644 645 if( (Second_half)&&(depth!=0) ) 646 { 647 // Second part of curve (InterMed[dept 648 // On the depth-1 level normally we ar 649 650 Second_half = true; 651 652 // Find new trial intersection point 653 // 654 SubStart_PointVelocity = *ptrInterMedF 655 CurrentA_PointVelocity = *ptrInterMedF 656 CurrentB_PointVelocity = *ptrInterMedF 657 // Ensure that the new endpoints are 658 // than on the curve due to different 659 // 660 G4double linDistSq, curveDist; 661 linDistSq = ( CurrentB_PointVelocity.G 662 - CurrentA_PointVelocity.G 663 curveDist = CurrentB_PointVelocity.Get 664 - CurrentA_PointVelocity.G 665 if( curveDist*curveDist*(1+2*GetEpsilo 666 { 667 // Re-integrate to obtain a new B 668 // 669 G4FieldTrack newEndPointFT = 670 ReEstimateEndpoint( CurrentA 671 CurrentB 672 linDistS 673 curveDis 674 G4FieldTrack oldPointVelB = CurrentB 675 CurrentB_PointVelocity = newEndPoint 676 if ( depth==1 ) 677 { 678 recalculatedEndPoint = true; 679 IntersectedOrRecalculatedFT = newE 680 // So that we can return it, if it 681 } 682 } 683 684 685 G4ThreeVector Point_A = CurrentA_Po 686 G4ThreeVector SubE_point = CurrentB_Po 687 GetNavigatorFor()->LocateGlobalPointWi 688 G4bool Intersects_AB = IntersectChord( 689 690 691 if( Intersects_AB ) 692 { 693 last_AF_intersection = Intersects_AB 694 CurrentE_Point = PointGe; 695 696 G4bool validNormalAB; 697 NormalAtEntry = GetSurfaceNormal( P 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) ) 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 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::Estimat 726 << " Start and end-point of 727 printStatus( CurveStartPointVelocity, Curv 728 -1.0, NewSafety, 0); 729 G4cout << " Start and end-point of 730 printStatus( CurrentA_PointVelocity, Curre 731 -1.0, NewSafety, substep_no-1 732 printStatus( CurrentA_PointVelocity, Curre 733 -1.0, NewSafety, substep_no); 734 std::ostringstream message; 735 message << "Too many substeps!" << G4endl 736 << " Convergence is requi 737 << substep_no << G4endl 738 << " Abandoning effort to 739 << " Found intersection = 740 << found_approximate_intersection 741 << " Intersection exists 742 << !there_is_no_intersection << G4 743 oldprc = G4cout.precision( 10 ); 744 G4double done_len = CurrentA_PointVelocity 745 G4double full_len = CurveEndPointVelocity. 746 message << " Undertaken only length 747 << " out of " << full_len << " req 748 << " Remaining length = " < 749 G4cout.precision( oldprc ); 750 751 G4Exception("G4BrentLocator::EstimateInter 752 "GeomNav0003", FatalException, 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 759 << G4endl 760 << " Undertaken length: " 761 << CurrentB_PointVelocity.GetCurve 762 << " - Needed: " << substep_no << 763 << " Warning level = " << 764 << " and maximum substeps = " << m 765 G4Exception("G4BrentLocator::EstimateInter 766 "GeomNav1002", JustWarning, me 767 G4cout.precision( oldprc ); 768 } 769 return !there_is_no_intersection; // Succe 770 } 771