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