Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Transportation.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//
27// $Id: G4Transportation.cc 2011/06/10 16:19:46 japost Exp japost $
28// GEANT4 tag $Name: not supported by cvs2svn $
29//
30// ------------------------------------------------------------
31// GEANT 4 include file implementation
32//
33// ------------------------------------------------------------
34//
35// This class is a process responsible for the transportation of
36// a particle, ie the geometrical propagation that encounters the
37// geometrical sub-volumes of the detectors.
38//
39// It is also tasked with the key role of proposing the "isotropic safety",
40// which will be used to update the post-step point's safety.
41//
42// =======================================================================
43// Modified:
44// 28 Oct 2011, P.Gumpl./J.Ap: Detect gravity field, use magnetic moment
45// 20 Nov 2008, J.Apostolakis: Push safety to helper - after ComputeSafety
46// 9 Nov 2007, J.Apostolakis: Flag for short steps, push safety to helper
47// 19 Jan 2006, P.MoraDeFreitas: Fix for suspended tracks (StartTracking)
48// 11 Aug 2004, M.Asai: Add G4VSensitiveDetector* for updating stepPoint.
49// 21 June 2003, J.Apostolakis: Calling field manager with
50// track, to enable it to configure its accuracy
51// 13 May 2003, J.Apostolakis: Zero field areas now taken into
52// account correclty in all cases (thanks to W Pokorski).
53// 29 June 2001, J.Apostolakis, D.Cote-Ahern, P.Gumplinger:
54// correction for spin tracking
55// 20 Febr 2001, J.Apostolakis: update for new FieldTrack
56// 22 Sept 2000, V.Grichine: update of Kinetic Energy
57// Created: 19 March 1997, J. Apostolakis
58// =======================================================================
59
60#include "G4Transportation.hh"
62
64#include "G4SystemOfUnits.hh"
66#include "G4ParticleTable.hh"
67#include "G4ChordFinder.hh"
68#include "G4SafetyHelper.hh"
70
72
73//////////////////////////////////////////////////////////////////////////
74//
75// Constructor
76
78 : G4VProcess( G4String("Transportation"), fTransportation ),
79 fTransportEndPosition( 0.0, 0.0, 0.0 ),
80 fTransportEndMomentumDir( 0.0, 0.0, 0.0 ),
81 fTransportEndKineticEnergy( 0.0 ),
82 fTransportEndSpin( 0.0, 0.0, 0.0 ),
83 fMomentumChanged(true),
84 fEnergyChanged(false),
85 fEndGlobalTimeComputed(false),
86 fCandidateEndGlobalTime(0.0),
87 fParticleIsLooping( false ),
88 fGeometryLimitedStep(true),
89 fPreviousSftOrigin( 0.,0.,0. ),
90 fPreviousSafety( 0.0 ),
91 // fParticleChange(),
92 fEndPointDistance( -1.0 ),
93 fThreshold_Warning_Energy( 100 * MeV ),
94 fThreshold_Important_Energy( 250 * MeV ),
95 fThresholdTrials( 10 ),
96 fUnimportant_Energy( 1 * MeV ), // Not used
97 fNoLooperTrials( 0 ),
98 fSumEnergyKilled( 0.0 ), fMaxEnergyKilled( 0.0 ),
99 fShortStepOptimisation( false ), // Old default: true (=fast short steps)
100 fUseMagneticMoment( false ),
101 fVerboseLevel( verbosity )
102{
103 // set Process Sub Type
104 SetProcessSubType(static_cast<int>(TRANSPORTATION));
105
106 G4TransportationManager* transportMgr ;
107
109
110 fLinearNavigator = transportMgr->GetNavigatorForTracking() ;
111
112 fFieldPropagator = transportMgr->GetPropagatorInField() ;
113
114 fpSafetyHelper = transportMgr->GetSafetyHelper(); // New
115
116 // Cannot determine whether a field exists here, as it would
117 // depend on the relative order of creating the detector's
118 // field and this process. That order is not guaranted.
119 // Instead later the method DoesGlobalFieldExist() is called
120
121 static G4TouchableHandle nullTouchableHandle; // Points to (G4VTouchable*) 0
122 fCurrentTouchableHandle = nullTouchableHandle;
123
124
125#ifdef G4VERBOSE
126 if( fVerboseLevel > 0)
127 {
128 G4cout << " G4Transportation constructor> set fShortStepOptimisation to ";
129 if ( fShortStepOptimisation ) G4cout << "true" << G4endl;
130 else G4cout << "false" << G4endl;
131 }
132#endif
133}
134
135//////////////////////////////////////////////////////////////////////////
136
138{
139 if( (fVerboseLevel > 0) && (fSumEnergyKilled > 0.0 ) ){
140 G4cout << " G4Transportation: Statistics for looping particles " << G4endl;
141 G4cout << " Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
142 G4cout << " Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
143 }
144}
145
146//////////////////////////////////////////////////////////////////////////
147//
148// Responsibilities:
149// Find whether the geometry limits the Step, and to what length
150// Calculate the new value of the safety and return it.
151// Store the final time, position and momentum.
152
155 G4double, // previousStepSize
156 G4double currentMinimumStep,
157 G4double& currentSafety,
158 G4GPILSelection* selection )
159{
160 G4double geometryStepLength= -1.0, newSafety= -1.0;
161 fParticleIsLooping = false ;
162
163 // Initial actions moved to StartTrack()
164 // --------------------------------------
165 // Note: in case another process changes touchable handle
166 // it will be necessary to add here (for all steps)
167 // fCurrentTouchableHandle = aTrack->GetTouchableHandle();
168
169 // GPILSelection is set to defaule value of CandidateForSelection
170 // It is a return value
171 //
172 *selection = CandidateForSelection ;
173
174 // Get initial Energy/Momentum of the track
175 //
176 const G4DynamicParticle* pParticle = track.GetDynamicParticle() ;
177 const G4ParticleDefinition* pParticleDef = pParticle->GetDefinition() ;
178 G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection() ;
179 G4ThreeVector startPosition = track.GetPosition() ;
180
181 // G4double theTime = track.GetGlobalTime() ;
182
183 // The Step Point safety can be limited by other geometries and/or the
184 // assumptions of any process - it's not always the geometrical safety.
185 // We calculate the starting point's isotropic safety here.
186 //
187 G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin ;
188 G4double MagSqShift = OriginShift.mag2() ;
189 if( MagSqShift >= sqr(fPreviousSafety) )
190 {
191 currentSafety = 0.0 ;
192 }
193 else
194 {
195 currentSafety = fPreviousSafety - std::sqrt(MagSqShift) ;
196 }
197
198 // Is the particle charged or has it a magnetic moment?
199 //
200 G4double particleCharge = pParticle->GetCharge() ;
201 G4double magneticMoment = pParticle->GetMagneticMoment() ;
202 G4double restMass = pParticleDef->GetPDGMass() ;
203
204 fGeometryLimitedStep = false ;
205 // fEndGlobalTimeComputed = false ;
206
207 // There is no need to locate the current volume. It is Done elsewhere:
208 // On track construction
209 // By the tracking, after all AlongStepDoIts, in "Relocation"
210
211 // Check if the particle has a force, EM or gravitational, exerted on it
212 //
213 G4FieldManager* fieldMgr=0;
214 G4bool fieldExertsForce = false ;
215
216 G4bool gravityOn = false;
217 G4bool fieldExists= false; // Field is not 0 (null pointer)
218
219 fieldMgr = fFieldPropagator->FindAndSetFieldManager( track.GetVolume() );
220 if( fieldMgr != 0 )
221 {
222 // Message the field Manager, to configure it for this track
223 fieldMgr->ConfigureForTrack( &track );
224 // Is here to allow a transition from no-field pointer
225 // to finite field (non-zero pointer).
226
227 // If the field manager has no field ptr, the field is zero
228 // by definition ( = there is no field ! )
229 const G4Field* ptrField= fieldMgr->GetDetectorField();
230 fieldExists = (ptrField!=0) ;
231 if( fieldExists )
232 {
233 gravityOn= ptrField->IsGravityActive();
234
235 if( (particleCharge != 0.0)
236 || (fUseMagneticMoment && (magneticMoment != 0.0) )
237 || (gravityOn && (restMass != 0.0) )
238 )
239 {
240 fieldExertsForce = fieldExists;
241 }
242 }
243 }
244 // G4cout << " G4Transport: field exerts force= " << fieldExertsForce
245 // << " fieldMgr= " << fieldMgr << G4endl;
246
247 if( !fieldExertsForce )
248 {
249 G4double linearStepLength ;
250 if( fShortStepOptimisation && (currentMinimumStep <= currentSafety) )
251 {
252 // The Step is guaranteed to be taken
253 //
254 geometryStepLength = currentMinimumStep ;
255 fGeometryLimitedStep = false ;
256 }
257 else
258 {
259 // Find whether the straight path intersects a volume
260 //
261 linearStepLength = fLinearNavigator->ComputeStep( startPosition,
262 startMomentumDir,
263 currentMinimumStep,
264 newSafety) ;
265 // Remember last safety origin & value.
266 //
267 fPreviousSftOrigin = startPosition ;
268 fPreviousSafety = newSafety ;
269 fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
270
271 currentSafety = newSafety ;
272
273 fGeometryLimitedStep= (linearStepLength <= currentMinimumStep);
274 if( fGeometryLimitedStep )
275 {
276 // The geometry limits the Step size (an intersection was found.)
277 geometryStepLength = linearStepLength ;
278 }
279 else
280 {
281 // The full Step is taken.
282 geometryStepLength = currentMinimumStep ;
283 }
284 }
285 fEndPointDistance = geometryStepLength ;
286
287 // Calculate final position
288 //
289 fTransportEndPosition = startPosition+geometryStepLength*startMomentumDir ;
290
291 // Momentum direction, energy and polarisation are unchanged by transport
292 //
293 fTransportEndMomentumDir = startMomentumDir ;
294 fTransportEndKineticEnergy = track.GetKineticEnergy() ;
295 fTransportEndSpin = track.GetPolarization();
296 fParticleIsLooping = false ;
297 fMomentumChanged = false ;
298 fEndGlobalTimeComputed = false ;
299 }
300 else // A field exerts force
301 {
302 G4double momentumMagnitude = pParticle->GetTotalMomentum() ;
303 G4ThreeVector EndUnitMomentum ;
304 G4double lengthAlongCurve ;
305
306 fFieldPropagator->SetChargeMomentumMass( particleCharge, // in e+ units
307 momentumMagnitude, // in Mev/c
308 restMass ) ;
309
310 G4ThreeVector spin = track.GetPolarization() ;
311 G4FieldTrack aFieldTrack = G4FieldTrack( startPosition,
312 track.GetMomentumDirection(),
313 0.0,
314 track.GetKineticEnergy(),
315 restMass,
316 track.GetVelocity(),
317 track.GetGlobalTime(), // Lab.
318 track.GetProperTime(), // Part.
319 &spin ) ;
320 if( currentMinimumStep > 0 )
321 {
322 // Do the Transport in the field (non recti-linear)
323 //
324 lengthAlongCurve = fFieldPropagator->ComputeStep( aFieldTrack,
325 currentMinimumStep,
326 currentSafety,
327 track.GetVolume() ) ;
328 fGeometryLimitedStep= lengthAlongCurve < currentMinimumStep;
329 if( fGeometryLimitedStep ) {
330 geometryStepLength = lengthAlongCurve ;
331 } else {
332 geometryStepLength = currentMinimumStep ;
333 }
334
335 // Remember last safety origin & value.
336 //
337 fPreviousSftOrigin = startPosition ;
338 fPreviousSafety = currentSafety ;
339 fpSafetyHelper->SetCurrentSafety( currentSafety, startPosition);
340 }
341 else
342 {
343 geometryStepLength = lengthAlongCurve= 0.0 ;
344 fGeometryLimitedStep = false ;
345 }
346
347 // Get the End-Position and End-Momentum (Dir-ection)
348 //
349 fTransportEndPosition = aFieldTrack.GetPosition() ;
350
351 // Momentum: Magnitude and direction can be changed too now ...
352 //
353 fMomentumChanged = true ;
354 fTransportEndMomentumDir = aFieldTrack.GetMomentumDir() ;
355
356 fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy() ;
357
358 if( fFieldPropagator->GetCurrentFieldManager()->DoesFieldChangeEnergy() )
359 {
360 // If the field can change energy, then the time must be integrated
361 // - so this should have been updated
362 //
363 fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
364 fEndGlobalTimeComputed = true;
365
366 // was ( fCandidateEndGlobalTime != track.GetGlobalTime() );
367 // a cleaner way is to have FieldTrack knowing whether time is updated.
368 }
369 else
370 {
371 // The energy should be unchanged by field transport,
372 // - so the time changed will be calculated elsewhere
373 //
374 fEndGlobalTimeComputed = false;
375
376 // Check that the integration preserved the energy
377 // - and if not correct this!
378 G4double startEnergy= track.GetKineticEnergy();
379 G4double endEnergy= fTransportEndKineticEnergy;
380
381 static G4int no_inexact_steps=0, no_large_ediff;
382 G4double absEdiff = std::fabs(startEnergy- endEnergy);
383 if( absEdiff > perMillion * endEnergy )
384 {
385 no_inexact_steps++;
386 // Possible statistics keeping here ...
387 }
388 if( fVerboseLevel > 1 )
389 {
390 if( std::fabs(startEnergy- endEnergy) > perThousand * endEnergy )
391 {
392 static G4int no_warnings= 0, warnModulo=1, moduloFactor= 10;
393 no_large_ediff ++;
394 if( (no_large_ediff% warnModulo) == 0 )
395 {
396 no_warnings++;
397 G4cout << "WARNING - G4Transportation::AlongStepGetPIL() "
398 << " Energy change in Step is above 1^-3 relative value. " << G4endl
399 << " Relative change in 'tracking' step = "
400 << std::setw(15) << (endEnergy-startEnergy)/startEnergy << G4endl
401 << " Starting E= " << std::setw(12) << startEnergy / MeV << " MeV " << G4endl
402 << " Ending E= " << std::setw(12) << endEnergy / MeV << " MeV " << G4endl;
403 G4cout << " Energy has been corrected -- however, review"
404 << " field propagation parameters for accuracy." << G4endl;
405 if( (fVerboseLevel > 2 ) || (no_warnings<4) || (no_large_ediff == warnModulo * moduloFactor) ){
406 G4cout << " These include EpsilonStepMax(/Min) in G4FieldManager "
407 << " which determine fractional error per step for integrated quantities. " << G4endl
408 << " Note also the influence of the permitted number of integration steps."
409 << G4endl;
410 }
411 G4cerr << "ERROR - G4Transportation::AlongStepGetPIL()" << G4endl
412 << " Bad 'endpoint'. Energy change detected"
413 << " and corrected. "
414 << " Has occurred already "
415 << no_large_ediff << " times." << G4endl;
416 if( no_large_ediff == warnModulo * moduloFactor )
417 {
418 warnModulo *= moduloFactor;
419 }
420 }
421 }
422 } // end of if (fVerboseLevel)
423
424 // Correct the energy for fields that conserve it
425 // This - hides the integration error
426 // - but gives a better physical answer
427 fTransportEndKineticEnergy= track.GetKineticEnergy();
428 }
429
430 fTransportEndSpin = aFieldTrack.GetSpin();
431 fParticleIsLooping = fFieldPropagator->IsParticleLooping() ;
432 fEndPointDistance = (fTransportEndPosition - startPosition).mag() ;
433 }
434
435 // If we are asked to go a step length of 0, and we are on a boundary
436 // then a boundary will also limit the step -> we must flag this.
437 //
438 if( currentMinimumStep == 0.0 )
439 {
440 if( currentSafety == 0.0 ) fGeometryLimitedStep = true ;
441 }
442
443 // Update the safety starting from the end-point,
444 // if it will become negative at the end-point.
445 //
446 if( currentSafety < fEndPointDistance )
447 {
448 if( particleCharge != 0.0 )
449 {
450 G4double endSafety =
451 fLinearNavigator->ComputeSafety( fTransportEndPosition) ;
452 currentSafety = endSafety ;
453 fPreviousSftOrigin = fTransportEndPosition ;
454 fPreviousSafety = currentSafety ;
455 fpSafetyHelper->SetCurrentSafety( currentSafety, fTransportEndPosition);
456
457 // Because the Stepping Manager assumes it is from the start point,
458 // add the StepLength
459 //
460 currentSafety += fEndPointDistance ;
461
462#ifdef G4DEBUG_TRANSPORT
463 G4cout.precision(12) ;
464 G4cout << "***G4Transportation::AlongStepGPIL ** " << G4endl ;
465 G4cout << " Called Navigator->ComputeSafety at " << fTransportEndPosition
466 << " and it returned safety= " << endSafety << G4endl ;
467 G4cout << " Adding endpoint distance " << fEndPointDistance
468 << " to obtain pseudo-safety= " << currentSafety << G4endl ;
469 }else{
470 G4cout << "***G4Transportation::AlongStepGPIL ** " << G4endl ;
471 G4cout << " Avoiding call to ComputeSafety : " << G4endl;
472 G4cout << " charge = " << particleCharge << G4endl;
473 G4cout << " mag moment = " << magneticMoment << G4endl;
474#endif
475 }
476 }
477
478 fParticleChange.ProposeTrueStepLength(geometryStepLength) ;
479
480 return geometryStepLength ;
481}
482
483//////////////////////////////////////////////////////////////////////////
484//
485// Initialize ParticleChange (by setting all its members equal
486// to corresponding members in G4Track)
487
489 const G4Step& stepData )
490{
491 static G4int noCalls=0;
492 noCalls++;
493
494 fParticleChange.Initialize(track) ;
495
496 // Code for specific process
497 //
498 fParticleChange.ProposePosition(fTransportEndPosition) ;
499 fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir) ;
500 fParticleChange.ProposeEnergy(fTransportEndKineticEnergy) ;
501 fParticleChange.SetMomentumChanged(fMomentumChanged) ;
502
503 fParticleChange.ProposePolarization(fTransportEndSpin);
504
505 G4double deltaTime = 0.0 ;
506
507 // Calculate Lab Time of Flight (ONLY if field Equations used it!)
508 // G4double endTime = fCandidateEndGlobalTime;
509 // G4double delta_time = endTime - startTime;
510
511 G4double startTime = track.GetGlobalTime() ;
512
513 if (!fEndGlobalTimeComputed)
514 {
515 // The time was not integrated .. make the best estimate possible
516 //
517 G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity();
518 G4double stepLength = track.GetStepLength();
519
520 deltaTime= 0.0; // in case initialVelocity = 0
521 if ( initialVelocity > 0.0 ) deltaTime = stepLength/initialVelocity ;
522
523 fCandidateEndGlobalTime = startTime + deltaTime ;
524 fParticleChange.ProposeLocalTime( track.GetLocalTime() + deltaTime) ;
525 }
526 else
527 {
528 deltaTime = fCandidateEndGlobalTime - startTime ;
529 fParticleChange.ProposeGlobalTime( fCandidateEndGlobalTime ) ;
530 }
531
532
533 // Now Correct by Lorentz factor to get delta "proper" Time
534
535 G4double restMass = track.GetDynamicParticle()->GetMass() ;
536 G4double deltaProperTime = deltaTime*( restMass/track.GetTotalEnergy() ) ;
537
538 fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime) ;
539 //fParticleChange. ProposeTrueStepLength( track.GetStepLength() ) ;
540
541 // If the particle is caught looping or is stuck (in very difficult
542 // boundaries) in a magnetic field (doing many steps)
543 // THEN this kills it ...
544 //
545 if ( fParticleIsLooping )
546 {
547 G4double endEnergy= fTransportEndKineticEnergy;
548
549 if( (endEnergy < fThreshold_Important_Energy)
550 || (fNoLooperTrials >= fThresholdTrials ) ){
551 // Kill the looping particle
552 //
553 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
554
555 // 'Bare' statistics
556 fSumEnergyKilled += endEnergy;
557 if( endEnergy > fMaxEnergyKilled) { fMaxEnergyKilled= endEnergy; }
558
559#ifdef G4VERBOSE
560 if( (fVerboseLevel > 1) ||
561 ( endEnergy > fThreshold_Warning_Energy ) ) {
562 G4cout << " G4Transportation is killing track that is looping or stuck "
563 << G4endl
564 << " This track has " << track.GetKineticEnergy() / MeV
565 << " MeV energy." << G4endl;
566 G4cout << " Number of trials = " << fNoLooperTrials
567 << " No of calls to AlongStepDoIt = " << noCalls
568 << G4endl;
569 }
570#endif
571 fNoLooperTrials=0;
572 }
573 else{
574 fNoLooperTrials ++;
575#ifdef G4VERBOSE
576 if( (fVerboseLevel > 2) ){
577 G4cout << " G4Transportation::AlongStepDoIt(): Particle looping - "
578 << " Number of trials = " << fNoLooperTrials
579 << " No of calls to = " << noCalls
580 << G4endl;
581 }
582#endif
583 }
584 }else{
585 fNoLooperTrials=0;
586 }
587
588 // Another (sometimes better way) is to use a user-limit maximum Step size
589 // to alleviate this problem ..
590
591 // Introduce smooth curved trajectories to particle-change
592 //
594 (fFieldPropagator->GimmeTrajectoryVectorAndForgetIt() );
595
596 return &fParticleChange ;
597}
598
599//////////////////////////////////////////////////////////////////////////
600//
601// This ensures that the PostStep action is always called,
602// so that it can do the relocation if it is needed.
603//
604
607 G4double, // previousStepSize
608 G4ForceCondition* pForceCond )
609{
610 *pForceCond = Forced ;
611 return DBL_MAX ; // was kInfinity ; but convention now is DBL_MAX
612}
613
614/////////////////////////////////////////////////////////////////////////////
615//
616
618 const G4Step& )
619{
620 G4TouchableHandle retCurrentTouchable ; // The one to return
621 G4bool isLastStep= false;
622
623 // Initialize ParticleChange (by setting all its members equal
624 // to corresponding members in G4Track)
625 // fParticleChange.Initialize(track) ; // To initialise TouchableChange
626
627 fParticleChange.ProposeTrackStatus(track.GetTrackStatus()) ;
628
629 // If the Step was determined by the volume boundary,
630 // logically relocate the particle
631
632 if(fGeometryLimitedStep)
633 {
634 // fCurrentTouchable will now become the previous touchable,
635 // and what was the previous will be freed.
636 // (Needed because the preStepPoint can point to the previous touchable)
637
638 fLinearNavigator->SetGeometricallyLimitedStep() ;
639 fLinearNavigator->
640 LocateGlobalPointAndUpdateTouchableHandle( track.GetPosition(),
641 track.GetMomentumDirection(),
642 fCurrentTouchableHandle,
643 true ) ;
644 // Check whether the particle is out of the world volume
645 // If so it has exited and must be killed.
646 //
647 if( fCurrentTouchableHandle->GetVolume() == 0 )
648 {
649 fParticleChange.ProposeTrackStatus( fStopAndKill ) ;
650 }
651 retCurrentTouchable = fCurrentTouchableHandle ;
652 fParticleChange.SetTouchableHandle( fCurrentTouchableHandle ) ;
653
654 // Update the Step flag which identifies the Last Step in a volume
655 isLastStep = fLinearNavigator->ExitedMotherVolume()
656 | fLinearNavigator->EnteredDaughterVolume() ;
657
658#ifdef G4DEBUG_TRANSPORT
659 // Checking first implementation of flagging Last Step in Volume
660 G4bool exiting = fLinearNavigator->ExitedMotherVolume();
661 G4bool entering = fLinearNavigator->EnteredDaughterVolume();
662 if( ! (exiting || entering) ) {
663 G4cout << " Transport> : Proposed isLastStep= " << isLastStep
664 << " Exiting " << fLinearNavigator->ExitedMotherVolume()
665 << " Entering " << fLinearNavigator->EnteredDaughterVolume()
666 << G4endl;
667 }
668#endif
669 }
670 else // fGeometryLimitedStep is false
671 {
672 // This serves only to move the Navigator's location
673 //
674 fLinearNavigator->LocateGlobalPointWithinVolume( track.GetPosition() ) ;
675
676 // The value of the track's current Touchable is retained.
677 // (and it must be correct because we must use it below to
678 // overwrite the (unset) one in particle change)
679 // It must be fCurrentTouchable too ??
680 //
681 fParticleChange.SetTouchableHandle( track.GetTouchableHandle() ) ;
682 retCurrentTouchable = track.GetTouchableHandle() ;
683
684 isLastStep= false;
685#ifdef G4DEBUG_TRANSPORT
686 // Checking first implementation of flagging Last Step in Volume
687 G4cout << " Transport> Proposed isLastStep= " << isLastStep
688 << " Geometry did not limit step. " << G4endl;
689#endif
690 } // endif ( fGeometryLimitedStep )
691
692 fParticleChange.ProposeLastStepInVolume(isLastStep);
693
694 const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume() ;
695 const G4Material* pNewMaterial = 0 ;
696 const G4VSensitiveDetector* pNewSensitiveDetector = 0 ;
697
698 if( pNewVol != 0 )
699 {
700 pNewMaterial= pNewVol->GetLogicalVolume()->GetMaterial();
701 pNewSensitiveDetector= pNewVol->GetLogicalVolume()->GetSensitiveDetector();
702 }
703
704 // ( <const_cast> pNewMaterial ) ;
705 // ( <const_cast> pNewSensitiveDetector) ;
706
707 fParticleChange.SetMaterialInTouchable( (G4Material *) pNewMaterial ) ;
708 fParticleChange.SetSensitiveDetectorInTouchable( (G4VSensitiveDetector *) pNewSensitiveDetector ) ;
709
710 const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
711 if( pNewVol != 0 )
712 {
713 pNewMaterialCutsCouple=pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
714 }
715
716 if( pNewVol!=0 && pNewMaterialCutsCouple!=0 && pNewMaterialCutsCouple->GetMaterial()!=pNewMaterial )
717 {
718 // for parametrized volume
719 //
720 pNewMaterialCutsCouple =
722 ->GetMaterialCutsCouple(pNewMaterial,
723 pNewMaterialCutsCouple->GetProductionCuts());
724 }
725 fParticleChange.SetMaterialCutsCoupleInTouchable( pNewMaterialCutsCouple );
726
727 // temporarily until Get/Set Material of ParticleChange,
728 // and StepPoint can be made const.
729 // Set the touchable in ParticleChange
730 // this must always be done because the particle change always
731 // uses this value to overwrite the current touchable pointer.
732 //
733 fParticleChange.SetTouchableHandle(retCurrentTouchable) ;
734
735 return &fParticleChange ;
736}
737
738// New method takes over the responsibility to reset the state of G4Transportation
739// object at the start of a new track or the resumption of a suspended track.
740
741void
743{
745
746// The actions here are those that were taken in AlongStepGPIL
747// when track.GetCurrentStepNumber()==1
748
749 // reset safety value and center
750 //
751 fPreviousSafety = 0.0 ;
752 fPreviousSftOrigin = G4ThreeVector(0.,0.,0.) ;
753
754 // reset looping counter -- for motion in field
755 fNoLooperTrials= 0;
756 // Must clear this state .. else it depends on last track's value
757 // --> a better solution would set this from state of suspended track TODO ?
758 // Was if( aTrack->GetCurrentStepNumber()==1 ) { .. }
759
760 // ChordFinder reset internal state
761 //
762 if( DoesGlobalFieldExist() ) {
763 fFieldPropagator->ClearPropagatorState();
764 // Resets all state of field propagator class (ONLY)
765 // including safety values (in case of overlaps and to wipe for first track).
766
767 // G4ChordFinder* chordF= fFieldPropagator->GetChordFinder();
768 // if( chordF ) chordF->ResetStepEstimate();
769 }
770
771 // Make sure to clear the chord finders of all fields (ie managers)
773 fieldMgrStore->ClearAllChordFindersState();
774
775 // Update the current touchable handle (from the track's)
776 //
777 fCurrentTouchableHandle = aTrack->GetTouchableHandle();
778}
779
G4ForceCondition
@ Forced
G4GPILSelection
@ CandidateForSelection
@ fTransportation
CLHEP::Hep3Vector G4ThreeVector
@ fStopAndKill
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 mag2() const
G4double GetMass() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetCharge() const
G4ParticleDefinition * GetDefinition() const
G4double GetMagneticMoment() const
G4double GetTotalMomentum() const
static G4FieldManagerStore * GetInstance()
G4bool DoesFieldChangeEnergy() const
virtual void ConfigureForTrack(const G4Track *)
const G4Field * GetDetectorField() const
const G4ThreeVector & GetMomentumDir() const
G4double GetKineticEnergy() const
G4ThreeVector GetPosition() const
G4ThreeVector GetSpin() const
G4double GetLabTimeOfFlight() const
G4bool IsGravityActive() const
Definition: G4Field.hh:97
G4VSensitiveDetector * GetSensitiveDetector() const
G4Material * GetMaterial() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Material * GetMaterial() const
G4ProductionCuts * GetProductionCuts() const
void SetGeometricallyLimitedStep()
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4double pProposedMaxLength=DBL_MAX, const G4bool keepState=true)
virtual void LocateGlobalPointWithinVolume(const G4ThreeVector &position)
Definition: G4Navigator.cc:548
virtual G4double ComputeStep(const G4ThreeVector &pGlobalPoint, const G4ThreeVector &pDirection, const G4double pCurrentProposedStepLength, G4double &pNewSafety)
Definition: G4Navigator.cc:699
G4bool EnteredDaughterVolume() const
G4bool ExitedMotherVolume() const
void SetMaterialInTouchable(G4Material *fMaterial)
void SetTouchableHandle(const G4TouchableHandle &fTouchable)
void SetMaterialCutsCoupleInTouchable(const G4MaterialCutsCouple *fMaterialCutsCouple)
void SetPointerToVectorOfAuxiliaryPoints(std::vector< G4ThreeVector > *theNewVectorPointer)
virtual void Initialize(const G4Track &)
void SetSensitiveDetectorInTouchable(G4VSensitiveDetector *fSensitiveDetector)
void SetMomentumChanged(G4bool b)
void ProposePolarization(G4double Px, G4double Py, G4double Pz)
void ProposePosition(G4double x, G4double y, G4double z)
void ProposeLocalTime(G4double t)
void ProposeProperTime(G4double finalProperTime)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
void ProposeGlobalTime(G4double t)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4ProductionCutsTable * GetProductionCutsTable()
G4double ComputeStep(G4FieldTrack &pFieldTrack, G4double pCurrentProposedStepLength, G4double &pNewSafety, G4VPhysicalVolume *pPhysVol=0)
G4FieldManager * FindAndSetFieldManager(G4VPhysicalVolume *pCurrentPhysVol)
G4FieldManager * GetCurrentFieldManager()
G4bool IsParticleLooping() const
void SetChargeMomentumMass(G4double charge, G4double momentum, G4double pMass)
std::vector< G4ThreeVector > * GimmeTrajectoryVectorAndForgetIt() const
void SetCurrentSafety(G4double val, const G4ThreeVector &pos)
G4double GetVelocity() const
Definition: G4Step.hh:78
G4StepPoint * GetPreStepPoint() const
G4TrackStatus GetTrackStatus() const
G4double GetVelocity() const
G4VPhysicalVolume * GetVolume() const
const G4ThreeVector & GetPosition() const
G4double GetGlobalTime() const
G4double GetProperTime() const
G4double GetLocalTime() const
const G4DynamicParticle * GetDynamicParticle() const
const G4TouchableHandle & GetTouchableHandle() const
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
const G4ThreeVector & GetPolarization() const
G4double GetStepLength() const
G4double GetTotalEnergy() const
static G4TransportationManager * GetTransportationManager()
G4PropagatorInField * GetPropagatorInField() const
G4SafetyHelper * GetSafetyHelper() const
G4Navigator * GetNavigatorForTracking() const
G4double AlongStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety, G4GPILSelection *selection)
G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &stepData)
G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &stepData)
G4bool DoesGlobalFieldExist()
G4double PostStepGetPhysicalInteractionLength(const G4Track &, G4double previousStepSize, G4ForceCondition *pForceCond)
void StartTracking(G4Track *aTrack)
G4Transportation(G4int verbosityLevel=1)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLastStepInVolume(G4bool flag)
void ProposeTrueStepLength(G4double truePathLength)
G4LogicalVolume * GetLogicalVolume() const
void SetProcessSubType(G4int)
Definition: G4VProcess.hh:403
virtual void StartTracking(G4Track *)
Definition: G4VProcess.cc:125
virtual G4VPhysicalVolume * GetVolume(G4int depth=0) const
Definition: G4VTouchable.cc:44
T sqr(const T &x)
Definition: templates.hh:145
#define DBL_MAX
Definition: templates.hh:83