Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4VIntersectionLocator.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// $Id$
27//
28// Class G4VIntersectionLocator implementation
29//
30// 27.10.08 - John Apostolakis, Tatiana Nikitina.
31// ---------------------------------------------------------------------------
32
33#include <iomanip>
34#include <sstream>
35
36#include "globals.hh"
37#include "G4ios.hh"
38#include "G4SystemOfUnits.hh"
41
42///////////////////////////////////////////////////////////////////////////
43//
44// Constructor
45//
47 fUseNormalCorrection(false),
48 fiNavigator( theNavigator ),
49 fiChordFinder( 0 ), // Not set - overridden at each step
50 fiEpsilonStep( -1.0 ), // Out of range - overridden at each step
51 fiDeltaIntersection( -1.0 ), // Out of range - overridden at each step
52 fiUseSafety(false), // Default - overridden at each step
53 fpTouchable(0)
54{
56 fVerboseLevel = 0;
58}
59
60///////////////////////////////////////////////////////////////////////////
61//
62// Destructor.
63//
65{
66 delete fHelpingNavigator;
67 delete fpTouchable;
68}
69
70///////////////////////////////////////////////////////////////////////////
71//
72// Dumps status of propagator.
73//
74void
76 const G4FieldTrack& CurrentFT,
77 G4double requestStep,
78 G4double safety,
79 G4int stepNo)
80{
81 const G4int verboseLevel= fVerboseLevel;
82 const G4ThreeVector StartPosition = StartFT.GetPosition();
83 const G4ThreeVector StartUnitVelocity = StartFT.GetMomentumDir();
84 const G4ThreeVector CurrentPosition = CurrentFT.GetPosition();
85 const G4ThreeVector CurrentUnitVelocity = CurrentFT.GetMomentumDir();
86
87 G4double step_len = CurrentFT.GetCurveLength() - StartFT.GetCurveLength();
88 G4int oldprc; // cout/cerr precision settings
89
90 if( ((stepNo == 0) && (verboseLevel <3)) || (verboseLevel >= 3) )
91 {
92 oldprc = G4cout.precision(4);
93 G4cout << std::setw( 6) << " "
94 << std::setw( 25) << " Current Position and Direction" << " "
95 << G4endl;
96 G4cout << std::setw( 5) << "Step#"
97 << std::setw(10) << " s " << " "
98 << std::setw(10) << "X(mm)" << " "
99 << std::setw(10) << "Y(mm)" << " "
100 << std::setw(10) << "Z(mm)" << " "
101 << std::setw( 7) << " N_x " << " "
102 << std::setw( 7) << " N_y " << " "
103 << std::setw( 7) << " N_z " << " " ;
104 G4cout << std::setw( 7) << " Delta|N|" << " "
105 << std::setw( 9) << "StepLen" << " "
106 << std::setw(12) << "StartSafety" << " "
107 << std::setw( 9) << "PhsStep" << " ";
108 G4cout << G4endl;
109 G4cout.precision(oldprc);
110 }
111 if((stepNo == 0) && (verboseLevel <=3))
112 {
113 // Recurse to print the start values
114 //
115 printStatus( StartFT, StartFT, -1.0, safety, -1);
116 }
117 if( verboseLevel <= 3 )
118 {
119 if( stepNo >= 0)
120 {
121 G4cout << std::setw( 4) << stepNo << " ";
122 }
123 else
124 {
125 G4cout << std::setw( 5) << "Start" ;
126 }
127 oldprc = G4cout.precision(8);
128 G4cout << std::setw(10) << CurrentFT.GetCurveLength() << " ";
129 G4cout << std::setw(10) << CurrentPosition.x() << " "
130 << std::setw(10) << CurrentPosition.y() << " "
131 << std::setw(10) << CurrentPosition.z() << " ";
132 G4cout.precision(4);
133 G4cout << std::setw( 7) << CurrentUnitVelocity.x() << " "
134 << std::setw( 7) << CurrentUnitVelocity.y() << " "
135 << std::setw( 7) << CurrentUnitVelocity.z() << " ";
136 G4cout.precision(3);
137 G4cout << std::setw( 7)
138 << CurrentFT.GetMomentum().mag()- StartFT.GetMomentum().mag()
139 << " ";
140 G4cout << std::setw( 9) << step_len << " ";
141 G4cout << std::setw(12) << safety << " ";
142 if( requestStep != -1.0 )
143 {
144 G4cout << std::setw( 9) << requestStep << " ";
145 }
146 else
147 {
148 G4cout << std::setw( 9) << "Init/NotKnown" << " ";
149 }
150 G4cout << G4endl;
151 G4cout.precision(oldprc);
152 }
153 else // if( verboseLevel > 3 )
154 {
155 // Multi-line output
156
157 G4cout << "Step taken was " << step_len
158 << " out of PhysicalStep= " << requestStep << G4endl;
159 G4cout << "Final safety is: " << safety << G4endl;
160 G4cout << "Chord length = " << (CurrentPosition-StartPosition).mag()
161 << G4endl;
162 G4cout << G4endl;
163 }
164}
165
166///////////////////////////////////////////////////////////////////////////
167//
168// ReEstimateEndPoint.
169//
171ReEstimateEndpoint( const G4FieldTrack& CurrentStateA,
172 const G4FieldTrack& EstimatedEndStateB,
173 G4double linearDistSq,
174 G4double curveDist )
175{
176 G4FieldTrack newEndPoint( CurrentStateA );
178
179 G4FieldTrack retEndPoint( CurrentStateA );
180 G4bool goodAdvance;
181 G4int itrial=0;
182 const G4int no_trials= 20;
183
184 G4double endCurveLen= EstimatedEndStateB.GetCurveLength();
185 do
186 {
187 G4double currentCurveLen= newEndPoint.GetCurveLength();
188 G4double advanceLength= endCurveLen - currentCurveLen ;
189 if (std::abs(advanceLength)<kCarTolerance)
190 {
191 goodAdvance=true;
192 }
193 else{
194 goodAdvance=
195 integrDriver->AccurateAdvance(newEndPoint, advanceLength,
197 }
198 }
199 while( !goodAdvance && (++itrial < no_trials) );
200
201 if( goodAdvance )
202 {
203 retEndPoint= newEndPoint;
204 }
205 else
206 {
207 retEndPoint= EstimatedEndStateB; // Could not improve without major work !!
208 }
209
210 // All the work is done
211 // below are some diagnostics only -- before the return!
212 //
213 static const G4String MethodName("G4VIntersectionLocator::ReEstimateEndpoint");
214
215#ifdef G4VERBOSE
216 G4int latest_good_trials=0;
217 if( itrial > 1)
218 {
219 if( fVerboseLevel > 0 )
220 {
221 G4cout << MethodName << " called - goodAdv= " << goodAdvance
222 << " trials = " << itrial
223 << " previous good= " << latest_good_trials
224 << G4endl;
225 }
226 latest_good_trials=0;
227 }
228 else
229 {
230 latest_good_trials++;
231 }
232#endif
233
234#ifdef G4DEBUG_FIELD
235 G4double lengthDone = newEndPoint.GetCurveLength()
236 - CurrentStateA.GetCurveLength();
237 if( !goodAdvance )
238 {
239 if( fVerboseLevel >= 3 )
240 {
241 G4cout << MethodName << "> AccurateAdvance failed " ;
242 G4cout << " in " << itrial << " integration trials/steps. " << G4endl;
243 G4cout << " It went only " << lengthDone << " instead of " << curveDist
244 << " -- a difference of " << curveDist - lengthDone << G4endl;
245 G4cout << " ReEstimateEndpoint> Reset endPoint to original value!"
246 << G4endl;
247 }
248 }
249
250 static G4int noInaccuracyWarnings = 0;
251 G4int maxNoWarnings = 10;
252 if ( (noInaccuracyWarnings < maxNoWarnings )
253 || (fVerboseLevel > 1) )
254 {
255 G4cerr << "G4PropagatorInField::LocateIntersectionPoint():"
256 << G4endl
257 << " Warning: Integration inaccuracy requires"
258 << " an adjustment in the step's endpoint." << G4endl
259 << " Two mid-points are further apart than their"
260 << " curve length difference" << G4endl
261 << " Dist = " << std::sqrt(linearDistSq)
262 << " curve length = " << curveDist << G4endl;
263 G4cerr << " Correction applied is "
264 << (newEndPoint.GetPosition()-EstimatedEndStateB.GetPosition()).mag()
265 << G4endl;
266 }
267#else
268 // Statistics on the RMS value of the corrections
269
270 static G4int noCorrections=0;
271 static G4double sumCorrectionsSq = 0;
272 noCorrections++;
273 if( goodAdvance )
274 {
275 sumCorrectionsSq += (EstimatedEndStateB.GetPosition() -
276 newEndPoint.GetPosition()).mag2();
277 }
278 linearDistSq -= curveDist; // To use linearDistSq ... !
279#endif
280
281 return retEndPoint;
282}
283
284///////////////////////////////////////////////////////////////////////////
285//
286// Method for finding SurfaceNormal of Intersecting Solid
287//
288G4ThreeVector G4VIntersectionLocator::
289GetLocalSurfaceNormal(const G4ThreeVector& CurrentE_Point, G4bool& validNormal)
290{
291 G4ThreeVector Normal(G4ThreeVector(0.0,0.0,0.0));
292 G4VPhysicalVolume* located;
293
294 validNormal = false;
296 located = fHelpingNavigator->LocateGlobalPointAndSetup( CurrentE_Point );
297
298 delete fpTouchable;
300
301 // To check if we can use GetGlobalExitNormal()
302 //
303 G4ThreeVector localPosition = fpTouchable->GetHistory()
304 ->GetTopTransform().TransformPoint(CurrentE_Point);
305
306 // Issue: in the case of coincident surfaces, this version does not recognise
307 // which side you are located onto (can return vector with wrong sign.)
308 // TO-DO: use direction (of chord) to identify volume we will be "entering"
309
310 if( located != 0)
311 {
312 G4LogicalVolume* pLogical= located->GetLogicalVolume();
313 G4VSolid* pSolid;
314
315 if( (pLogical != 0) && ( (pSolid=pLogical->GetSolid()) !=0 ) )
316 {
317 // G4bool goodPoint, nearbyPoint;
318 // G4int numGoodPoints, numNearbyPoints; // --> use for stats
319 if ( ( pSolid->Inside(localPosition)==kSurface )
320 || ( pSolid->DistanceToOut(localPosition) < 1000.0 * kCarTolerance )
321 )
322 {
323 Normal = pSolid->SurfaceNormal(localPosition);
324 validNormal = true;
325
326#ifdef G4DEBUG_FIELD
327 if( std::fabs(Normal.mag2() - 1.0 ) > perMille)
328 {
329 G4cerr << "PROBLEM in G4VIntersectionLocator::GetLocalSurfaceNormal."
330 << G4endl;
331 G4cerr << " Normal is not unit - mag=" << Normal.mag() << G4endl;
332 G4cerr << " at trial local point " << CurrentE_Point << G4endl;
333 G4cerr << " Solid is " << *pSolid << G4endl;
334 }
335#endif
336 }
337 }
338 }
339
340 return Normal;
341}
342
343///////////////////////////////////////////////////////////////////////////
344//
345// Adjustment of Found Intersection
346//
348AdjustmentOfFoundIntersection( const G4ThreeVector& CurrentA_Point,
349 const G4ThreeVector& CurrentE_Point,
350 const G4ThreeVector& CurrentF_Point,
351 const G4ThreeVector& MomentumDir,
352 const G4bool IntersectAF,
353 G4ThreeVector& IntersectionPoint, // I/O
354 G4double& NewSafety, // I/O
355 G4double& fPreviousSafety, // I/O
356 G4ThreeVector& fPreviousSftOrigin )// I/O
357{
358 G4double dist,lambda;
359 G4ThreeVector Normal, NewPoint, Point_G;
360 G4bool goodAdjust=false, Intersects_FP=false, validNormal=false;
361
362 // Get SurfaceNormal of Intersecting Solid
363 //
364 Normal = GetGlobalSurfaceNormal(CurrentE_Point,validNormal);
365 if(!validNormal) { return false; }
366
367 // Intersection between Line and Plane
368 //
369 G4double n_d_m = Normal.dot(MomentumDir);
370 if ( std::abs(n_d_m)>kCarTolerance )
371 {
372#ifdef G4VERBOSE
373 if ( fVerboseLevel>1 )
374 {
375 G4cerr << "WARNING - "
376 << "G4VIntersectionLocator::AdjustementOfFoundIntersection()"
377 << G4endl
378 << " No intersection. Parallels lines!" << G4endl;
379 }
380#endif
381 lambda =- Normal.dot(CurrentF_Point-CurrentE_Point)/n_d_m;
382
383 // New candidate for Intersection
384 //
385 NewPoint = CurrentF_Point+lambda*MomentumDir;
386
387 // Distance from CurrentF to Calculated Intersection
388 //
389 dist = std::abs(lambda);
390
391 if ( dist<kCarTolerance*0.001 ) { return false; }
392
393 // Calculation of new intersection point on the path.
394 //
395 if ( IntersectAF ) // First part intersects
396 {
397 G4double stepLengthFP;
398 G4ThreeVector Point_P = CurrentA_Point;
400 Intersects_FP = IntersectChord( Point_P, NewPoint, NewSafety,
401 fPreviousSafety, fPreviousSftOrigin,
402 stepLengthFP, Point_G );
403
404 }
405 else // Second part intersects
406 {
407 G4double stepLengthFP;
409 Intersects_FP = IntersectChord( CurrentF_Point, NewPoint, NewSafety,
410 fPreviousSafety, fPreviousSftOrigin,
411 stepLengthFP, Point_G );
412 }
413 if ( Intersects_FP )
414 {
415 goodAdjust = true;
416 IntersectionPoint = Point_G;
417 }
418 }
419
420 return goodAdjust;
421}
422
425 G4bool& validNormal) // const
426{
427 G4ThreeVector NormalAtEntry; // ( -10. , -10., -10. );
428
429 G4ThreeVector NormalAtEntryLast, NormalAtEntryGlobal, diffNormals;
430 G4bool validNormalLast;
431
432 // Relies on a call to Navigator::ComputeStep in IntersectChord before
433 // this call
434 //
435 NormalAtEntryLast = GetLastSurfaceNormal( CurrentInt_Point, validNormalLast );
436 // May return valid=false in cases, including
437 // - if the candidate volume was not found (eg exiting world), or
438 // - a replica was involved -- determined the step size.
439 // (This list is not complete.)
440
441#ifdef G4DEBUG_FIELD
442 if ( validNormalLast
443 && ( std::fabs(NormalAtEntryLast.mag2() - 1.0) > perThousand ) )
444 {
445 std::ostringstream message;
446 message << "G4VIntersectionLocator::GetSurfaceNormal -- identified problem."
447 << G4endl;
448 message << "PROBLEM: Normal is not unit - magnitude = "
449 << NormalAtEntryLast.mag() << G4endl;
450 message << " at trial intersection point " << CurrentInt_Point << G4endl;
451 message << " Obtained from Get *Last* Surface Normal." << G4endl;
452 G4Exception("G4VIntersectionLocator::GetGlobalSurfaceNormal()",
453 "GeomNav1002", JustWarning, message);
454 }
455#endif
456
457 if( validNormalLast )
458 {
459 NormalAtEntry=NormalAtEntryLast;
460 }
461 validNormal = validNormalLast;
462
463 return NormalAtEntry;
464}
465
467GetGlobalSurfaceNormal(const G4ThreeVector& CurrentE_Point,
468 G4bool& validNormal)
469{
470 G4ThreeVector localNormal=
471 GetLocalSurfaceNormal( CurrentE_Point, validNormal );
472 G4AffineTransform localToGlobal= // Must use the same Navigator !!
474 G4ThreeVector globalNormal =
475 localToGlobal.TransformAxis( localNormal );
476
477#ifdef G4DEBUG_FIELD
478 if( validNormal && ( std::fabs(globalNormal.mag2() - 1.0) > perThousand ) )
479 {
480 std::ostringstream message;
481 message << "**************************************************************"
482 << G4endl;
483 message << " Bad Normal in G4VIntersectionLocator::GetGlobalSurfaceNormal "
484 << G4endl;
485 message << " * Constituents: " << G4endl;
486 message << " Local Normal= " << localNormal << G4endl;
487 message << " Transform: " << G4endl
488 << " Net Translation= " << localToGlobal.NetTranslation()
489 << G4endl
490 << " Net Rotation = " << localToGlobal.NetRotation()
491 << G4endl;
492 message << " * Result: " << G4endl;
493 message << " Global Normal= " << localNormal << G4endl;
494 message << "**************************************************************"
495 << G4endl;
496 G4Exception("G4VIntersectionLocator::GetGlobalSurfaceNormal()",
497 "GeomNav1002", JustWarning, message);
498 }
499#endif
500
501 return globalNormal;
502}
503
505G4VIntersectionLocator::GetLastSurfaceNormal( const G4ThreeVector& intersectPoint,
506 G4bool& normalIsValid) const
507{
508 G4ThreeVector normalVec;
509 G4bool validNorm;
510 normalVec = fiNavigator->GetGlobalExitNormal( intersectPoint, &validNorm );
511 normalIsValid= validNorm;
512
513 return normalVec;
514}
515
517 const G4ThreeVector& ChordAB_v,
518 const G4ThreeVector& ChordEF_v,
519 const G4ThreeVector& NewMomentumDir,
520 const G4ThreeVector& NormalAtEntry,
521 G4bool validNormal )
522{
523 G4double ABchord_length = ChordAB_v.mag();
524 G4double MomDir_dot_Norm = NewMomentumDir.dot( NormalAtEntry ) ;
525 G4double MomDir_dot_ABchord;
526 MomDir_dot_ABchord= (1.0 / ABchord_length) * NewMomentumDir.dot( ChordAB_v );
527
528 std::ostringstream outStream;
529 outStream // G4cout
530 << std::setw(6) << " Step# "
531 << std::setw(17) << " |ChordEF|(mag)" << " "
532 << std::setw(18) << " uMomentum.Normal" << " "
533 << std::setw(18) << " uMomentum.ABdir " << " "
534 << std::setw(16) << " AB-dist " << " "
535 << " Chord Vector (EF) "
536 << G4endl;
537 outStream.precision(7);
538 outStream // G4cout
539 << " " << std::setw(5) << step_no
540 << " " << std::setw(18) << ChordEF_v.mag()
541 << " " << std::setw(18) << MomDir_dot_Norm
542 << " " << std::setw(18) << MomDir_dot_ABchord
543 << " " << std::setw(12) << ABchord_length
544 << " " << ChordEF_v
545 << G4endl;
546 outStream // G4cout
547 << " MomentumDir= " << " " << NewMomentumDir
548 << " Normal at Entry E= " << NormalAtEntry
549 << " AB chord = " << ChordAB_v
550 << G4endl;
551 G4cout << outStream.str(); // ostr_verbose;
552
553 if( ( std::fabs(NormalAtEntry.mag2() - 1.0) > perThousand ) )
554 {
555 G4cerr << " PROBLEM in G4VIntersectionLocator::ReportTrialStep " << G4endl
556 << " Normal is not unit - mag=" << NormalAtEntry.mag()
557 << " ValidNormalAtE = " << validNormal
558 << G4endl;
559 }
560 return;
561}
@ JustWarning
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
double z() const
double x() const
double mag2() const
double y() const
double dot(const Hep3Vector &) const
double mag() const
G4ThreeVector NetTranslation() const
G4RotationMatrix NetRotation() const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
G4MagInt_Driver * GetIntegrationDriver()
const G4ThreeVector & GetMomentumDir() const
G4double GetCurveLength() const
G4ThreeVector GetPosition() const
G4ThreeVector GetMomentum() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4VSolid * GetSolid() const
G4bool AccurateAdvance(G4FieldTrack &y_current, G4double hstep, G4double eps, G4double hinitial=0.0)
const G4AffineTransform & GetTopTransform() const
G4TouchableHistory * CreateTouchableHistory() const
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
Definition: G4Navigator.cc:548
virtual G4ThreeVector GetGlobalExitNormal(const G4ThreeVector &point, G4bool *valid)
const G4AffineTransform GetLocalToGlobalTransform() const
void SetWorldVolume(G4VPhysicalVolume *pWorld)
virtual G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=0, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true)
Definition: G4Navigator.cc:116
const G4NavigationHistory * GetHistory() const
G4ThreeVector GetGlobalSurfaceNormal(const G4ThreeVector &CurrentE_Point, G4bool &validNormal)
G4Navigator * GetNavigatorFor()
G4ChordFinder * GetChordFinderFor()
G4VIntersectionLocator(G4Navigator *theNavigator)
G4TouchableHistory * fpTouchable
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=0)
G4double GetEpsilonStepFor()
G4FieldTrack ReEstimateEndpoint(const G4FieldTrack &CurrentStateA, const G4FieldTrack &EstimtdEndStateB, G4double linearDistSq, G4double curveDist)
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)
void printStatus(const G4FieldTrack &startFT, const G4FieldTrack &currentFT, G4double requestStep, G4double safety, G4int step)
G4LogicalVolume * GetLogicalVolume() const
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
@ kSurface
Definition: geomdefs.hh:58
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41