Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4SimpleLocator.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 G4SimpleLocator implementation
27//
28// 27.10.08 - Tatiana Nikitina, extracted from G4PropagatorInField class
29// 04.10.11 - John Apostolakis, revised convergence to use Surface Normal
30// ---------------------------------------------------------------------------
31
32#include <iomanip>
33
34#include "G4ios.hh"
35#include "G4SimpleLocator.hh"
36
41
43
44// --------------------------------------------------------------------------
45// G4bool G4PropagatorInField::LocateIntersectionPoint(
46// const G4FieldTrack& CurveStartPointVelocity, // A
47// const G4FieldTrack& CurveEndPointVelocity, // B
48// const G4ThreeVector& TrialPoint, // E
49// G4FieldTrack& IntersectedOrRecalculated // Output
50// G4bool& recalculated ) // Out
51// --------------------------------------------------------------------------
52//
53// Function that returns the intersection of the true path with the surface
54// of the current volume (either the external one or the inner one with one
55// of the daughters:
56//
57// A = Initial point
58// B = another point
59//
60// Both A and B are assumed to be on the true path:
61//
62// E is the first point of intersection of the chord AB with
63// a volume other than A (on the surface of A or of a daughter)
64//
65// Convention of Use :
66// i) If it returns "true", then IntersectionPointVelocity is set
67// to the approximate intersection point.
68// ii) If it returns "false", no intersection was found.
69// The validity of IntersectedOrRecalculated depends on 'recalculated'
70// a) if latter is false, then IntersectedOrRecalculated is invalid.
71// b) if latter is true, then IntersectedOrRecalculated is
72// the new endpoint, due to a re-integration.
73// --------------------------------------------------------------------------
74// NOTE: implementation taken from G4PropagatorInField
75//
77 const G4FieldTrack& CurveStartPointVelocity, // A
78 const G4FieldTrack& CurveEndPointVelocity, // B
79 const G4ThreeVector& TrialPoint, // E
80 G4FieldTrack& IntersectedOrRecalculatedFT, // Output
81 G4bool& recalculatedEndPoint, // Out
82 G4double &fPreviousSafety, //In/Out
84{
85 // Find Intersection Point ( A, B, E ) of true path AB - start at E.
86
87 G4bool found_approximate_intersection = false;
88 G4bool there_is_no_intersection = false;
89
90 G4FieldTrack CurrentA_PointVelocity = CurveStartPointVelocity;
91 G4FieldTrack CurrentB_PointVelocity = CurveEndPointVelocity;
92 G4ThreeVector CurrentE_Point = TrialPoint;
93 G4bool validNormalAtE = false;
94 G4ThreeVector NormalAtEntry;
95
96 G4FieldTrack ApproxIntersecPointV(CurveEndPointVelocity); // FT-Def-Construct
97 G4double NewSafety = 0.0;
98 G4bool last_AF_intersection = false;
99 G4bool final_section = true; // Shows whether current section is last
100 // (i.e. B=full end)
101 recalculatedEndPoint = false;
102
103 G4bool restoredFullEndpoint = false;
104
105 G4int substep_no = 0;
106
107 // Limits for substep number
108 //
109 const G4int max_substeps = 100000000; // Test 120 (old value 100 )
110 const G4int warn_substeps = 1000; // 100
111
112 // Statistics for substeps
113 //
114 static G4ThreadLocal G4int max_no_seen= -1;
115
116 NormalAtEntry = GetSurfaceNormal( CurrentE_Point, validNormalAtE);
117
118#ifdef G4DEBUG_FIELD
119 const G4double tolerance = 1.0e-8;
120 G4ThreeVector StartPosition= CurveStartPointVelocity.GetPosition();
121 if( (TrialPoint - StartPosition).mag() < tolerance * CLHEP::mm )
122 {
123 G4Exception("G4SimpleLocator::EstimateIntersectionPoint()",
124 "GeomNav1002", JustWarning,
125 "Intersection point F is exactly at start point A." );
126 }
127#endif
128
129 do
130 {
131 G4ThreeVector Point_A = CurrentA_PointVelocity.GetPosition();
132 G4ThreeVector Point_B = CurrentB_PointVelocity.GetPosition();
133
134 // F = a point on true AB path close to point E
135 // (the closest if possible)
136 //
137 ApproxIntersecPointV = GetChordFinderFor()
138 ->ApproxCurvePointV( CurrentA_PointVelocity,
139 CurrentB_PointVelocity,
140 CurrentE_Point,
142 // The above method is the key & most intuitive part ...
143
144#ifdef G4DEBUG_FIELD
145 if( ApproxIntersecPointV.GetCurveLength() >
146 CurrentB_PointVelocity.GetCurveLength() * (1.0 + tolerance) )
147 {
148 G4Exception("G4SimpleLocator::EstimateIntersectionPoint()",
149 "GeomNav0003", FatalException,
150 "Intermediate F point is past end B point!" );
151 }
152#endif
153
154 G4ThreeVector CurrentF_Point = ApproxIntersecPointV.GetPosition();
155
156 // First check whether EF is small - then F is a good approx. point
157 // Calculate the length and direction of the chord AF
158 //
159 G4ThreeVector ChordEF_Vector = CurrentF_Point - CurrentE_Point;
160
161 G4ThreeVector NewMomentumDir = ApproxIntersecPointV.GetMomentumDir();
162 G4double MomDir_dot_Norm = NewMomentumDir.dot( NormalAtEntry ) ;
163
164 G4ThreeVector ChordAB = Point_B - Point_A;
165
166#ifdef G4DEBUG_FIELD
168 ReportTrialStep( substep_no, ChordAB, ChordEF_Vector,
169 NewMomentumDir, NormalAtEntry, validNormalAtE );
170#endif
171 // Check Sign is always exiting !! TODO
172 // Could ( > -epsilon) be used instead?
173 //
174 G4bool adequate_angle = ( MomDir_dot_Norm >= 0.0 )
175 || (! validNormalAtE ); // Invalid
176 G4double EF_dist2= ChordEF_Vector.mag2();
177 if ( ( EF_dist2 <= sqr(fiDeltaIntersection) && ( adequate_angle ) )
178 || ( EF_dist2 <= kCarTolerance*kCarTolerance ) )
179 {
180 found_approximate_intersection = true;
181
182 // Create the "point" return value
183 //
184 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
185 IntersectedOrRecalculatedFT.SetPosition( CurrentE_Point );
186
188 {
189 // Try to Get Correction of IntersectionPoint using SurfaceNormal()
190 //
191 G4ThreeVector IP;
192 G4ThreeVector MomentumDir= ApproxIntersecPointV.GetMomentumDirection();
193 G4bool goodCorrection = AdjustmentOfFoundIntersection( Point_A,
194 CurrentE_Point, CurrentF_Point, MomentumDir,
195 last_AF_intersection, IP, NewSafety,
197
198 if ( goodCorrection )
199 {
200 IntersectedOrRecalculatedFT = ApproxIntersecPointV;
201 IntersectedOrRecalculatedFT.SetPosition(IP);
202 }
203 }
204
205 // Note: in order to return a point on the boundary,
206 // we must return E. But it is F on the curve.
207 // So we must "cheat": we are using the position at point E
208 // and the velocity at point F !!!
209 //
210 // This must limit the length we can allow for displacement!
211 }
212 else // E is NOT close enough to the curve (ie point F)
213 {
214 // Check whether any volumes are encountered by the chord AF
215 // ---------------------------------------------------------
216 // First relocate to restore any Voxel etc information
217 // in the Navigator before calling ComputeStep()
218 //
220
221 G4ThreeVector PointG; // Candidate intersection point
222 G4double stepLengthAF;
223 G4bool usedNavigatorAF = false;
224 G4bool Intersects_AF = IntersectChord( Point_A,
225 CurrentF_Point,
226 NewSafety,
229 stepLengthAF,
230 PointG,
231 &usedNavigatorAF );
232 last_AF_intersection = Intersects_AF;
233 if( Intersects_AF )
234 {
235 // G is our new Candidate for the intersection point.
236 // It replaces "E" and we will repeat the test to see if
237 // it is a good enough approximate point for us.
238 // B <- F
239 // E <- G
240
241 CurrentB_PointVelocity = ApproxIntersecPointV;
242 CurrentE_Point = PointG;
243
244 // Need to recalculate the Exit Normal at the new PointG
245 // Relies on a call to Navigator::ComputeStep in IntersectChord above
246 // If the safety was adequate (for the step) this would NOT be called!
247 // But this must not occur, no intersection can be found in that case,
248 // so this branch, ie if( Intersects_AF ) would not be reached!
249 //
250 G4bool validNormalLast;
251 NormalAtEntry = GetSurfaceNormal( PointG, validNormalLast );
252 validNormalAtE = validNormalLast;
253
254 // By moving point B, must take care if current
255 // AF has no intersection to try current FB!!
256 //
257 final_section = false;
258
259#ifdef G4VERBOSE
260 if( fVerboseLevel > 3 )
261 {
262 G4cout << "G4PiF::LI> Investigating intermediate point"
263 << " at s=" << ApproxIntersecPointV.GetCurveLength()
264 << " on way to full s="
265 << CurveEndPointVelocity.GetCurveLength() << G4endl;
266 }
267#endif
268 }
269 else // not Intersects_AF
270 {
271 // In this case:
272 // There is NO intersection of AF with a volume boundary.
273 // We must continue the search in the segment FB!
274 //
276
277 G4double stepLengthFB;
278 G4ThreeVector PointH;
279 G4bool usedNavigatorFB = false;
280
281 // Check whether any volumes are encountered by the chord FB
282 // ---------------------------------------------------------
283
284 G4bool Intersects_FB = IntersectChord( CurrentF_Point, Point_B,
285 NewSafety,fPreviousSafety,
287 stepLengthFB,
288 PointH, &usedNavigatorFB );
289 if( Intersects_FB )
290 {
291 // There is an intersection of FB with a volume boundary
292 // H <- First Intersection of Chord FB
293
294 // H is our new Candidate for the intersection point.
295 // It replaces "E" and we will repeat the test to see if
296 // it is a good enough approximate point for us.
297
298 // Note that F must be in volume volA (the same as A)
299 // (otherwise AF would meet a volume boundary!)
300 // A <- F
301 // E <- H
302 //
303 CurrentA_PointVelocity = ApproxIntersecPointV;
304 CurrentE_Point = PointH;
305
306 // Need to recalculate the Exit Normal at the new PointG
307 // Relies on call to Navigator::ComputeStep in IntersectChord above
308 // If safety was adequate (for the step) this would NOT be called!
309 // But this must not occur, no intersection found in that case,
310 // so this branch, i.e. if( Intersects_AF ) would not be reached!
311 //
312 G4bool validNormalLast;
313 NormalAtEntry = GetSurfaceNormal( PointH, validNormalLast );
314 validNormalAtE = validNormalLast;
315 }
316 else // not Intersects_FB
317 {
318 // There is NO intersection of FB with a volume boundary
319
320 if( final_section )
321 {
322 // If B is the original endpoint, this means that whatever
323 // volume(s) intersected the original chord, none touch the
324 // smaller chords we have used.
325 // The value of 'IntersectedOrRecalculatedFT' returned is
326 // likely not valid
327
328 there_is_no_intersection = true; // real final_section
329 }
330 else
331 {
332 // We must restore the original endpoint
333
334 CurrentA_PointVelocity = CurrentB_PointVelocity; // Got to B
335 CurrentB_PointVelocity = CurveEndPointVelocity;
336 restoredFullEndpoint = true;
337 }
338 } // Endif (Intersects_FB)
339 } // Endif (Intersects_AF)
340
341 // Ensure that the new endpoints are not further apart in space
342 // than on the curve due to different errors in the integration
343 //
344 G4double linDistSq, curveDist;
345 linDistSq = ( CurrentB_PointVelocity.GetPosition()
346 - CurrentA_PointVelocity.GetPosition() ).mag2();
347 curveDist = CurrentB_PointVelocity.GetCurveLength()
348 - CurrentA_PointVelocity.GetCurveLength();
349
350 // Change this condition for very strict parameters of propagation
351 //
352 if( curveDist*curveDist*(1+2* GetEpsilonStepFor()) < linDistSq )
353 {
354 // Re-integrate to obtain a new B
355 //
356 G4FieldTrack newEndPointFT =
357 ReEstimateEndpoint( CurrentA_PointVelocity,
358 CurrentB_PointVelocity,
359 linDistSq, // to avoid recalculation
360 curveDist );
361 G4FieldTrack oldPointVelB = CurrentB_PointVelocity;
362 CurrentB_PointVelocity = newEndPointFT;
363
364 if( (final_section)) // real final section
365 {
366 recalculatedEndPoint = true;
367 IntersectedOrRecalculatedFT = newEndPointFT;
368 // So that we can return it, if it is the endpoint!
369 }
370 }
371 if( curveDist < 0.0 )
372 {
373 fVerboseLevel = 5; // Print out a maximum of information
374 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
375 -1.0, NewSafety, substep_no );
376 std::ostringstream message;
377 message << "Error in advancing propagation." << G4endl
378 << " Point A (start) is " << CurrentA_PointVelocity
379 << G4endl
380 << " Point B (end) is " << CurrentB_PointVelocity
381 << G4endl
382 << " Curve distance is " << curveDist << G4endl
383 << G4endl
384 << "The final curve point is not further along"
385 << " than the original!" << G4endl;
386
387 if( recalculatedEndPoint )
388 {
389 message << "Recalculation of EndPoint was called with fEpsStep= "
391 }
392 message.precision(20);
393 message << " Point A (Curve start) is " << CurveStartPointVelocity
394 << G4endl
395 << " Point B (Curve end) is " << CurveEndPointVelocity
396 << G4endl
397 << " Point A (Current start) is " << CurrentA_PointVelocity
398 << G4endl
399 << " Point B (Current end) is " << CurrentB_PointVelocity
400 << G4endl
401 << " Point E (Trial Point) is " << CurrentE_Point
402 << G4endl
403 << " Point F (Intersection) is " << ApproxIntersecPointV
404 << G4endl
405 << " LocateIntersection parameters are : Substep no= "
406 << substep_no;
407
408 G4Exception("G4SimpleLocator::EstimateIntersectionPoint()",
409 "GeomNav0003", FatalException, message);
410 }
411
412 if ( restoredFullEndpoint )
413 {
414 final_section = restoredFullEndpoint;
415 restoredFullEndpoint = false;
416 }
417 } // EndIf ( E is close enough to the curve, ie point F. )
418 // tests ChordAF_Vector.mag() <= maximum_lateral_displacement
419
420#ifdef G4DEBUG_LOCATE_INTERSECTION
421 G4int trigger_substepno_print= warn_substeps - 20;
422
423 if( substep_no >= trigger_substepno_print )
424 {
425 G4cout << "Difficulty in converging in "
426 << "G4SimpleLocator::EstimateIntersectionPoint():"
427 << G4endl
428 << " Substep no = " << substep_no << G4endl;
429 if( substep_no == trigger_substepno_print )
430 {
431 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
432 -1.0, NewSafety, 0);
433 }
434 G4cout << " State of point A: ";
435 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
436 -1.0, NewSafety, substep_no-1, 0);
437 G4cout << " State of point B: ";
438 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
439 -1.0, NewSafety, substep_no);
440 }
441#endif
442 ++substep_no;
443
444 } while ( ( ! found_approximate_intersection )
445 && ( ! there_is_no_intersection )
446 && ( substep_no <= max_substeps) ); // UNTIL found or failed
447
448 if( substep_no > max_no_seen )
449 {
450 max_no_seen = substep_no;
451#ifdef G4DEBUG_LOCATE_INTERSECTION
452 if( max_no_seen > warn_substeps )
453 {
454 trigger_substepno_print = max_no_seen-20; // Want to see last 20 steps
455 }
456#endif
457 }
458
459 if( ( substep_no >= max_substeps)
460 && !there_is_no_intersection
461 && !found_approximate_intersection )
462 {
463 G4cout << "ERROR - G4SimpleLocator::EstimateIntersectionPoint()" << G4endl
464 << " Start and Endpoint of Requested Step:" << G4endl;
465 printStatus( CurveStartPointVelocity, CurveEndPointVelocity,
466 -1.0, NewSafety, 0);
467 G4cout << G4endl
468 << " Start and end-point of current Sub-Step:" << G4endl;
469 printStatus( CurrentA_PointVelocity, CurrentA_PointVelocity,
470 -1.0, NewSafety, substep_no-1);
471 printStatus( CurrentA_PointVelocity, CurrentB_PointVelocity,
472 -1.0, NewSafety, substep_no);
473
474 std::ostringstream message;
475 message << "Convergence is requiring too many substeps: "
476 << substep_no << G4endl
477 << " Abandoning effort to intersect." << G4endl
478 << " Found intersection = "
479 << found_approximate_intersection << G4endl
480 << " Intersection exists = "
481 << !there_is_no_intersection << G4endl;
482 message.precision(10);
483 G4double done_len = CurrentA_PointVelocity.GetCurveLength();
484 G4double full_len = CurveEndPointVelocity.GetCurveLength();
485 message << " Undertaken only length: " << done_len
486 << " out of " << full_len << " required." << G4endl
487 << " Remaining length = " << full_len-done_len;
488
489 G4Exception("G4SimpleLocator::EstimateIntersectionPoint()",
490 "GeomNav0003", FatalException, message);
491 }
492 else if( substep_no >= warn_substeps )
493 {
494 std::ostringstream message;
495 message.precision(10);
496
497 message << "Many substeps while trying to locate intersection." << G4endl
498 << " Undertaken length: "
499 << CurrentB_PointVelocity.GetCurveLength()
500 << " - Needed: " << substep_no << " substeps." << G4endl
501 << " Warning level = " << warn_substeps
502 << " and maximum substeps = " << max_substeps;
503 G4Exception("G4SimpleLocator::EstimateIntersectionPoint()",
504 "GeomNav1002", JustWarning, message);
505 }
506 return !there_is_no_intersection; // Success or failure
507}
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define fPreviousSftOrigin
#define fPreviousSafety
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double mag2() const
double dot(const Hep3Vector &) const
G4FieldTrack ApproxCurvePointV(const G4FieldTrack &curveAPointVelocity, const G4FieldTrack &curveBPointVelocity, const G4ThreeVector &currentEPoint, G4double epsStep)
const G4ThreeVector & GetMomentumDir() const
G4double GetCurveLength() const
G4ThreeVector GetMomentumDirection() const
void SetPosition(const G4ThreeVector &nPos)
G4ThreeVector GetPosition() const
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
G4SimpleLocator(G4Navigator *aNavigator)
G4bool EstimateIntersectionPoint(const G4FieldTrack &curveStartPointTangent, const G4FieldTrack &curveEndPointTangent, const G4ThreeVector &trialPoint, G4FieldTrack &intersectPointTangent, G4bool &recalculatedEndPoint, G4double &fPreviousSafety, G4ThreeVector &fPreviousSftOrigin) override
~G4SimpleLocator() override
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()
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)
T sqr(const T &x)
Definition templates.hh:128
#define G4ThreadLocal
Definition tls.hh:77