Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4RegularNavigation.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 G4RegularNavigation implementation
27//
28// Author: Pedro Arce, May 2007
29//
30// --------------------------------------------------------------------
31
33#include "G4TouchableHistory.hh"
35#include "G4Material.hh"
36#include "G4NormalNavigation.hh"
37#include "G4Navigator.hh"
40
41//------------------------------------------------------------------
43{
45 fMinStep = 101*kCarTolerance;
46}
47
48
49//------------------------------------------------------------------
51
52
53//------------------------------------------------------------------
55 ComputeStep(const G4ThreeVector& localPoint,
56 const G4ThreeVector& localDirection,
57 const G4double currentProposedStepLength,
58 G4double& newSafety,
59 G4NavigationHistory& history,
60 G4bool& validExitNormal,
61 G4ThreeVector& exitNormal,
62 G4bool& exiting,
63 G4bool& entering,
64 G4VPhysicalVolume *(*pBlockedPhysical),
65 G4int& blockedReplicaNo)
66{
67 // This method is never called because to be called the daughter has to be
68 // a regular structure. This would only happen if the track is in the mother
69 // of voxels volume. But the voxels fill completely their mother, so when a
70 // track enters the mother it automatically enters a voxel. Only precision
71 // problems would make this method to be called
72
73 G4ThreeVector globalPoint =
74 history.GetTopTransform().InverseTransformPoint(localPoint);
75 G4ThreeVector globalDirection =
76 history.GetTopTransform().InverseTransformAxis(localDirection);
77
78 G4ThreeVector localPoint2 = localPoint; // take away constantness
79
80 LevelLocate( history, *pBlockedPhysical, blockedReplicaNo,
81 globalPoint, &globalDirection, true, localPoint2 );
82
83
84 // Get in which voxel it is
85 //
86 G4VPhysicalVolume *motherPhysical, *daughterPhysical;
87 G4LogicalVolume *motherLogical;
88 motherPhysical = history.GetTopVolume();
89 motherLogical = motherPhysical->GetLogicalVolume();
90 daughterPhysical = motherLogical->GetDaughter(0);
91
92 auto daughterParam =
93 (G4PhantomParameterisation*)(daughterPhysical->GetParameterisation());
94 G4int copyNo = daughterParam ->GetReplicaNo(localPoint,localDirection);
95
96 G4ThreeVector voxelTranslation = daughterParam->GetTranslation( copyNo );
97 G4ThreeVector daughterPoint = localPoint - voxelTranslation;
98
99
100 // Compute step in voxel
101 //
102 return fnormalNav->ComputeStep(daughterPoint,
103 localDirection,
104 currentProposedStepLength,
105 newSafety,
106 history,
107 validExitNormal,
108 exitNormal,
109 exiting,
110 entering,
111 pBlockedPhysical,
112 blockedReplicaNo);
113}
114
115
116//------------------------------------------------------------------
118 G4ThreeVector& localPoint,
119 const G4ThreeVector& localDirection,
120 const G4double currentProposedStepLength,
121 G4double& newSafety,
122 G4NavigationHistory& history,
123 G4bool& validExitNormal,
124 G4ThreeVector& exitNormal,
125 G4bool& exiting,
126 G4bool& entering,
127 G4VPhysicalVolume *(*pBlockedPhysical),
128 G4int& blockedReplicaNo,
129 G4VPhysicalVolume* pCurrentPhysical)
130{
132
133 auto param =
134 (G4PhantomParameterisation*)(pCurrentPhysical->GetParameterisation());
135
136 if( !param->SkipEqualMaterials() )
137 {
138 return fnormalNav->ComputeStep(localPoint,
139 localDirection,
140 currentProposedStepLength,
141 newSafety,
142 history,
143 validExitNormal,
144 exitNormal,
145 exiting,
146 entering,
147 pBlockedPhysical,
148 blockedReplicaNo);
149 }
150
151
152 G4double ourStep = 0.;
153
154 // To get replica No: transform local point to the reference system of the
155 // param container volume
156 //
157 auto ide = (G4int)history.GetDepth();
158 G4ThreeVector containerPoint = history.GetTransform(ide)
159 .InverseTransformPoint(localPoint);
160
161 // Point in global frame
162 //
163 containerPoint = history.GetTransform(ide).InverseTransformPoint(localPoint);
164
165 // Point in voxel parent volume frame
166 //
167 containerPoint = history.GetTransform(ide-1).TransformPoint(containerPoint);
168
169 // Store previous voxel translation to move localPoint by the difference
170 // with the new one
171 //
172 G4ThreeVector prevVoxelTranslation = containerPoint - localPoint;
173
174 // Do not use the expression below: There are cases where the
175 // fLastLocatedPointLocal does not give the correct answer
176 // (particle reaching a wall and bounced back, particle travelling through
177 // the wall that is deviated in an step, ...; these are pathological cases
178 // that give wrong answers in G4PhantomParameterisation::GetReplicaNo()
179 //
180 // G4ThreeVector prevVoxelTranslation = param->GetTranslation( copyNo );
181
182 G4int copyNo = param->GetReplicaNo(containerPoint,localDirection);
183
184 G4Material* currentMate = param->ComputeMaterial( copyNo, nullptr, nullptr );
185 G4VSolid* voxelBox = pCurrentPhysical->GetLogicalVolume()->GetSolid();
186
187 G4VSolid* containerSolid = param->GetContainerSolid();
188 G4Material* nextMate;
189 G4bool bFirstStep = true;
190 G4double newStep;
191 G4double totalNewStep = 0.;
192
193 // Loop while same material is found
194 //
195 //
196 fNumberZeroSteps = 0;
197 for( G4int ii = 0; ii < fNoStepsAllowed+1; ++ii )
198 {
199 if( ii == fNoStepsAllowed ) {
200 // Must kill this stuck track
201 //
202 G4ThreeVector pGlobalpoint = history.GetTransform(ide)
203 .InverseTransformPoint(localPoint);
204 std::ostringstream message;
205 message << "G4RegularNavigation::ComputeStepSkippingEqualMaterials()"
206 << "Stuck Track: potential geometry or navigation problem."
207 << G4endl
208 << " Track stuck, moving for more than "
209 << ii << " steps" << G4endl
210 << "- at point " << pGlobalpoint << G4endl
211 << " local direction: " << localDirection << G4endl;
212 G4Exception("G4RegularNavigation::ComputeStepSkippingEqualMaterials()",
213 "GeomRegNav1001",
215 message);
216 }
217 newStep = voxelBox->DistanceToOut( localPoint, localDirection );
218 fLastStepWasZero = (newStep<fMinStep);
219 if( fLastStepWasZero )
220 {
221 ++fNumberZeroSteps;
222#ifdef G4DEBUG_NAVIGATION
223 if( fNumberZeroSteps > 1 )
224 {
225 G4ThreeVector pGlobalpoint = history.GetTransform(ide)
226 .InverseTransformPoint(localPoint);
227 std::ostringstream message;
228 message.precision(16);
229 message << "G4RegularNavigation::ComputeStepSkippingEqualMaterials(): another 'zero' step, # "
230 << fNumberZeroSteps
231 << ", at " << pGlobalpoint
232 << ", nav-comp-step calls # " << ii
233 << ", Step= " << newStep;
234 G4Exception("G4RegularNavigation::ComputeStepSkippingEqualMaterials()",
235 "GeomRegNav1002", JustWarning, message,
236 "Potential overlap in geometry!");
237 }
238#endif
239 if( fNumberZeroSteps > fActionThreshold_NoZeroSteps-1 )
240 {
241 // Act to recover this stuck track. Pushing it along direction
242 //
243 newStep = std::min(101*kCarTolerance*std::pow(10,fNumberZeroSteps-2),0.1);
244#ifdef G4DEBUG_NAVIGATION
245 G4ThreeVector pGlobalpoint = history.GetTransform(ide)
246 .InverseTransformPoint(localPoint);
247 std::ostringstream message;
248 message.precision(16);
249 message << "Track stuck or not moving." << G4endl
250 << " Track stuck, not moving for "
251 << fNumberZeroSteps << " steps" << G4endl
252 << "- at point " << pGlobalpoint
253 << " (local point " << localPoint << ")" << G4endl
254 << " local direction: " << localDirection
255 << " Potential geometry or navigation problem !"
256 << G4endl
257 << " Trying pushing it of " << newStep << " mm ...";
258 G4Exception("G4RegularNavigation::ComputeStepSkippingEqualMaterials()",
259 "GeomRegNav1003", JustWarning, message,
260 "Potential overlap in geometry!");
261#endif
262 }
263 if( fNumberZeroSteps > fAbandonThreshold_NoZeroSteps-1 )
264 {
265 // Must kill this stuck track
266 //
267 G4ThreeVector pGlobalpoint = history.GetTransform(ide)
268 .InverseTransformPoint(localPoint);
269 std::ostringstream message;
270 message << "G4RegularNavigation::ComputeStepSkippingEqualMaterials()"
271 << "Stuck Track: potential geometry or navigation problem."
272 << G4endl
273 << " Track stuck, not moving for "
274 << fNumberZeroSteps << " steps" << G4endl
275 << "- at point " << pGlobalpoint << G4endl
276 << " local direction: " << localDirection << G4endl;
277 G4Exception("G4RegularNavigation::ComputeStepSkippingEqualMaterials()",
278 "GeomRegNav1004",
280 message);
281 }
282 }
283 else
284 {
285 // reset the zero step counter when a non-zero step was performed
286 fNumberZeroSteps = 0;
287 }
288 if( (bFirstStep) && (newStep < currentProposedStepLength) )
289 {
290 exiting = true;
291 }
292 bFirstStep = false;
293
294 newStep += kCarTolerance; // Avoid precision problems
295 ourStep += newStep;
296 totalNewStep += newStep;
297
298 // Physical process is limiting the step, don't continue
299 //
300 if(std::fabs(totalNewStep-currentProposedStepLength) < kCarTolerance)
301 {
302 return currentProposedStepLength;
303 }
304 if(totalNewStep > currentProposedStepLength)
305 {
307 AddStepLength(copyNo, newStep-totalNewStep+currentProposedStepLength);
308 return currentProposedStepLength;
309 }
311
312 // Move container point until wall of voxel
313 //
314 containerPoint += newStep*localDirection;
315 if( containerSolid->Inside( containerPoint ) != kInside )
316 {
317 break;
318 }
319
320 // Get copyNo and translation of new voxel
321 //
322 copyNo = param->GetReplicaNo(containerPoint, localDirection);
323 G4ThreeVector voxelTranslation = param->GetTranslation( copyNo );
324
325 // Move local point until wall of voxel and then put it in the new voxel
326 // local coordinates
327 //
328 localPoint += newStep*localDirection;
329 localPoint += prevVoxelTranslation - voxelTranslation;
330
331 prevVoxelTranslation = voxelTranslation;
332
333 // Check if material of next voxel is the same as that of the current voxel
334 nextMate = param->ComputeMaterial( copyNo, nullptr, nullptr );
335
336 if( currentMate != nextMate ) { break; }
337 }
338
339 return ourStep;
340}
341
342
343//------------------------------------------------------------------
346 const G4NavigationHistory& history,
347 const G4double pMaxLength)
348{
349 // This method is never called because to be called the daughter has to be a
350 // regular structure. This would only happen if the track is in the mother of
351 // voxels volume. But the voxels fill completely their mother, so when a
352 // track enters the mother it automatically enters a voxel. Only precision
353 // problems would make this method to be called
354
355 // Compute step in voxel
356 //
357 return fnormalNav->ComputeSafety(localPoint,
358 history,
359 pMaxLength );
360}
361
362
363//------------------------------------------------------------------
364G4bool
366 const G4VPhysicalVolume* ,
367 const G4int ,
368 const G4ThreeVector& globalPoint,
369 const G4ThreeVector* globalDirection,
370 const G4bool, // pLocatedOnEdge,
371 G4ThreeVector& localPoint )
372{
373 G4VPhysicalVolume *motherPhysical, *pPhysical;
375 G4LogicalVolume *motherLogical;
376 G4ThreeVector localDir;
377 G4int replicaNo;
378
379 motherPhysical = history.GetTopVolume();
380 motherLogical = motherPhysical->GetLogicalVolume();
381
382 pPhysical = motherLogical->GetDaughter(0);
383 pParam = (G4PhantomParameterisation*)(pPhysical->GetParameterisation());
384
385 // Save parent history in touchable history
386 // ... for use as parent t-h in ComputeMaterial method of param
387 //
388 G4TouchableHistory parentTouchable( history );
389
390 // Get local direction
391 //
392 if( globalDirection != nullptr )
393 {
394 localDir = history.GetTopTransform().TransformAxis(*globalDirection);
395 }
396 else
397 {
398 localDir = G4ThreeVector(0.,0.,0.);
399 }
400
401 // Enter this daughter
402 //
403 replicaNo = pParam->GetReplicaNo( localPoint, localDir );
404
405 if( replicaNo < 0 || replicaNo >= G4int(pParam->GetNoVoxels()) )
406 {
407 return false;
408 }
409
410 // Set the correct copy number in physical
411 //
412 pPhysical->SetCopyNo(replicaNo);
413 pParam->ComputeTransformation(replicaNo,pPhysical);
414
415 history.NewLevel(pPhysical, kParameterised, replicaNo );
416 localPoint = history.GetTopTransform().TransformPoint(globalPoint);
417
418 // Set the correct solid and material in Logical Volume
419 //
420 G4LogicalVolume *pLogical = pPhysical->GetLogicalVolume();
421
422 pLogical->UpdateMaterial(pParam->ComputeMaterial(replicaNo,
423 pPhysical, &parentTouchable) );
424 return true;
425}
@ JustWarning
@ EventMustBeAborted
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4ThreeVector InverseTransformAxis(const G4ThreeVector &axis) const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
G4ThreeVector InverseTransformPoint(const G4ThreeVector &vec) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4VSolid * GetSolid() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
void UpdateMaterial(G4Material *pMaterial)
void NewLevel(G4VPhysicalVolume *pNewMother, EVolume vType=kNormal, G4int nReplica=-1)
const G4AffineTransform & GetTopTransform() const
std::size_t GetDepth() const
G4VPhysicalVolume * GetTopVolume() const
const G4AffineTransform & GetTransform(G4int n) const
G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX) final
G4double ComputeStep(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo) final
virtual G4int GetReplicaNo(const G4ThreeVector &localPoint, const G4ThreeVector &localDir)
G4Material * ComputeMaterial(const G4int repNo, G4VPhysicalVolume *currentVol, const G4VTouchable *parentTouch=nullptr) override
void ComputeTransformation(const G4int, G4VPhysicalVolume *) const override
std::size_t GetNoVoxels() const
static G4RegularNavigationHelper * Instance()
void AddStepLength(G4int copyNo, G4double slen)
G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo) final
G4bool LevelLocate(G4NavigationHistory &history, const G4VPhysicalVolume *blockedVol, const G4int blockedNum, const G4ThreeVector &globalPoint, const G4ThreeVector *globalDirection, const G4bool pLocatedOnEdge, G4ThreeVector &localPoint) final
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4NavigationHistory &history, const G4double pProposedMaxLength=DBL_MAX) final
G4double ComputeStepSkippingEqualMaterials(G4ThreeVector &localPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo, G4VPhysicalVolume *pCurrentPhysical)
virtual void SetCopyNo(G4int CopyNo)=0
G4LogicalVolume * GetLogicalVolume() const
virtual G4VPVParameterisation * GetParameterisation() const =0
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
@ kInside
Definition geomdefs.hh:70
@ kParameterised
Definition geomdefs.hh:86