ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4SteppingManager2.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4SteppingManager2.cc
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 //
28 //---------------------------------------------------------------
29 //
30 // G4SteppingManager2.cc
31 //
32 // Description:
33 // This class represents the manager who steers to move the give
34 // particle from the TrackingManger by one Step.
35 //
36 // Contact:
37 // Questions and comments to this code should be sent to
38 // Katsuya Amako (e-mail: Katsuya.Amako@kek.jp)
39 // Takashi Sasaki (e-mail: Takashi.Sasaki@kek.jp)
40 //
41 //---------------------------------------------------------------
42 
43 //#define debug
44 
45 #include "G4UImanager.hh"
46 #include "G4ForceCondition.hh"
47 #include "G4GPILSelection.hh"
48 #include "G4SteppingControl.hh"
50 #include "G4SteppingManager.hh"
51 #include "G4LossTableManager.hh"
52 #include "G4ParticleTable.hh"
53 
57 {
58 #ifdef debug
59  G4cout<<"G4SteppingManager::GetProcessNumber: is called track="
60  <<fTrack<<G4endl;
61 #endif
62 
64  if(!pm)
65  {
66  G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
67  << " ProcessManager is NULL for particle = "
68  << fTrack->GetDefinition()->GetParticleName() << ", PDG_code = "
70  G4Exception("G4SteppingManager::GetProcessNumber()", "Tracking0011",
71  FatalException, "Process Manager is not found.");
72  return;
73  }
74 
75 // AtRestDoits
79 #ifdef debug
80  G4cout << "G4SteppingManager::GetProcessNumber: #ofAtRest="
82 #endif
83 
84 // AlongStepDoits
88 #ifdef debug
89  G4cout << "G4SteppingManager::GetProcessNumber:#ofAlongStp="
91 #endif
92 
93 // PostStepDoits
97 #ifdef debug
98  G4cout << "G4SteppingManager::GetProcessNumber: #ofPostStep="
100 #endif
101 
105  {
106  G4cerr << "ERROR - G4SteppingManager::GetProcessNumber()" << G4endl
107  << " SizeOfSelectedDoItVector= " << SizeOfSelectedDoItVector
108  << " ; is smaller then one of MAXofAtRestLoops= "
109  << MAXofAtRestLoops << G4endl
110  << " or MAXofAlongStepLoops= " << MAXofAlongStepLoops
111  << " or MAXofPostStepLoops= " << MAXofPostStepLoops << G4endl;
112  G4Exception("G4SteppingManager::GetProcessNumber()",
113  "Tracking0012", FatalException,
114  "The array size is smaller than the actual No of processes.");
115  }
116 }
117 
118 
119 // ************************************************************************
120 //
121 // Private Member Functions
122 //
123 // ************************************************************************
124 
125 
129 {
130 
131 // ReSet the counter etc.
132  PhysicalStep = DBL_MAX; // Initialize by a huge number
133  physIntLength = DBL_MAX; // Initialize by a huge number
134 #ifdef G4VERBOSE
135  // !!!!! Verbose
137 #endif
138 
139 // Obtain the user defined maximum allowed Step in the volume
140 // 1997.12.13 adds argument for GetMaxAllowedStep by K.Kurashige
141 // 2004.01.20 This block will be removed by Geant4 7.0
142 // G4UserLimits* ul= fCurrentVolume->GetLogicalVolume()->GetUserLimits();
143 // if (ul) {
144 // physIntLength = ul->GetMaxAllowedStep(*fTrack);
145 //#ifdef G4VERBOSE
146 // // !!!!! Verbose
147 // if(verboseLevel>0) fVerbose->DPSLUserLimit();
148 //#endif
149 // }
150 //
151 // if(physIntLength < PhysicalStep ){
152 // PhysicalStep = physIntLength;
153 // fStepStatus = fUserDefinedLimit;
154 // fStep->GetPostStepPoint()
155 // ->SetProcessDefinedStep(0);
156 // // Take note that the process pointer is 'NULL' if the Step
157 // // is defined by the user defined limit.
158 // }
159 // 2004.01.20 This block will be removed by Geant4 7.0
160 
161 // GPIL for PostStep
163 
164  for(size_t np=0; np < MAXofPostStepLoops; np++){
165  fCurrentProcess = (*fPostStepGetPhysIntVector)(np);
166  if (fCurrentProcess== 0) {
167  (*fSelectedPostStepDoItVector)[np] = InActivated;
168  continue;
169  } // NULL means the process is inactivated by a user on fly.
170 
172  PostStepGPIL( *fTrack,
174  &fCondition );
175 #ifdef G4VERBOSE
176  // !!!!! Verbose
178 #endif
179 
180  switch (fCondition) {
181  case ExclusivelyForced:
182  (*fSelectedPostStepDoItVector)[np] = ExclusivelyForced;
186  break;
187  case Conditionally:
188  // (*fSelectedPostStepDoItVector)[np] = Conditionally;
189  G4Exception("G4SteppingManager::DefinePhysicalStepLength()", "Tracking1001", FatalException, "This feature no more supported");
190 
191  break;
192  case Forced:
193  (*fSelectedPostStepDoItVector)[np] = Forced;
194  break;
195  case StronglyForced:
196  (*fSelectedPostStepDoItVector)[np] = StronglyForced;
197  break;
198  default:
199  (*fSelectedPostStepDoItVector)[np] = InActivated;
200  break;
201  }
202 
203 
204 
206  for(size_t nrest=np+1; nrest < MAXofPostStepLoops; nrest++){
207  (*fSelectedPostStepDoItVector)[nrest] = InActivated;
208  }
209  return; // Take note the 'return' at here !!!
210  }
211  else{
218  }
219  }
220 
221 
222  }
223 
224  if (fPostStepDoItProcTriggered<MAXofPostStepLoops) {
226  InActivated) {
227  (*fSelectedPostStepDoItVector)[fPostStepDoItProcTriggered] =
228  NotForced;
229  }
230  }
231 
232 // GPIL for AlongStep
234  G4double safetyProposedToAndByProcess = proposedSafety;
235 
236  for(size_t kp=0; kp < MAXofAlongStepLoops; kp++){
237  fCurrentProcess = (*fAlongStepGetPhysIntVector)[kp];
238  if (fCurrentProcess== 0) continue;
239  // NULL means the process is inactivated by a user on fly.
240 
242  AlongStepGPIL( *fTrack, fPreviousStepSize,
243  PhysicalStep,
244  safetyProposedToAndByProcess,
245  &fGPILSelection );
246 #ifdef G4VERBOSE
247  // !!!!! Verbose
249 #endif
252 
253  // Check if the process wants to be the GPIL winner. For example,
254  // multi-scattering proposes Step limit, but won't be the winner.
259  }
260 
261  // Transportation is assumed to be the last process in the vector
262  if(kp == MAXofAlongStepLoops-1)
264  }
265 
266  // Make sure to check the safety, even if Step is not limited
267  // by this process. J. Apostolakis, June 20, 1998
268  //
269  if (safetyProposedToAndByProcess < proposedSafety)
270  // proposedSafety keeps the smallest value:
271  proposedSafety = safetyProposedToAndByProcess;
272  else
273  // safetyProposedToAndByProcess always proposes a valid safety:
274  safetyProposedToAndByProcess = proposedSafety;
275 
276  }
277 } // void G4SteppingManager::DefinePhysicalStepLength() //
278 
279 
283 {
284 // Select the rest process which has the shortest time before
285 // it is invoked. In rest processes, GPIL()
286 // returns the time before a process occurs.
287  G4double lifeTime, shortestLifeTime;
288 
290  shortestLifeTime = DBL_MAX;
291 
292  unsigned int NofInactiveProc=0;
293  for( size_t ri=0 ; ri < MAXofAtRestLoops ; ri++ ){
294  fCurrentProcess = (*fAtRestGetPhysIntVector)[ri];
295  if (fCurrentProcess== 0) {
296  (*fSelectedAtRestDoItVector)[ri] = InActivated;
297  NofInactiveProc++;
298  continue;
299  } // NULL means the process is inactivated by a user on fly.
300 
301  lifeTime =
303 
304 
305 
307  (*fSelectedAtRestDoItVector)[ri] = Forced;
308  }
309  else{
310  (*fSelectedAtRestDoItVector)[ri] = InActivated;
311  if(lifeTime < shortestLifeTime ){
312  shortestLifeTime = lifeTime;
314  }
315  }
316  }
317 
318  (*fSelectedAtRestDoItVector)[fAtRestDoItProcTriggered] = NotForced;
319 
320 // at least one process is necessary to destroy the particle
321 // exit with warning
322  if(NofInactiveProc==MAXofAtRestLoops){
323  G4Exception("G4SteppingManager::InvokeAtRestDoItProcs()", "Tracking0013",
324  JustWarning, "No AtRestDoIt process is active!" );
325  }
326 
327  fStep->SetStepLength( 0. ); //the particle has stopped
328  fTrack->SetStepLength( 0. );
329 
330 // invoke selected process
331  for(size_t np=0; np < MAXofAtRestLoops; np++){
332  //
333  // Note: DoItVector has inverse order against GetPhysIntVector
334  // and SelectedAtRestDoItVector.
335  //
336  if( (*fSelectedAtRestDoItVector)[MAXofAtRestLoops-np-1] != InActivated){
337 
338  fCurrentProcess = (*fAtRestDoItVector)[np];
341 
342  // Set the current process as a process which defined this Step length
345 
346  // Update Step
348 
349  // Now Store the secondaries from ParticleChange to SecondaryList
350  G4Track* tempSecondaryTrack;
351  G4int num2ndaries;
352 
353  num2ndaries = fParticleChange->GetNumberOfSecondaries();
354 
355  for(G4int DSecLoop=0 ; DSecLoop< num2ndaries; DSecLoop++){
356  tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
357 
358  if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
359  { ApplyProductionCut(tempSecondaryTrack); }
360 
361  // Set parentID
362  tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
363 
364  // Set the process pointer which created this track
365  tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
366 
367  // If this 2ndry particle has 'zero' kinetic energy, make sure
368  // it invokes a rest process at the beginning of the tracking
369  if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN){
370  G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()->GetProcessManager();
371  if(!pm)
372  {
374  ED << "A track without proper process manager is pushed into the track stack.\n"
375  << " Particle name : " << tempSecondaryTrack->GetDefinition()->GetParticleName() << " -- ";
376  if(tempSecondaryTrack->GetParentID()<0)
377  { ED << "created by a primary particle generator."; }
378  else
379  {
380  const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
381  if(vp)
382  { ED << "created by " << vp->GetProcessName() << "."; }
383  else
384  { ED << "creaded by unknown process."; }
385  }
386  G4Exception("G4SteppingManager::InvokeAtRestDoItProcs()","Tracking10051",
387  FatalException,ED);
388  }
389  if (pm->GetAtRestProcessVector()->entries()>0){
390  tempSecondaryTrack->SetTrackStatus( fStopButAlive );
391  fSecondary->push_back( tempSecondaryTrack );
393  } else {
394  delete tempSecondaryTrack;
395  }
396  } else {
397  fSecondary->push_back( tempSecondaryTrack );
399  }
400  } //end of loop on secondary
401 
402 
403  // clear ParticleChange
405 
406  } //if(fSelectedAtRestDoItVector[np] != InActivated){
407  } //for(size_t np=0; np < MAXofAtRestLoops; np++){
408  fStep->UpdateTrack();
409 
411 }
412 
413 
417 {
418 
419 // If the current Step is defined by a 'ExclusivelyForced'
420 // PostStepDoIt, then don't invoke any AlongStepDoIt
422  return; // Take note 'return' is here !!!
423  }
424 
425 // Invoke the all active continuous processes
426  for( size_t ci=0 ; ci<MAXofAlongStepLoops ; ci++ ){
427  fCurrentProcess = (*fAlongStepDoItVector)[ci];
428  if (fCurrentProcess== 0) continue;
429  // NULL means the process is inactivated by a user on fly.
430 
433 
434  // Update the PostStepPoint of Step according to ParticleChange
436 #ifdef G4VERBOSE
437  // !!!!! Verbose
439 #endif
440 
441  // Now Store the secondaries from ParticleChange to SecondaryList
442  G4Track* tempSecondaryTrack;
443  G4int num2ndaries;
444 
445  num2ndaries = fParticleChange->GetNumberOfSecondaries();
446 
447  for(G4int DSecLoop=0 ; DSecLoop< num2ndaries; DSecLoop++){
448  tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
449 
450  if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
451  { ApplyProductionCut(tempSecondaryTrack); }
452 
453  // Set parentID
454  tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
455 
456  // Set the process pointer which created this track
457  tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
458 
459  // If this 2ndry particle has 'zero' kinetic energy, make sure
460  // it invokes a rest process at the beginning of the tracking
461  if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN){
462  G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()->GetProcessManager();
463  if(!pm)
464  {
466  ED << "A track without proper process manager is pushed into the track stack.\n"
467  << " Particle name : " << tempSecondaryTrack->GetDefinition()->GetParticleName() << " -- ";
468  if(tempSecondaryTrack->GetParentID()<0)
469  { ED << "created by a primary particle generator."; }
470  else
471  {
472  const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
473  if(vp)
474  { ED << "created by " << vp->GetProcessName() << "."; }
475  else
476  { ED << "creaded by unknown process."; }
477  }
478  G4Exception("G4SteppingManager::InvokeAlongStepDoItProcs()","Tracking10051",
479  FatalException,ED);
480  }
481  if (pm->GetAtRestProcessVector()->entries()>0){
482  tempSecondaryTrack->SetTrackStatus( fStopButAlive );
483  fSecondary->push_back( tempSecondaryTrack );
485  } else {
486  delete tempSecondaryTrack;
487  }
488  } else {
489  fSecondary->push_back( tempSecondaryTrack );
491  }
492  } //end of loop on secondary
493 
494  // Set the track status according to what the process defined
495  // if kinetic energy >0, otherwise set fStopButAlive
497 
498  // clear ParticleChange
500  }
501 
502  fStep->UpdateTrack();
503  G4TrackStatus fNewStatus = fTrack->GetTrackStatus();
504 
505  if ( fNewStatus == fAlive && fTrack->GetKineticEnergy() <= DBL_MIN ) {
506  if(MAXofAtRestLoops>0) fNewStatus = fStopButAlive;
507  else fNewStatus = fStopAndKill;
508  fTrack->SetTrackStatus( fNewStatus );
509  }
510 
511 }
512 
516 {
517 
518 // Invoke the specified discrete processes
519  for(size_t np=0; np < MAXofPostStepLoops; np++){
520  //
521  // Note: DoItVector has inverse order against GetPhysIntVector
522  // and SelectedPostStepDoItVector.
523  //
524  G4int Cond = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np-1];
525  if(Cond != InActivated){
526  if( ((Cond == NotForced) && (fStepStatus == fPostStepDoItProc)) ||
527  ((Cond == Forced) && (fStepStatus != fExclusivelyForcedProc)) ||
528  // ((Cond == Conditionally) && (fStepStatus == fAlongStepDoItProc)) ||
530  ((Cond == StronglyForced) )
531  ) {
532 
533  InvokePSDIP(np);
534  if ((np==0) && (fTrack->GetNextVolume() == 0)){
537  }
538  }
539  } //if(*fSelectedPostStepDoItVector(np)........
540 
541  // Exit from PostStepLoop if the track has been killed,
542  // but extra treatment for processes with Strongly Forced flag
544  for(size_t np1=np+1; np1 < MAXofPostStepLoops; np1++){
545  G4int Cond2 = (*fSelectedPostStepDoItVector)[MAXofPostStepLoops-np1-1];
546  if (Cond2 == StronglyForced) {
547  InvokePSDIP(np1);
548  }
549  }
550  break;
551  }
552  } //for(size_t np=0; np < MAXofPostStepLoops; np++){
553 }
554 
555 
556 
558 {
559  fCurrentProcess = (*fPostStepDoItVector)[np];
562 
563  // Update PostStepPoint of Step according to ParticleChange
565 #ifdef G4VERBOSE
566  // !!!!! Verbose
568 #endif
569  // Update G4Track according to ParticleChange after each PostStepDoIt
570  fStep->UpdateTrack();
571 
572  // Update safety after each invocation of PostStepDoIts
574 
575  // Now Store the secondaries from ParticleChange to SecondaryList
576  G4Track* tempSecondaryTrack;
577  G4int num2ndaries;
578 
579  num2ndaries = fParticleChange->GetNumberOfSecondaries();
580 
581  for(G4int DSecLoop=0 ; DSecLoop< num2ndaries; DSecLoop++){
582  tempSecondaryTrack = fParticleChange->GetSecondary(DSecLoop);
583 
584  if(tempSecondaryTrack->GetDefinition()->GetApplyCutsFlag())
585  { ApplyProductionCut(tempSecondaryTrack); }
586 
587  // Set parentID
588  tempSecondaryTrack->SetParentID( fTrack->GetTrackID() );
589 
590  // Set the process pointer which created this track
591  tempSecondaryTrack->SetCreatorProcess( fCurrentProcess );
592 
593  // If this 2ndry particle has 'zero' kinetic energy, make sure
594  // it invokes a rest process at the beginning of the tracking
595  if(tempSecondaryTrack->GetKineticEnergy() <= DBL_MIN){
596  G4ProcessManager* pm = tempSecondaryTrack->GetDefinition()->GetProcessManager();
597  if(!pm)
598  {
600  ED << "A track without proper process manager is pushed into the track stack.\n"
601  << " Particle name : " << tempSecondaryTrack->GetDefinition()->GetParticleName() << " -- ";
602  if(tempSecondaryTrack->GetParentID()<0)
603  { ED << "created by a primary particle generator."; }
604  else
605  {
606  const G4VProcess* vp = tempSecondaryTrack->GetCreatorProcess();
607  if(vp)
608  { ED << "created by " << vp->GetProcessName() << "."; }
609  else
610  { ED << "creaded by unknown process."; }
611  }
612  G4Exception("G4SteppingManager::InvokePSDIP()","Tracking10053",
613  FatalException,ED);
614  }
615  if (pm->GetAtRestProcessVector()->entries()>0){
616  tempSecondaryTrack->SetTrackStatus( fStopButAlive );
617  fSecondary->push_back( tempSecondaryTrack );
619  } else {
620  delete tempSecondaryTrack;
621  }
622  } else {
623  fSecondary->push_back( tempSecondaryTrack );
625  }
626  } //end of loop on secondary
627 
628  // Set the track status according to what the process defined
630 
631  // clear ParticleChange
633 }
634 
635 #include "G4EnergyLossTables.hh"
636 #include "G4ProductionCuts.hh"
637 #include "G4ProductionCutsTable.hh"
638 
640 {
641  G4bool tBelowCutEnergyAndSafety = false;
642  G4int tPtclIdx
643  = G4ProductionCuts::GetIndex(aSecondary->GetDefinition());
644  if (tPtclIdx<0) { return; }
645  G4ProductionCutsTable* tCutsTbl
647  G4int tCoupleIdx
649  G4double tProdThreshold
650  = (*(tCutsTbl->GetEnergyCutsVector(tPtclIdx)))[tCoupleIdx];
651  if( aSecondary->GetKineticEnergy()<tProdThreshold )
652  {
653  tBelowCutEnergyAndSafety = true;
654  if(std::abs(aSecondary->GetDynamicParticle()->GetCharge()) > DBL_MIN)
655  {
656  G4double currentRange
658  aSecondary->GetKineticEnergy(),
660  tBelowCutEnergyAndSafety = (currentRange < CalculateSafety() );
661  }
662  }
663 
664  if( tBelowCutEnergyAndSafety )
665  {
666  if( !(aSecondary->IsGoodForTracking()) )
667  {
668 //G4cout << "!! Warning - G4SteppingManager:" << G4endl
669 //<< " This physics process generated a secondary"
670 //<< " of which energy is below cut but"
671 //<< " GoodForTracking is off !!!!!" << G4endl;
672  // Add kinetic energy to the total energy deposit
674  aSecondary->GetKineticEnergy() );
675  aSecondary->SetKineticEnergy(0.0);
676  }
677  }
678 }
679