ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4NormalNavigation.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4NormalNavigation.cc
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 G4NormalNavigation Implementation
27 //
28 // Author: P.Kent, 1996
29 //
30 // --------------------------------------------------------------------
31 
32 #include "G4NormalNavigation.hh"
33 #include "G4NavigationLogger.hh"
34 #include "G4AffineTransform.hh"
35 
36 // ********************************************************************
37 // Constructor
38 // ********************************************************************
39 //
41 {
42  fLogger = new G4NavigationLogger("G4NormalNavigation");
43 }
44 
45 // ********************************************************************
46 // Destructor
47 // ********************************************************************
48 //
50 {
51  delete fLogger;
52 }
53 
54 // ********************************************************************
55 // ComputeStep
56 // ********************************************************************
57 //
58 // On entry
59 // exitNormal, validExitNormal: for previous exited volume (daughter)
60 //
61 // On exit
62 // exitNormal, validExitNormal: for mother, if exiting it (else unchanged)
65  const G4ThreeVector& localDirection,
66  const G4double currentProposedStepLength,
67  G4double& newSafety,
69  G4bool& validExitNormal,
70  G4ThreeVector& exitNormal,
71  G4bool& exiting,
72  G4bool& entering,
73  G4VPhysicalVolume* (*pBlockedPhysical),
74  G4int& blockedReplicaNo)
75 {
76  G4VPhysicalVolume *motherPhysical, *samplePhysical,
77  *blockedExitedVol = nullptr;
78  G4LogicalVolume *motherLogical;
79  G4VSolid *motherSolid;
80  G4ThreeVector sampleDirection;
81  G4double ourStep = currentProposedStepLength, ourSafety;
82  G4double motherSafety, motherStep = DBL_MAX;
83  G4int localNoDaughters, sampleNo;
84  G4bool motherValidExitNormal = false;
85  G4ThreeVector motherExitNormal;
86 
87  motherPhysical = history.GetTopVolume();
88  motherLogical = motherPhysical->GetLogicalVolume();
89  motherSolid = motherLogical->GetSolid();
90 
91  // Compute mother safety
92  //
93  motherSafety = motherSolid->DistanceToOut(localPoint);
94  ourSafety = motherSafety; // Working isotropic safety
95 
96  localNoDaughters = motherLogical->GetNoDaughters();
97 
98 #ifdef G4VERBOSE
99  if ( fCheck && ( (localNoDaughters>0) || (ourStep < motherSafety) ) )
100  {
101  fLogger->PreComputeStepLog(motherPhysical, motherSafety, localPoint);
102  }
103 #endif
104  // Compute daughter safeties & intersections
105  //
106 
107  // Exiting normal optimisation
108  //
109  if ( exiting && validExitNormal )
110  {
111  if ( localDirection.dot(exitNormal)>=kMinExitingNormalCosine )
112  {
113  // Block exited daughter volume
114  //
115  blockedExitedVol = (*pBlockedPhysical);
116  ourSafety = 0;
117  }
118  }
119  exiting = false;
120  entering = false;
121 
122 #ifdef G4VERBOSE
123  if ( fCheck )
124  {
125  // Compute early:
126  // a) to check whether point is (wrongly) outside
127  // (signaled if step < 0 or step == kInfinity )
128  // b) to check value against answer of daughters!
129 
130  motherStep = motherSolid->DistanceToOut(localPoint,
131  localDirection,
132  true,
133  &motherValidExitNormal,
134  &motherExitNormal);
135 
136  if( (motherStep >= kInfinity) || (motherStep < 0.0) )
137  {
138  // Error - indication of being outside solid !!
139  fLogger->ReportOutsideMother(localPoint, localDirection, motherPhysical);
140 
141  ourStep = motherStep = 0.0;
142 
143  exiting = true;
144  entering = false;
145 
146  // If we are outside the solid does the normal make sense?
147  validExitNormal = motherValidExitNormal;
148  exitNormal = motherExitNormal;
149 
150  *pBlockedPhysical = nullptr; // or motherPhysical ?
151  blockedReplicaNo = 0; // or motherReplicaNumber ?
152 
153  newSafety = 0.0;
154  return ourStep;
155  }
156  }
157 #endif
158 
159  for ( sampleNo=localNoDaughters-1; sampleNo>=0; sampleNo--)
160  {
161  samplePhysical = motherLogical->GetDaughter(sampleNo);
162  if ( samplePhysical!=blockedExitedVol )
163  {
164  G4AffineTransform sampleTf(samplePhysical->GetRotation(),
165  samplePhysical->GetTranslation());
166  sampleTf.Invert();
167  const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint);
168  const G4VSolid *sampleSolid =
169  samplePhysical->GetLogicalVolume()->GetSolid();
170  const G4double sampleSafety =
171  sampleSolid->DistanceToIn(samplePoint);
172 
173  if ( sampleSafety<ourSafety )
174  {
175  ourSafety=sampleSafety;
176  }
177 
178  if ( sampleSafety<=ourStep )
179  {
180  sampleDirection = sampleTf.TransformAxis(localDirection);
181  const G4double sampleStep =
182  sampleSolid->DistanceToIn(samplePoint,sampleDirection);
183 #ifdef G4VERBOSE
184  if( fCheck )
185  {
186  fLogger->PrintDaughterLog(sampleSolid, samplePoint,
187  sampleSafety, true,
188  sampleDirection, sampleStep);
189  }
190 #endif
191  if ( sampleStep<=ourStep )
192  {
193  ourStep = sampleStep;
194  entering = true;
195  exiting = false;
196  *pBlockedPhysical = samplePhysical;
197  blockedReplicaNo = -1;
198 #ifdef G4VERBOSE
199  if( fCheck )
200  {
201  fLogger->AlongComputeStepLog(sampleSolid, samplePoint,
202  sampleDirection, localDirection,
203  sampleSafety, sampleStep);
204  }
205 #endif
206  }
207 
208 #ifdef G4VERBOSE
209  if( fCheck && (sampleStep < kInfinity) && (sampleStep >= motherStep) )
210  {
211  // The intersection point with the daughter is at or after the exit
212  // point from the mother volume. Double check!
213  fLogger->CheckDaughterEntryPoint(sampleSolid,
214  samplePoint, sampleDirection,
215  motherSolid,
216  localPoint, localDirection,
217  motherStep, sampleStep);
218  }
219 #endif
220  } // end of if ( sampleSafety <= ourStep )
221 #ifdef G4VERBOSE
222  else if ( fCheck )
223  {
224  fLogger->PrintDaughterLog(sampleSolid, samplePoint,
225  sampleSafety, false,
226  G4ThreeVector(0.,0.,0.), -1.0 );
227  }
228 #endif
229  }
230  }
231  if ( currentProposedStepLength<ourSafety )
232  {
233  // Guaranteed physics limited
234  //
235  entering = false;
236  exiting = false;
237  *pBlockedPhysical = nullptr;
238  ourStep = kInfinity;
239  }
240  else
241  {
242  // Consider intersection with mother solid
243  //
244  if ( motherSafety<=ourStep )
245  {
246  if ( !fCheck ) // The call is moved above when running in check_mode
247  {
248  motherStep = motherSolid->DistanceToOut(localPoint,
249  localDirection,
250  true,
251  &motherValidExitNormal,
252  &motherExitNormal);
253  }
254 #ifdef G4VERBOSE
255  else // check_mode
256  {
257  fLogger->PostComputeStepLog(motherSolid, localPoint, localDirection,
258  motherStep, motherSafety);
259  if( motherValidExitNormal )
260  {
261  fLogger->CheckAndReportBadNormal(motherExitNormal,
262  localPoint,
263  localDirection,
264  motherStep,
265  motherSolid,
266  "From motherSolid::DistanceToOut" );
267  }
268  }
269 #endif
270 
271  if( (motherStep >= kInfinity) || (motherStep < 0.0) )
272  {
273 #ifdef G4VERBOSE
274  if( fCheck ) // Clearly outside the mother solid!
275  {
276  fLogger->ReportOutsideMother(localPoint, localDirection,
277  motherPhysical);
278  }
279 #endif
280  ourStep = motherStep = 0.0;
281  exiting = true;
282  entering = false;
283  // validExitNormal= motherValidExitNormal;
284  // exitNormal= motherExitNormal;
285  // The normal could be useful - but only if near the mother
286  // But it could be unreliable!
287  validExitNormal = false;
288  *pBlockedPhysical = nullptr; // or motherPhysical ?
289  blockedReplicaNo = 0; // or motherReplicaNumber ?
290  newSafety= 0.0;
291  return ourStep;
292  }
293 
294  if ( motherStep<=ourStep )
295  {
296  ourStep = motherStep;
297  exiting = true;
298  entering = false;
299  validExitNormal = motherValidExitNormal;
300  exitNormal = motherExitNormal;
301 
302  if ( motherValidExitNormal )
303  {
304  const G4RotationMatrix *rot = motherPhysical->GetRotation();
305  if (rot)
306  {
307  exitNormal *= rot->inverse();
308 #ifdef G4VERBOSE
309  if( fCheck )
310  fLogger->CheckAndReportBadNormal(exitNormal, // rotated
311  motherExitNormal, // original
312  *rot,
313  "From RotationMatrix" );
314 #endif
315  }
316  }
317  }
318  else
319  {
320  validExitNormal = false;
321  }
322  }
323  }
324  newSafety = ourSafety;
325  return ourStep;
326 }
327 
328 // ********************************************************************
329 // ComputeSafety
330 // ********************************************************************
331 //
333  const G4NavigationHistory& history,
334  const G4double)
335 {
336  G4VPhysicalVolume *motherPhysical, *samplePhysical;
337  G4LogicalVolume *motherLogical;
338  G4VSolid *motherSolid;
339  G4double motherSafety, ourSafety;
340  G4int localNoDaughters, sampleNo;
341 
342  motherPhysical = history.GetTopVolume();
343  motherLogical = motherPhysical->GetLogicalVolume();
344  motherSolid = motherLogical->GetSolid();
345 
346  // Compute mother safety
347  //
348  motherSafety = motherSolid->DistanceToOut(localPoint);
349  ourSafety = motherSafety; // Working isotropic safety
350 
351 #ifdef G4VERBOSE
352  if( fCheck )
353  {
354  fLogger->ComputeSafetyLog(motherSolid,localPoint,motherSafety,true,true);
355  }
356 #endif
357 
358  // Compute daughter safeties
359  //
360  localNoDaughters = motherLogical->GetNoDaughters();
361  for ( sampleNo=localNoDaughters-1; sampleNo>=0; sampleNo-- )
362  {
363  samplePhysical = motherLogical->GetDaughter(sampleNo);
364  G4AffineTransform sampleTf(samplePhysical->GetRotation(),
365  samplePhysical->GetTranslation());
366  sampleTf.Invert();
367  const G4ThreeVector samplePoint =
368  sampleTf.TransformPoint(localPoint);
369  const G4VSolid *sampleSolid =
370  samplePhysical->GetLogicalVolume()->GetSolid();
371  const G4double sampleSafety =
372  sampleSolid->DistanceToIn(samplePoint);
373  if ( sampleSafety<ourSafety )
374  {
375  ourSafety = sampleSafety;
376  }
377 #ifdef G4VERBOSE
378  if(fCheck)
379  {
380  fLogger->ComputeSafetyLog(sampleSolid, samplePoint,
381  sampleSafety, false, false);
382  // Not mother, no banner
383  }
384 #endif
385  }
386  return ourSafety;
387 }
388 
389 // The following methods have been imported to this source file
390 // in order to avoid dependency of the header file on the
391 // header implementation of G4NavigationLogger.
392 
393 // ********************************************************************
394 // GetVerboseLevel
395 // ********************************************************************
396 //
398 {
399  return fLogger->GetVerboseLevel();
400 }
401 
402 // ********************************************************************
403 // SetVerboseLevel
404 // ********************************************************************
405 //
407 {
408  fLogger->SetVerboseLevel(level);
409 }