source: trunk/source/processes/transportation/src/G4Transportation.cc @ 1253

Last change on this file since 1253 was 1228, checked in by garnier, 14 years ago

update geant4.9.3 tag

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