Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/exoticphysics/monopole/src/G4MonopoleTransportation.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 /// \file exoticphysics/monopole/src/G4MonopoleTransportation.cc
 27 /// \brief Implementation of the G4MonopoleTransportation class
 28 //
 29 //
 30 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 31 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 32 //
 33 // This class is a process responsible for the transportation of
 34 // magnetic monopoles, ie the geometrical propagation that encounters the
 35 // geometrical sub-volumes of the detectors.
 36 //
 37 // For monopoles, uses a different equation of motion and ignores energy
 38 // conservation.
 39 //
 40 
 41 // =======================================================================
 42 // Created:  3 May 2010, J. Apostolakis, B. Bozsogi
 43 // =======================================================================
 44 
 45 #include "G4MonopoleTransportation.hh"
 46 
 47 #include "DetectorConstruction.hh"
 48 
 49 #include "G4ChordFinder.hh"
 50 #include "G4FieldManagerStore.hh"
 51 #include "G4Monopole.hh"
 52 #include "G4ParticleTable.hh"
 53 #include "G4ProductionCutsTable.hh"
 54 #include "G4RunManager.hh"
 55 #include "G4SafetyHelper.hh"
 56 #include "G4SystemOfUnits.hh"
 57 #include "G4TransportationProcessType.hh"
 58 
 59 class G4VSensitiveDetector;
 60 
 61 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 62 
 63 G4MonopoleTransportation::G4MonopoleTransportation(const G4Monopole* mpl, G4int verb)
 64   : G4VProcess(G4String("MonopoleTransportation"), fTransportation),
 65     fParticleDef(mpl),
 66     fMagSetup(0),
 67     fLinearNavigator(0),
 68     fFieldPropagator(0),
 69     fParticleIsLooping(false),
 70     fPreviousSftOrigin(0., 0., 0.),
 71     fPreviousSafety(0.0),
 72     fThreshold_Warning_Energy(100 * MeV),
 73     fThreshold_Important_Energy(250 * MeV),
 74     fThresholdTrials(10),
 75     // fUnimportant_Energy( 1 * MeV ),
 76     fNoLooperTrials(0),
 77     fSumEnergyKilled(0.0),
 78     fMaxEnergyKilled(0.0),
 79     fShortStepOptimisation(false),  // Old default: true (=fast short steps)
 80     fpSafetyHelper(0),
 81     noCalls(0)
 82 {
 83   verboseLevel = verb;
 84 
 85   // set Process Sub Type
 86   SetProcessSubType(TRANSPORTATION);
 87 
 88   // Do not finalize the G4MonopoleTransportation class
 89   if (G4Threading::IsMasterThread() && G4Threading::IsMultithreadedApplication()) {
 90     return;
 91   }
 92 
 93   const DetectorConstruction* detector = static_cast<const DetectorConstruction*>(
 94     G4RunManager::GetRunManager()->GetUserDetectorConstruction());
 95 
 96   fMagSetup = detector->GetMonopoleFieldSetup();
 97 
 98   G4TransportationManager* transportMgr = G4TransportationManager::GetTransportationManager();
 99 
100   fLinearNavigator = transportMgr->GetNavigatorForTracking();
101 
102   fFieldPropagator = transportMgr->GetPropagatorInField();
103   fpSafetyHelper = transportMgr->GetSafetyHelper();
104 
105   // New
106 
107   // Cannot determine whether a field exists here,
108   //  because it would only work if the field manager has informed
109   //  about the detector's field before this transportation process
110   //  is constructed.
111   // Instead later the method DoesGlobalFieldExist() is called
112   fCurrentTouchableHandle = nullptr;
113 
114   fEndGlobalTimeComputed = false;
115   fCandidateEndGlobalTime = 0;
116 }
117 
118 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
119 
120 G4MonopoleTransportation::~G4MonopoleTransportation()
121 {
122   if ((verboseLevel > 0) && (fSumEnergyKilled > 0.0)) {
123     G4cout << " G4MonopoleTransportation: Statistics for looping particles " << G4endl;
124     G4cout << "   Sum of energy of loopers killed: " << fSumEnergyKilled << G4endl;
125     G4cout << "   Max energy of loopers killed: " << fMaxEnergyKilled << G4endl;
126   }
127 }
128 
129 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
130 //
131 // Responsibilities:
132 //    Find whether the geometry limits the Step, and to what length
133 //    Calculate the new value of the safety and return it.
134 //    Store the final time, position and momentum.
135 
136 G4double G4MonopoleTransportation::AlongStepGetPhysicalInteractionLength(
137   const G4Track& track,
138   G4double,  //  previousStepSize
139   G4double currentMinimumStep, G4double& currentSafety, G4GPILSelection* selection)
140 {
141   fMagSetup->SetStepperAndChordFinder(1);
142   // change to monopole equation
143 
144   G4double geometryStepLength, newSafety;
145   fParticleIsLooping = false;
146 
147   // Initial actions moved to  StartTrack()
148   // --------------------------------------
149   // Note: in case another process changes touchable handle
150   //    it will be necessary to add here (for all steps)
151   // fCurrentTouchableHandle = aTrack->GetTouchableHandle();
152 
153   // GPILSelection is set to defaule value of CandidateForSelection
154   // It is a return value
155   //
156   *selection = CandidateForSelection;
157 
158   // Get initial Energy/Momentum of the track
159   //
160   const G4DynamicParticle* pParticle = track.GetDynamicParticle();
161   G4ThreeVector startMomentumDir = pParticle->GetMomentumDirection();
162   G4ThreeVector startPosition = track.GetPosition();
163 
164   // G4double   theTime        = track.GetGlobalTime() ;
165 
166   // The Step Point safety can be limited by other geometries and/or the
167   // assumptions of any process - it's not always the geometrical safety.
168   // We calculate the starting point's isotropic safety here.
169   //
170   G4ThreeVector OriginShift = startPosition - fPreviousSftOrigin;
171   G4double MagSqShift = OriginShift.mag2();
172   if (MagSqShift >= sqr(fPreviousSafety)) {
173     currentSafety = 0.0;
174   }
175   else {
176     currentSafety = fPreviousSafety - std::sqrt(MagSqShift);
177   }
178 
179   // Is the monopole charged ?
180   //
181   G4double particleMagneticCharge = fParticleDef->MagneticCharge();
182   G4double particleElectricCharge = pParticle->GetCharge();
183 
184   fGeometryLimitedStep = false;
185   // fEndGlobalTimeComputed = false ;
186 
187   // There is no need to locate the current volume. It is Done elsewhere:
188   //   On track construction
189   //   By the tracking, after all AlongStepDoIts, in "Relocation"
190 
191   // Check whether the particle have an (EM) field force exerting upon it
192   //
193   G4FieldManager* fieldMgr = 0;
194   G4bool fieldExertsForce = false;
195 
196   if ((particleMagneticCharge != 0.0)) {
197     fieldMgr = fFieldPropagator->FindAndSetFieldManager(track.GetVolume());
198     if (fieldMgr != 0) {
199       // Message the field Manager, to configure it for this track
200       fieldMgr->ConfigureForTrack(&track);
201       // Moved here, in order to allow a transition
202       //   from a zero-field  status (with fieldMgr->(field)0
203       //   to a finite field  status
204 
205       // If the field manager has no field, there is no field !
206       fieldExertsForce = (fieldMgr->GetDetectorField() != 0);
207     }
208   }
209 
210   // G4cout << " G4Transport:  field exerts force= " << fieldExertsForce
211   //          << "  fieldMgr= " << fieldMgr << G4endl;
212 
213   // Choose the calculation of the transportation: Field or not
214   //
215   if (!fieldExertsForce) {
216     G4double linearStepLength;
217     if (fShortStepOptimisation && (currentMinimumStep <= currentSafety)) {
218       // The Step is guaranteed to be taken
219       //
220       geometryStepLength = currentMinimumStep;
221       fGeometryLimitedStep = false;
222     }
223     else {
224       //  Find whether the straight path intersects a volume
225       //
226       linearStepLength = fLinearNavigator->ComputeStep(startPosition, startMomentumDir,
227                                                        currentMinimumStep, newSafety);
228       // Remember last safety origin & value.
229       //
230       fPreviousSftOrigin = startPosition;
231       fPreviousSafety = newSafety;
232       // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
233 
234       // The safety at the initial point has been re-calculated:
235       //
236       currentSafety = newSafety;
237 
238       fGeometryLimitedStep = (linearStepLength <= currentMinimumStep);
239       if (fGeometryLimitedStep) {
240         // The geometry limits the Step size (an intersection was found.)
241         geometryStepLength = linearStepLength;
242       }
243       else {
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 = fParticleDef->GetPDGMass();
269 
270     G4ChargeState chargeState(particleElectricCharge,  // The charge can change
271                               fParticleDef->GetPDGSpin(),
272                               0,  //  Magnetic moment:
273                               0,  //  Electric Dipole moment
274                               particleMagneticCharge);  // in Mev/c
275 
276     G4EquationOfMotion* equationOfMotion =
277       fFieldPropagator->GetChordFinder()->GetIntegrationDriver()->GetEquationOfMotion();
278 
279     equationOfMotion->SetChargeMomentumMass(chargeState, momentumMagnitude, restMass);
280     // SetChargeMomentumMass now passes both the electric and magnetic
281     // charge in chargeState
282 
283     G4ThreeVector spin = track.GetPolarization();
284     G4FieldTrack aFieldTrack = G4FieldTrack(startPosition, track.GetMomentumDirection(), 0.0,
285                                             track.GetKineticEnergy(), restMass, track.GetVelocity(),
286                                             track.GetGlobalTime(),  // Lab.
287                                             track.GetProperTime(),  // Part.
288                                             &spin);
289     if (currentMinimumStep > 0) {
290       // Do the Transport in the field (non recti-linear)
291       //
292       lengthAlongCurve = fFieldPropagator->ComputeStep(aFieldTrack, currentMinimumStep,
293                                                        currentSafety, track.GetVolume());
294       fGeometryLimitedStep = lengthAlongCurve < currentMinimumStep;
295       if (fGeometryLimitedStep) {
296         geometryStepLength = lengthAlongCurve;
297       }
298       else {
299         geometryStepLength = currentMinimumStep;
300       }
301     }
302     else {
303       geometryStepLength = lengthAlongCurve = 0.0;
304       fGeometryLimitedStep = false;
305     }
306 
307     // Remember last safety origin & value.
308     //
309     fPreviousSftOrigin = startPosition;
310     fPreviousSafety = currentSafety;
311     // fpSafetyHelper->SetCurrentSafety( newSafety, startPosition);
312 
313     // Get the End-Position and End-Momentum (Dir-ection)
314     //
315     fTransportEndPosition = aFieldTrack.GetPosition();
316 
317     // Momentum:  Magnitude and direction can be changed too now ...
318     //
319     fMomentumChanged = true;
320     fTransportEndMomentumDir = aFieldTrack.GetMomentumDir();
321 
322     fTransportEndKineticEnergy = aFieldTrack.GetKineticEnergy();
323 
324     fCandidateEndGlobalTime = aFieldTrack.GetLabTimeOfFlight();
325     fEndGlobalTimeComputed = true;
326 
327     fTransportEndSpin = aFieldTrack.GetSpin();
328     fParticleIsLooping = fFieldPropagator->IsParticleLooping();
329     endpointDistance = (fTransportEndPosition - startPosition).mag();
330   }
331 
332   // If we are asked to go a step length of 0, and we are on a boundary
333   // then a boundary will also limit the step -> we must flag this.
334   //
335   if (currentMinimumStep == 0.0) {
336     if (currentSafety == 0.0) fGeometryLimitedStep = true;
337   }
338 
339   // Update the safety starting from the end-point,
340   // if it will become negative at the end-point.
341   //
342   if (currentSafety < endpointDistance) {
343     // if( particleMagneticCharge == 0.0 )
344     // G4cout  << "  Avoiding call to ComputeSafety : charge = 0.0 " << G4endl;
345 
346     if (particleMagneticCharge != 0.0) {
347       G4double endSafety = fLinearNavigator->ComputeSafety(fTransportEndPosition);
348       currentSafety = endSafety;
349       fPreviousSftOrigin = fTransportEndPosition;
350       fPreviousSafety = currentSafety;
351       fpSafetyHelper->SetCurrentSafety(currentSafety, fTransportEndPosition);
352 
353       // Because the Stepping Manager assumes it is from the start point,
354       //  add the StepLength
355       //
356       currentSafety += endpointDistance;
357 
358 #ifdef G4DEBUG_TRANSPORT
359       G4cout.precision(12);
360       G4cout << "***G4MonopoleTransportation::AlongStepGPIL ** " << G4endl;
361       G4cout << "  Called Navigator->ComputeSafety at " << fTransportEndPosition
362              << "    and it returned safety= " << endSafety << G4endl;
363       G4cout << "  Adding endpoint distance " << endpointDistance
364              << "   to obtain pseudo-safety= " << currentSafety << G4endl;
365 #endif
366     }
367   }
368 
369   fParticleChange.ProposeTrueStepLength(geometryStepLength);
370 
371   fMagSetup->SetStepperAndChordFinder(0);
372   // change back to usual equation
373 
374   return geometryStepLength;
375 }
376 
377 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
378 //
379 //   Initialize ParticleChange  (by setting all its members equal
380 //                               to corresponding members in G4Track)
381 
382 G4VParticleChange* G4MonopoleTransportation::AlongStepDoIt(const G4Track& track,
383                                                            const G4Step& stepData)
384 {
385   ++noCalls;
386 
387   if (fGeometryLimitedStep) {
388     stepData.GetPostStepPoint()->SetStepStatus(fGeomBoundary);
389   }
390 
391   fParticleChange.Initialize(track);
392 
393   //  Code for specific process
394   //
395   fParticleChange.ProposePosition(fTransportEndPosition);
396   fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir);
397   fParticleChange.ProposeEnergy(fTransportEndKineticEnergy);
398   fParticleChange.SetMomentumChanged(fMomentumChanged);
399 
400   fParticleChange.ProposePolarization(fTransportEndSpin);
401 
402   G4double deltaTime = 0.0;
403 
404   // Calculate  Lab Time of Flight (ONLY if field Equations used it!)
405 
406   G4double startTime = track.GetGlobalTime();
407 
408   if (!fEndGlobalTimeComputed) {
409     // The time was not integrated .. make the best estimate possible
410     //
411     G4double finalVelocity = track.GetVelocity();
412     G4double initialVelocity = stepData.GetPreStepPoint()->GetVelocity();
413     G4double stepLength = track.GetStepLength();
414 
415     deltaTime = 0.0;  // in case initialVelocity = 0
416     if (finalVelocity > 0.0) {
417       G4double meanInverseVelocity;
418       // deltaTime = stepLength/finalVelocity ;
419       meanInverseVelocity = 0.5 * (1.0 / initialVelocity + 1.0 / finalVelocity);
420       deltaTime = stepLength * meanInverseVelocity;
421     }
422     else if (initialVelocity > 0.0) {
423       deltaTime = stepLength / initialVelocity;
424     }
425     fCandidateEndGlobalTime = startTime + deltaTime;
426   }
427   else {
428     deltaTime = fCandidateEndGlobalTime - startTime;
429   }
430 
431   fParticleChange.ProposeGlobalTime(fCandidateEndGlobalTime);
432 
433   // Now Correct by Lorentz factor to get "proper" deltaTime
434 
435   G4double restMass = track.GetDynamicParticle()->GetMass();
436   G4double deltaProperTime = deltaTime * (restMass / track.GetTotalEnergy());
437 
438   fParticleChange.ProposeProperTime(track.GetProperTime() + deltaProperTime);
439 
440   // If the particle is caught looping or is stuck (in very difficult
441   // boundaries) in a magnetic field (doing many steps)
442   //   THEN this kills it ...
443   //
444   if (fParticleIsLooping) {
445     G4double endEnergy = fTransportEndKineticEnergy;
446 
447     if ((endEnergy < fThreshold_Important_Energy) || (fNoLooperTrials >= fThresholdTrials)) {
448       // Kill the looping particle
449       //
450       fParticleChange.ProposeTrackStatus(fStopAndKill);
451 
452       // 'Bare' statistics
453       fSumEnergyKilled += endEnergy;
454       if (endEnergy > fMaxEnergyKilled) {
455         fMaxEnergyKilled = endEnergy;
456       }
457 
458 #ifdef G4VERBOSE
459       if ((verboseLevel > 1) || (endEnergy > fThreshold_Warning_Energy)) {
460         G4cout << " G4MonopoleTransportation is killing track "
461                << "that is looping or stuck " << G4endl << "   This track has "
462                << track.GetKineticEnergy() / MeV << " MeV energy." << G4endl;
463         G4cout << "   Number of trials = " << fNoLooperTrials
464                << "   No of calls to AlongStepDoIt = " << noCalls << G4endl;
465       }
466 #endif
467       fNoLooperTrials = 0;
468     }
469     else {
470       fNoLooperTrials++;
471 #ifdef G4VERBOSE
472       if ((verboseLevel > 2)) {
473         G4cout << "   G4MonopoleTransportation::AlongStepDoIt(): "
474                << "Particle looping - "
475                << "   Number of trials = " << fNoLooperTrials << "   No of calls to  = " << noCalls
476                << G4endl;
477       }
478 #endif
479     }
480   }
481   else {
482     fNoLooperTrials = 0;
483   }
484 
485   // Another (sometimes better way) is to use a user-limit maximum Step size
486   // to alleviate this problem ..
487 
488   // Introduce smooth curved trajectories to particle-change
489   //
490   fParticleChange.SetPointerToVectorOfAuxiliaryPoints(
491     fFieldPropagator->GimmeTrajectoryVectorAndForgetIt());
492 
493   return &fParticleChange;
494 }
495 
496 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
497 //
498 //  This ensures that the PostStep action is always called,
499 //  so that it can do the relocation if it is needed.
500 //
501 
502 G4double
503 G4MonopoleTransportation::PostStepGetPhysicalInteractionLength(const G4Track&,
504                                                                G4double,  // previousStepSize
505                                                                G4ForceCondition* pForceCond)
506 {
507   *pForceCond = Forced;
508   return DBL_MAX;  // was kInfinity ; but convention now is DBL_MAX
509 }
510 
511 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
512 
513 G4VParticleChange* G4MonopoleTransportation::PostStepDoIt(const G4Track& track, const G4Step&)
514 {
515   G4TouchableHandle retCurrentTouchable;  // The one to return
516 
517   // Initialize ParticleChange  (by setting all its members equal
518   //                             to corresponding members in G4Track)
519   // fParticleChange.Initialize(track) ;  // To initialise TouchableChange
520 
521   fParticleChange.ProposeTrackStatus(track.GetTrackStatus());
522 
523   // If the Step was determined by the volume boundary,
524   // logically relocate the particle
525 
526   if (fGeometryLimitedStep) {
527     // fCurrentTouchable will now become the previous touchable,
528     // and what was the previous will be freed.
529     // (Needed because the preStepPoint can point to the previous touchable)
530 
531     fLinearNavigator->SetGeometricallyLimitedStep();
532     fLinearNavigator->LocateGlobalPointAndUpdateTouchableHandle(
533       track.GetPosition(), track.GetMomentumDirection(), fCurrentTouchableHandle, true);
534     // Check whether the particle is out of the world volume
535     // If so it has exited and must be killed.
536     //
537     if (fCurrentTouchableHandle->GetVolume() == 0) {
538       fParticleChange.ProposeTrackStatus(fStopAndKill);
539     }
540     retCurrentTouchable = fCurrentTouchableHandle;
541     fParticleChange.SetTouchableHandle(fCurrentTouchableHandle);
542   }
543   else  // fGeometryLimitedStep  is false
544   {
545     // This serves only to move the Navigator's location
546     //
547     fLinearNavigator->LocateGlobalPointWithinVolume(track.GetPosition());
548 
549     // The value of the track's current Touchable is retained.
550     // (and it must be correct because we must use it below to
551     // overwrite the (unset) one in particle change)
552     //  It must be fCurrentTouchable too ??
553     //
554     fParticleChange.SetTouchableHandle(track.GetTouchableHandle());
555     retCurrentTouchable = track.GetTouchableHandle();
556   }  // endif ( fGeometryLimitedStep )
557 
558   const G4VPhysicalVolume* pNewVol = retCurrentTouchable->GetVolume();
559   const G4Material* pNewMaterial = 0;
560   G4VSensitiveDetector* pNewSensitiveDetector = 0;
561   if (pNewVol != 0) {
562     pNewMaterial = pNewVol->GetLogicalVolume()->GetMaterial();
563     pNewSensitiveDetector = pNewVol->GetLogicalVolume()->GetSensitiveDetector();
564   }
565 
566   // ( <const_cast> pNewMaterial ) ;
567 
568   fParticleChange.SetMaterialInTouchable((G4Material*)pNewMaterial);
569   fParticleChange.SetSensitiveDetectorInTouchable(pNewSensitiveDetector);
570 
571   const G4MaterialCutsCouple* pNewMaterialCutsCouple = 0;
572   if (pNewVol != 0) {
573     pNewMaterialCutsCouple = pNewVol->GetLogicalVolume()->GetMaterialCutsCouple();
574   }
575 
576   if (pNewVol != 0 && pNewMaterialCutsCouple != 0
577       && pNewMaterialCutsCouple->GetMaterial() != pNewMaterial)
578   {
579     // for parametrized volume
580     //
581     pNewMaterialCutsCouple = G4ProductionCutsTable::GetProductionCutsTable()->GetMaterialCutsCouple(
582       pNewMaterial, pNewMaterialCutsCouple->GetProductionCuts());
583   }
584   fParticleChange.SetMaterialCutsCoupleInTouchable(pNewMaterialCutsCouple);
585 
586   // temporarily until Get/Set Material of ParticleChange,
587   // and StepPoint can be made const.
588   // Set the touchable in ParticleChange
589   // this must always be done because the particle change always
590   // uses this value to overwrite the current touchable pointer.
591   //
592   fParticleChange.SetTouchableHandle(retCurrentTouchable);
593 
594   return &fParticleChange;
595 }
596 
597 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
598 
599 // New method takes over the responsibility to reset the state
600 // of G4MonopoleTransportation object at the start of a new track
601 // or the resumption of a suspended track.
602 
603 void G4MonopoleTransportation::StartTracking(G4Track* aTrack)
604 {
605   G4VProcess::StartTracking(aTrack);
606 
607   // The actions here are those that were taken in AlongStepGPIL
608   //   when track.GetCurrentStepNumber()==1
609 
610   // reset safety value and center
611   //
612   fPreviousSafety = 0.0;
613   fPreviousSftOrigin = G4ThreeVector(0., 0., 0.);
614 
615   // reset looping counter -- for motion in field
616   fNoLooperTrials = 0;
617   // Must clear this state .. else it depends on last track's value
618   //  --> a better solution would set this from state of suspended track TODO ?
619   // Was if( aTrack->GetCurrentStepNumber()==1 ) { .. }
620 
621   // ChordFinder reset internal state
622   //
623   if (DoesGlobalFieldExist()) {
624     fFieldPropagator->ClearPropagatorState();
625     // Resets all state of field propagator class (ONLY)
626     // including safety values
627     // in case of overlaps and to wipe for first track).
628 
629     // G4ChordFinder* chordF= fFieldPropagator->GetChordFinder();
630     // if( chordF ) chordF->ResetStepEstimate();
631   }
632 
633   // Make sure to clear the chord finders of all fields (ie managers)
634   G4FieldManagerStore* fieldMgrStore = G4FieldManagerStore::GetInstance();
635   fieldMgrStore->ClearAllChordFindersState();
636 
637   // Update the current touchable handle  (from the track's)
638   //
639   fCurrentTouchableHandle = aTrack->GetTouchableHandle();
640 }
641 
642 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
643