CMS 3D CMS Logo

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