Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/event/src/G4StackManager.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 // G4StackManager class implementation
 27 //
 28 // Author: Makoto Asai, 1996
 29 // Adding sub-event parallelism
 30 //        23/Aug/2023
 31 // --------------------------------------------------------------------
 32 
 33 #include "G4StackManager.hh"
 34 #include "G4StackingMessenger.hh"
 35 #include "G4VTrajectory.hh"
 36 #include "G4Event.hh"
 37 #include "G4ios.hh"
 38 
 39 #include "G4ParticleDefinition.hh"
 40 #include "G4VProcess.hh"
 41 
 42 // Needed for temporal service
 43 //
 44 #include "G4ParticleTable.hh"
 45 #include "G4ProcessManager.hh"
 46 #include "G4ProcessVector.hh"
 47 
 48 G4StackManager::G4StackManager()
 49 {
 50   theMessenger = new G4StackingMessenger(this);
 51 #ifdef G4_USESMARTSTACK
 52   urgentStack = new G4SmartTrackStack;
 53   // G4cout << "+++ G4StackManager uses G4SmartTrackStack. +++" << G4endl;
 54 #else
 55   urgentStack = new G4TrackStack(5000);
 56   // G4cout << "+++ G4StackManager uses ordinary G4TrackStack. +++" << G4endl;
 57 #endif
 58   waitingStack = new G4TrackStack(1000);
 59   postponeStack = new G4TrackStack(1000);
 60 }
 61 
 62 G4StackManager::~G4StackManager()
 63 {
 64   delete userStackingAction; 
 65 
 66 #ifdef G4VERBOSE
 67   if(verboseLevel>0)
 68   {
 69     G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << G4endl;
 70     G4cout << " Maximum number of tracks in the urgent stack : " << urgentStack->GetMaxNTrack() << G4endl;
 71     G4cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << G4endl;
 72   }
 73 #endif
 74   delete urgentStack;
 75   delete waitingStack;
 76   delete postponeStack;
 77   delete theMessenger;
 78   if(numberOfAdditionalWaitingStacks>0)
 79   {
 80     for(G4int i=0; i<numberOfAdditionalWaitingStacks; ++i)
 81     {
 82       delete additionalWaitingStacks[i];
 83     }
 84   }
 85 }
 86 
 87 G4int G4StackManager::
 88 PushOneTrack(G4Track* newTrack, G4VTrajectory* newTrajectory)
 89 {
 90   const G4ParticleDefinition* pd = newTrack->GetParticleDefinition();
 91   if(pd->GetParticleDefinitionID() < 0)
 92   {
 93     G4ExceptionDescription ED;
 94     ED << "A track without proper process manager is pushed \
 95            into the track stack.\n"
 96        << " Particle name : " << pd->GetParticleName() << " -- ";
 97     if(newTrack->GetParentID()==0)
 98     {
 99       ED << "created by a primary particle generator.";
100     }
101     else
102     { 
103       const G4VProcess* vp = newTrack->GetCreatorProcess();
104       if(vp != nullptr)
105       {
106         ED << "created by " << vp->GetProcessName() << ".";
107       }
108       else
109       {
110         ED << "creaded by unknown process.";
111       }
112     }
113     G4Exception("G4StackManager::PushOneTrack","Event10051",
114                  FatalException,ED);
115     delete newTrack;
116     return GetNUrgentTrack();
117   }
118     
119   DefineDefaultClassification( newTrack );
120   G4ClassificationOfNewTrack classification = fDefaultClassification;
121   if(userStackingAction!=nullptr)
122   {
123     classification = userStackingAction->ClassifyNewTrack( newTrack );
124     if(classification != fDefaultClassification)
125     {
126       if(fExceptionSeverity!=G4ExceptionSeverity::IgnoreTheIssue)
127       {
128         G4ExceptionDescription ed;
129         ed << "UserStackingAction has changed the track classification from "
130            << fDefaultClassification << " to " << classification << ". ";
131         G4Exception("G4StackManager::PushOneTrack","Event10052",
132                     fExceptionSeverity,ed);
133       }
134     }
135   }
136   if(newTrack->GetTrackStatus() == fSuspendAndWait && classification > 0)
137   // to avoid this track sent to Waiting stack again
138   { newTrack->SetTrackStatus( fSuspend ); }
139 
140 #ifdef G4VERBOSE
141   if( verboseLevel > 1 )
142   {
143     G4cout << "### Storing a track ("
144            << newTrack->GetParticleDefinition()->GetParticleName()
145            << ",trackID=" << newTrack->GetTrackID()
146            << ",parentID=" << newTrack->GetParentID() << ") ";
147     if(newTrack->GetParentID()==0)
148     { G4cout << "created by a primary particle generator "; }
149     else
150     { 
151       const G4VProcess* vp = newTrack->GetCreatorProcess();
152       if(vp != nullptr)
153       { G4cout << "created by " << vp->GetProcessName() << " "; }
154       else
155       { G4cout << "creaded by unknown process "; }
156     }
157     G4cout << "into stack #" << classification << G4endl;
158   }
159 #endif
160   G4StackedTrack newStackedTrack( newTrack, newTrajectory );
161   SortOut(newStackedTrack,classification);
162 
163   return GetNUrgentTrack();
164 }
165 
166 G4Track* G4StackManager::PopNextTrack(G4VTrajectory** newTrajectory)
167 {
168 #ifdef G4VERBOSE
169   if( verboseLevel > 1 )
170   {
171     G4cout << "### pop requested out of " 
172            << GetNUrgentTrack() << " stacked tracks." << G4endl;
173   }
174 #endif
175 
176   while( GetNUrgentTrack() == 0 )
177   {
178 #ifdef G4VERBOSE
179     if( verboseLevel > 1 )
180     {
181       G4cout << "### " << GetNWaitingTrack()
182              << " waiting tracks are re-classified to" << G4endl;
183     }
184 #endif
185     waitingStack->TransferTo(urgentStack);
186     if(numberOfAdditionalWaitingStacks>0)
187     {
188       for(G4int i=0; i<numberOfAdditionalWaitingStacks; ++i)
189       {
190         if(i==0)
191         {
192           additionalWaitingStacks[0]->TransferTo(waitingStack);
193         }
194         else
195         {
196           additionalWaitingStacks[i]->TransferTo(additionalWaitingStacks[i-1]);
197         }
198       }
199     }
200     if(userStackingAction != nullptr)
201     {
202       userStackingAction->NewStage();
203     }
204 
205 #ifdef G4VERBOSE
206     if( verboseLevel > 1 )
207       G4cout << "     " << GetNUrgentTrack()
208              << " urgent tracks and " << GetNWaitingTrack()
209              << " waiting tracks." << G4endl;
210 #endif
211     if( ( GetNUrgentTrack()==0 ) && ( GetNWaitingTrack()==0 ) )
212       return nullptr;
213   }
214 
215   G4StackedTrack selectedStackedTrack = urgentStack->PopFromStack();
216   G4Track * selectedTrack = selectedStackedTrack.GetTrack();
217   *newTrajectory = selectedStackedTrack.GetTrajectory();
218 
219 #ifdef G4VERBOSE
220   if( verboseLevel > 2 )
221   {
222     G4cout << "Selected G4StackedTrack : " << &selectedStackedTrack
223            << " with G4Track " << selectedStackedTrack.GetTrack()
224            << " (trackID " << selectedStackedTrack.GetTrack()->GetTrackID()
225            << ", parentID " << selectedStackedTrack.GetTrack()->GetParentID()
226            << ")" << G4endl;
227   }
228 #endif
229 
230   return selectedTrack;
231 }
232 
233 void G4StackManager::ReClassify()
234 {
235   G4StackedTrack aStackedTrack;
236   G4TrackStack tmpStack;
237   
238   if( userStackingAction == nullptr ) return;
239   if( GetNUrgentTrack() == 0 ) return;
240   
241   urgentStack->TransferTo(&tmpStack);
242   while( tmpStack.GetNTrack() > 0 )
243   {
244     aStackedTrack=tmpStack.PopFromStack();
245     DefineDefaultClassification( aStackedTrack.GetTrack() );
246     G4ClassificationOfNewTrack classification = fDefaultClassification;
247     if(userStackingAction!=nullptr)
248     {
249       classification = userStackingAction->ClassifyNewTrack( aStackedTrack.GetTrack() );
250       if(classification != fDefaultClassification)
251       {
252         if(fExceptionSeverity!=G4ExceptionSeverity::IgnoreTheIssue)
253         {
254           G4ExceptionDescription ed;
255           ed << "UserStackingAction has changed the track classification from "
256              << fDefaultClassification << " to " << classification << ". ";
257           G4Exception("G4StackManager::PushOneTrack","Event10052",
258                       fExceptionSeverity,ed);
259         }
260       }
261     }
262     if(aStackedTrack.GetTrack()->GetTrackStatus() == fSuspendAndWait && classification > 0)
263     // to avoid this track sent to Waiting stack again
264     { aStackedTrack.GetTrack()->SetTrackStatus( fSuspend ); }
265 
266     SortOut(aStackedTrack,classification);
267   }
268 }
269 
270 G4int G4StackManager::PrepareNewEvent(G4Event* currentEvent)
271 {
272   if(userStackingAction != nullptr)
273   {
274     userStackingAction->PrepareNewEvent();
275   }
276   
277   // Set the urgentStack in a defined state. Not doing it would
278   // affect reproducibility
279   //
280   urgentStack->clearAndDestroy();
281   
282   G4int n_passedFromPrevious = 0;
283   
284   if( GetNPostponedTrack() > 0 )
285   {
286 #ifdef G4VERBOSE
287     if( verboseLevel > 1 )
288     {
289       G4cout << GetNPostponedTrack()
290              << " postponed tracked are now shifted to the stack." << G4endl;
291     }
292 #endif
293     
294     G4StackedTrack aStackedTrack;
295     G4TrackStack   tmpStack;
296     
297     postponeStack->TransferTo(&tmpStack);
298     
299     while( tmpStack.GetNTrack() > 0 )
300     {
301       aStackedTrack=tmpStack.PopFromStack();
302       G4Track* aTrack = aStackedTrack.GetTrack();
303       DefineDefaultClassification( aTrack );
304       G4ClassificationOfNewTrack classification = fDefaultClassification;
305       if(userStackingAction!=nullptr)
306       {
307         classification = userStackingAction->ClassifyNewTrack( aTrack );
308         if(classification != fDefaultClassification)
309         {
310           if(fExceptionSeverity!=G4ExceptionSeverity::IgnoreTheIssue)
311           {
312             G4ExceptionDescription ed;
313             ed << "UserStackingAction has changed the track classification from "
314                << fDefaultClassification << " to " << classification << ". ";
315             G4Exception("G4StackManager::PushOneTrack","Event10052",
316                         fExceptionSeverity,ed);
317           }
318         }
319       }
320       if(classification!=fKill)
321       {
322         aTrack->SetParentID(-1);
323         aTrack->SetTrackID(-(++n_passedFromPrevious)); 
324       }
325       else if(aTrack->GetTrackStatus() == fSuspendAndWait && classification > 0)
326       // to avoid this track sent to Waiting stack again
327       { aTrack->SetTrackStatus( fSuspend ); }
328 
329       SortOut(aStackedTrack,classification);
330     }
331   }
332 
333   // Reset sub-event stacks for a new event
334   for(auto& ses : subEvtStackMap)
335   { ses.second->PrepareNewEvent(currentEvent); }
336 
337   return n_passedFromPrevious;
338 }
339 
340 void G4StackManager::SortOut(G4StackedTrack& aStackedTrack, G4ClassificationOfNewTrack classification)
341 {
342   if(classification==fKill)   // delete the without stacking
343   {
344     G4Track* newTrack = aStackedTrack.GetTrack();
345     G4VTrajectory* newTrajectory = aStackedTrack.GetTrajectory();
346 #ifdef G4VERBOSE
347     if( verboseLevel > 1 )
348     {
349       G4cout << "   ---> G4Track " << newTrack << " (trackID "
350              << newTrack->GetTrackID() << ", parentID "
351              << newTrack->GetParentID() << ") is not to be stored." << G4endl;
352     }
353 #endif
354     delete newTrack;
355     delete newTrajectory;
356   }
357   else
358   {
359     switch (classification)
360     {
361       case fUrgent:
362         urgentStack->PushToStack( aStackedTrack );
363         break;
364       case fWaiting:
365         waitingStack->PushToStack( aStackedTrack );
366         break;
367       case fPostpone:
368         postponeStack->PushToStack( aStackedTrack );
369         break;
370       default:
371         if(classification < 100)
372         {
373           // pushing to additional waiting stack
374           G4int i = classification - 10;
375           if(i<1 || i>numberOfAdditionalWaitingStacks)
376           {
377             G4ExceptionDescription ED;
378             ED << "invalid classification " << classification << G4endl;
379             G4Exception("G4StackManager::SortOut", "Event0051",
380                         FatalException,ED);
381           }
382           else
383           {
384             additionalWaitingStacks[i-1]->PushToStack( aStackedTrack );
385           }
386         }
387         else
388         {
389           // pushing to sub-event stack
390           G4int ty = classification - 100;
391           auto ses = subEvtStackMap.find(ty);
392           if(ses==subEvtStackMap.end())
393           {
394             G4ExceptionDescription ED;
395             ED << "invalid classification " << classification << G4endl;
396             G4Exception("G4StackManager::SortOut", "Event0051",
397                         FatalException,ED);
398           }
399           else
400           {
401             ses->second->PushToStack( aStackedTrack );
402           }
403         }
404         break;
405     }
406   }
407 }
408 
409 void G4StackManager::SetNumberOfAdditionalWaitingStacks(G4int iAdd)
410 {
411   if(iAdd > numberOfAdditionalWaitingStacks)
412   {
413     for(G4int i=numberOfAdditionalWaitingStacks; i<iAdd; ++i)
414     {
415       auto* newStack = new G4TrackStack;
416       additionalWaitingStacks.push_back(newStack);
417     }
418     numberOfAdditionalWaitingStacks = iAdd;
419   }
420   else if (iAdd < numberOfAdditionalWaitingStacks)
421   {
422     for(G4int i=numberOfAdditionalWaitingStacks; i>iAdd; --i)
423     {
424       delete additionalWaitingStacks[i];
425     }
426   }
427 }
428 
429 void G4StackManager::
430 TransferStackedTracks(G4ClassificationOfNewTrack origin,
431                       G4ClassificationOfNewTrack destination)
432 {
433   if(origin==destination) return;
434   if(origin==fKill) return;
435   G4TrackStack* originStack = nullptr;
436   switch(origin)
437   {
438     case fUrgent:
439       originStack = nullptr;
440       break;
441     case fWaiting:
442       originStack = waitingStack;
443       break;
444     case fPostpone:
445       originStack = postponeStack;
446       break;
447     default:
448       G4int i = origin - 10;
449       if(i<=numberOfAdditionalWaitingStacks)
450       {
451         originStack = additionalWaitingStacks[i-1];
452       }
453       else
454       {
455         G4ExceptionDescription ED;
456         ED << "Invalid origin stack ID " << origin;
457         G4Exception("G4StackManager::TransferStackedTracks","Stack0911",
458                     FatalException, ED);
459       }
460       break;
461   }
462   
463   if(destination==fKill)
464   {
465     if(originStack != nullptr)
466     {
467       originStack->clearAndDestroy();
468     }
469     else
470     {
471       urgentStack->clearAndDestroy();
472     }
473   }
474   else
475   {
476     G4TrackStack* targetStack = nullptr;
477     switch(destination)
478     {
479       case fUrgent:
480         targetStack = nullptr;
481         break;
482       case fWaiting:
483         targetStack = waitingStack;
484         break;
485       case fPostpone:
486         targetStack = postponeStack;
487         break;
488       default:
489         G4int i = destination - 10;
490         if(i<=numberOfAdditionalWaitingStacks)
491         {
492           targetStack = additionalWaitingStacks[i-1];
493         }
494         else
495         {
496           G4ExceptionDescription ED;
497           ED << "Invalid origin stack ID " << origin;
498           G4Exception("G4StackManager::TransferStackedTracks","Stack0911",
499                       FatalException, ED);
500         }
501         break;
502     }
503     if(originStack != nullptr)
504     {
505       if(targetStack != nullptr)
506       {
507         originStack->TransferTo(targetStack);
508       }
509       else
510       {
511         originStack->TransferTo(urgentStack);
512       }
513     }
514     else
515     {
516       urgentStack->TransferTo(targetStack);
517     }
518   }
519   return;
520 }
521 
522 void G4StackManager::
523 TransferOneStackedTrack(G4ClassificationOfNewTrack origin,
524                         G4ClassificationOfNewTrack destination)
525 {
526   if(origin==destination) return;
527   if(origin==fKill) return;
528   G4TrackStack* originStack = nullptr;
529   switch(origin)
530   {
531     case fUrgent:
532       originStack = nullptr;
533       break;
534     case fWaiting:
535       originStack = waitingStack;
536       break;
537     case fPostpone:
538       originStack = postponeStack;
539       break;
540     default:
541       G4int i = origin - 10;
542       if(i<=numberOfAdditionalWaitingStacks)
543       {
544         originStack = additionalWaitingStacks[i-1];
545       }
546       else
547       {
548         G4ExceptionDescription ED;
549         ED << "Invalid origin stack ID " << origin;
550         G4Exception("G4StackManager::TransferStackedTracks","Stack0911",
551                     FatalException, ED);
552       }
553       break;
554   }
555   
556   G4StackedTrack aStackedTrack;
557   if(destination==fKill)
558   {
559     if( originStack != nullptr && (originStack->GetNTrack() != 0u) )
560     {
561       aStackedTrack = originStack->PopFromStack();
562       delete aStackedTrack.GetTrack();
563       delete aStackedTrack.GetTrajectory();
564     }
565     else if (urgentStack->GetNTrack() != 0u )
566     {
567       aStackedTrack = urgentStack->PopFromStack();
568       delete aStackedTrack.GetTrack();
569       delete aStackedTrack.GetTrajectory();
570     }
571   }
572   else
573   {
574     G4TrackStack* targetStack = nullptr;
575     switch(destination)
576     {
577       case fUrgent:
578         targetStack = nullptr;
579         break;
580       case fWaiting:
581         targetStack = waitingStack;
582         break;
583       case fPostpone:
584         targetStack = postponeStack;
585         break;
586       default:
587         G4int i = destination - 10;
588         if(i<=numberOfAdditionalWaitingStacks)
589         {
590           targetStack = additionalWaitingStacks[i-1];
591         }
592         else
593         {
594           G4ExceptionDescription ED;
595           ED << "Invalid destination stack ID " << destination;
596           G4Exception("G4StackManager::TransferStackedTracks","Stack0911",
597                       FatalException, ED);
598         }
599         break;
600     }
601     if((originStack != nullptr) && (originStack->GetNTrack() != 0u))
602     {
603       aStackedTrack = originStack->PopFromStack();
604       if(targetStack != nullptr) { targetStack->PushToStack(aStackedTrack); }
605       else            { urgentStack->PushToStack(aStackedTrack); }
606     }
607     else if(urgentStack->GetNTrack() != 0u)
608     {
609       aStackedTrack = urgentStack->PopFromStack();
610       if(targetStack != nullptr) { targetStack->PushToStack(aStackedTrack); }
611       else            { urgentStack->PushToStack(aStackedTrack); }
612     }
613   }
614   return;
615 }
616 
617 void G4StackManager::clear()
618 {
619   ClearUrgentStack();
620   ClearWaitingStack();
621   for(G4int i=1; i<=numberOfAdditionalWaitingStacks; ++i)
622   {
623     ClearWaitingStack(i);
624   }
625 }
626 
627 void G4StackManager::ClearUrgentStack()
628 {
629   urgentStack->clearAndDestroy();
630 }
631 
632 void G4StackManager::ClearWaitingStack(G4int i)
633 {
634   if(i==0)
635   {
636     waitingStack->clearAndDestroy();
637   }
638   else
639   {
640     if(i<=numberOfAdditionalWaitingStacks)
641     {
642       additionalWaitingStacks[i-1]->clearAndDestroy();
643     }
644   }
645 }
646 
647 void G4StackManager::ClearPostponeStack()
648 {
649   postponeStack->clearAndDestroy();
650 }
651 
652 G4int G4StackManager::GetNTotalTrack() const
653 {
654   std::size_t n = urgentStack->GetNTrack()
655                 + waitingStack->GetNTrack()
656                 + postponeStack->GetNTrack();
657   for(G4int i=1; i<=numberOfAdditionalWaitingStacks; ++i)
658   {
659     n += additionalWaitingStacks[i-1]->GetNTrack();
660   }
661   return G4int(n);
662 }
663 
664 G4int G4StackManager::GetNUrgentTrack() const
665 {
666   return (G4int)urgentStack->GetNTrack();
667 }
668 
669 G4int G4StackManager::GetNWaitingTrack(int i) const
670 {
671   if(i==0)
672   {
673     return (G4int)waitingStack->GetNTrack();
674   }
675   
676   if(i<=numberOfAdditionalWaitingStacks)
677   {
678     return (G4int)additionalWaitingStacks[i-1]->GetNTrack();
679   }
680  
681   return 0;
682 }
683 
684 G4int G4StackManager::GetNPostponedTrack() const
685 {
686   return (G4int)postponeStack->GetNTrack();
687 }
688 
689 void G4StackManager::SetVerboseLevel( G4int const value )
690 {
691   verboseLevel = value;
692   for(auto& sets : subEvtStackMap)
693   { sets.second->SetVerboseLevel(value); }
694 }
695 
696 void G4StackManager::SetUserStackingAction(G4UserStackingAction* value)
697 {
698   userStackingAction = value;
699   if(userStackingAction != nullptr)
700   {
701     userStackingAction->SetStackManager(this);
702   }
703 }
704 
705 void G4StackManager::DefineDefaultClassification(const G4Track* aTrack)
706 {
707   fDefaultClassification = fUrgent;
708   fExceptionSeverity = G4ExceptionSeverity::IgnoreTheIssue;
709 
710   if(defClassPartDef.size()>0)
711   {
712     auto pdm = defClassPartDef.find(aTrack->GetParticleDefinition());
713     if(pdm!=defClassPartDef.end())
714     {
715       fDefaultClassification = pdm->second.first;
716       fExceptionSeverity = pdm->second.second;
717     }
718   }
719   else if(defClassTrackStatus.size()>0)
720   {
721     auto tsm = defClassTrackStatus.find(aTrack->GetTrackStatus());
722     if(tsm!=defClassTrackStatus.end()) 
723     {
724       fDefaultClassification = tsm->second.first;
725       fExceptionSeverity = tsm->second.second;
726     }
727   }
728   else if( aTrack->GetTrackStatus() == fSuspendAndWait )
729   { fDefaultClassification = fWaiting; }
730   else if( aTrack->GetTrackStatus() == fPostponeToNextEvent )
731   { fDefaultClassification = fPostpone; }
732 }
733 
734 void G4StackManager::SetDefaultClassification(G4TrackStatus ts,
735              G4ClassificationOfNewTrack val, G4ExceptionSeverity es)
736 {
737   auto tsm = defClassTrackStatus.find(ts);
738   if(tsm==defClassTrackStatus.end())
739   { defClassTrackStatus[ts] = std::pair(val,es); }
740   else
741   {
742     if(tsm->second.first!=val)
743     { // alternating default classification
744       G4ExceptionDescription ed;
745       ed << "Default classification for track status " << ts 
746          << " is changed from " << tsm->second.first << " to "
747          << val << ".";
748       G4Exception("G4StackManager::SetDefaultClassification",
749                   "Event11051",JustWarning,ed);
750       tsm->second.first = val;
751     }
752     // Change severity if needed.
753     if(tsm->second.second>es) tsm->second.second = es;
754   }
755 }
756 
757 void G4StackManager::SetDefaultClassification(const G4ParticleDefinition* pd,
758              G4ClassificationOfNewTrack val, G4ExceptionSeverity es)
759 {
760   auto pdm = defClassPartDef.find(pd);
761   if(pdm==defClassPartDef.end())
762   { defClassPartDef[pd] = std::pair(val,es); }
763   else
764   {
765     if(pdm->second.first!=val)
766     { // alternating default classification
767       G4ExceptionDescription ed;
768       ed << "Default classification for particle " << pd->GetParticleName()
769          << " is changed from " << pdm->second.first << " to "
770          << val << ".";
771       G4Exception("G4StackManager::SetDefaultClassification",
772                   "Event11052", JustWarning,ed);
773       pdm->second.first = val;
774     }
775     // Change severity if needed.
776     if(pdm->second.second>es) pdm->second.second = es;
777   }
778 }
779 
780 void G4StackManager::RegisterSubEventType(G4int ty, G4int maxEnt)
781 {
782   if(subEvtStackMap.find(ty)==subEvtStackMap.end())
783   {
784     subEvtStackMap[ty] = new G4SubEventTrackStack(ty,maxEnt);
785     subEvtTypes.push_back(ty);
786 #ifdef G4VERBOSE
787     subEvtStackMap[ty]->SetVerboseLevel(verboseLevel);
788     if( verboseLevel > 0 )
789     {
790       G4cout << "   ---> New sub-event stack for sub-event type "
791              << ty << " is created. Classification id for this stack is "
792              << subEvtTypes.size() + 99 << "." << G4endl;
793     }
794   }
795   else
796   {
797     if( verboseLevel > 1 )
798     {
799       G4cout << "   ---> Sub-event stack for sub-event type "
800              << ty << " already registered." << G4endl;
801     }
802 #endif  
803   }
804 }
805 
806 void G4StackManager::ReleaseSubEvent(G4int ty)
807 {
808   auto ses = subEvtStackMap.find(ty);
809   if(ses==subEvtStackMap.end())
810   {
811     G4ExceptionDescription ED;
812     ED << "Un-registered sub-event type " << ty << " requested.";
813     G4Exception("G4StackManager::PopSubEvent", "SubEvt8001",
814                  FatalException,ED);
815     return; // NOLINT: Required to silence Coverity, which does not recognize G4Exception as exit point
816   }
817 
818   ses->second->ReleaseSubEvent();
819 }
820 
821 
822