Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/management/src/G4Scheduler.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 //
 27 // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
 28 //
 29 // History:
 30 // -----------
 31 // 10 Oct 2011 M.Karamitros created
 32 //
 33 // -------------------------------------------------------------------
 34 
 35 #include "G4ITGun.hh"
 36 #include "G4ITModelHandler.hh"
 37 #include "G4ITModelProcessor.hh"
 38 #include "G4ITStepProcessor.hh"
 39 #include "G4ITStepStatus.hh"
 40 #include "G4ITTrackingInteractivity.hh"
 41 #include "G4ITTrackingManager.hh"
 42 #include "G4IosFlagsSaver.hh"
 43 #include "G4StateManager.hh"
 44 #include "G4SystemOfUnits.hh"
 45 #include "G4Timer.hh"
 46 #include "G4TrackingInformation.hh"
 47 #include "G4UnitsTable.hh"
 48 #include "G4UserTimeStepAction.hh"
 49 #include "G4VITStepModel.hh"
 50 
 51 #include <G4AllITFinder.hh>
 52 #include <G4Scheduler.hh>
 53 #include <G4SchedulerMessenger.hh>
 54 
 55 #include <sstream>
 56 
 57 #define DEBUG_MEM_STEPPING
 58 #define DEBUG_MEM_DETAILED_STEPPING
 59 
 60 #ifdef DEBUG_MEM
 61 #  include "G4MemStat.hh"
 62 using namespace G4MemStat;
 63 using G4MemStat::MemStat;
 64 #endif
 65 
 66 #ifdef USE_COLOR
 67 #  define RED "\033[0;31m"
 68 #  define LIGHT_RED "\33[1;31m"
 69 #  define GREEN "\033[32;40m"
 70 #  define GREEN_ON_BLUE "\033[1;32;44m"
 71 #  define RESET_COLOR "\033[0m"
 72 #else
 73 #  define RED ""
 74 #  define LIGHT_RED ""
 75 #  define GREEN ""
 76 #  define GREEN_ON_BLUE ""
 77 #  define RESET_COLOR ""
 78 #endif
 79 
 80 using namespace std;
 81 
 82 G4ThreadLocal G4Scheduler* G4Scheduler::fgScheduler(nullptr);
 83 
 84 template<typename T>
 85 inline G4bool IsInf(T value)
 86 {
 87   return std::numeric_limits<T>::has_infinity && value == std::numeric_limits<T>::infinity();
 88 }
 89 //_________________________________________________________________________
 90 
 91 G4Scheduler* G4Scheduler::Instance()
 92 {
 93   if (fgScheduler == nullptr) fgScheduler = new G4Scheduler();
 94   return fgScheduler;
 95 }
 96 //_________________________________________________________________________
 97 
 98 G4bool G4Scheduler::Notify(G4ApplicationState requestedState)
 99 {
100   if (requestedState == G4State_Quit) {
101     if (fVerbose >= 4) {
102       G4cout << "G4Scheduler received G4State_Quit" << G4endl;
103     }
104     Clear();
105   }
106   return true;
107 }
108 //_________________________________________________________________________
109 
110 void G4Scheduler::DeleteInstance()
111 {
112   delete fgScheduler;
113 }
114 //_________________________________________________________________________
115 
116 G4Scheduler::G4Scheduler() : fTrackContainer((G4ITTrackHolder&)*G4ITTrackHolder::Instance())
117 {
118   Create();
119 }
120 
121 void G4Scheduler::Create()
122 {
123   fUseDefaultTimeSteps = true;
124   fUserUpperTimeLimit = -1;
125   fpGun = nullptr;
126   fContinue = true;
127   fpTrackingInteractivity = nullptr;
128   fITStepStatus = eUndefined;
129   fpUserTimeSteps = nullptr;
130   fTimeStep = DBL_MAX;
131   fTSTimeStep = DBL_MAX;
132   fILTimeStep = DBL_MAX;
133   fPreviousTimeStep = DBL_MAX;
134   fZeroTimeCount = 0;
135   fMaxNZeroTimeStepsAllowed = 10000;
136   fStartTime = 0;
137   fTimeTolerance = 1 * picosecond;
138   fEndTime = 1 * microsecond;
139   fGlobalTime = -1;
140   fInteractionStep = true;
141   fUsePreDefinedTimeSteps = false;
142 
143   fDefaultMinTimeStep = 1 * picosecond;
144   fpStepProcessor = nullptr;
145   fpModelProcessor = nullptr;
146   fNbSteps = 0;
147   fMaxSteps = -1;
148   fRunning = false;
149   fInitialized = false;
150   fpUserTimeStepAction = nullptr;
151   fpModelHandler = new G4ITModelHandler();
152   fpTrackingManager = new G4ITTrackingManager();
153   fVerbose = 0;
154   fWhyDoYouStop = false;
155   fDefinedMinTimeStep = -1.;
156   fReachedUserTimeLimit = false;
157   fStopTime = -1.;
158   fpMessenger = new G4SchedulerMessenger(this);
159   fReactionSet = G4ITReactionSet::Instance();
160   fMaxTimeStep = DBL_MAX;
161   // hoang add
162   fResetScavenger = true;  // true by default
163   G4ITTypeManager::Instance()->ReserveRessource();
164 }
165 
166 //_________________________________________________________________________
167 
168 G4Scheduler::~G4Scheduler()
169 {
170   if (fpMessenger != nullptr)  // is used as a flag to know whether the manager was cleared
171   {
172     Clear();
173   }
174   fgScheduler = nullptr;
175 }
176 
177 void G4Scheduler::Clear()
178 {
179   if (fpMessenger != nullptr) {
180     delete fpMessenger;
181     fpMessenger = nullptr;
182   }
183   if (fpStepProcessor != nullptr) {
184     delete fpStepProcessor;
185     fpStepProcessor = nullptr;
186   }
187   if (fpModelProcessor != nullptr) {
188     delete fpModelProcessor;
189     fpModelProcessor = nullptr;
190   }
191 
192   G4ITTypeManager::Instance()->ReleaseRessource();
193   ClearList();
194   if (fpTrackingManager != nullptr) {
195     delete fpTrackingManager;
196     fpTrackingManager = nullptr;
197   }
198 
199   if (fReactionSet != nullptr) {
200     delete fReactionSet;
201     fReactionSet = nullptr;
202   }
203 
204   if (fpModelHandler != nullptr) {
205     delete fpModelHandler;
206     fpModelHandler = nullptr;
207   }
208 }
209 
210 //_________________________________________________________________________
211 
212 void G4Scheduler::ClearList()
213 {
214   fTrackContainer.Clear();
215   G4AllITFinder::DeleteInstance();
216 }
217 
218 //_________________________________________________________________________
219 void G4Scheduler::RegisterModel(G4VITStepModel* model, G4double time)
220 {
221   fpModelHandler->RegisterModel(model, time);
222 }
223 
224 //_________________________________________________________________________
225 
226 void G4Scheduler::Initialize()
227 {
228   delete fpStepProcessor;
229   delete fpModelProcessor;
230 
231   fpModelProcessor = new G4ITModelProcessor();
232   fpModelProcessor->SetModelHandler(fpModelHandler);
233   fpModelProcessor->SetTrackingManager(fpTrackingManager);
234   fpStepProcessor = new G4ITStepProcessor();
235   fpStepProcessor->SetTrackingManager(fpTrackingManager);
236   fpTrackingManager->SetInteractivity(fpTrackingInteractivity);
237   if (fUsePreDefinedTimeSteps) {
238     if (fpUserTimeSteps == nullptr)  // Extra checking, is it necessary ?
239     {
240       G4ExceptionDescription exceptionDescription;
241       exceptionDescription << "You are asking to use user defined steps but you did not give any.";
242       G4Exception("G4Scheduler::FindUserPreDefinedTimeStep", "Scheduler004", FatalErrorInArgument,
243                   exceptionDescription);
244       return;  // makes coverity happy
245     }
246   }
247 
248   fInitialized = true;
249 }
250 
251 //_________________________________________________________________________
252 
253 void G4Scheduler::Reset()
254 {
255   fStartTime = 0;
256   fUserUpperTimeLimit = -1;
257   fTimeStep = DBL_MAX;
258   fTSTimeStep = DBL_MAX;
259   fILTimeStep = DBL_MAX;
260   fPreviousTimeStep = DBL_MAX;
261   fGlobalTime = -1;
262   fInteractionStep = true;
263   fITStepStatus = eUndefined;
264   fZeroTimeCount = 0;
265 
266   fNbSteps = 0;
267   fContinue = true;
268   fReactionSet->CleanAllReaction();
269 }
270 //_________________________________________________________________________
271 
272 void G4Scheduler::Process()
273 {
274 #ifdef G4VERBOSE
275   if (fVerbose != 0) {
276     G4cout << "*** G4Scheduler starts processing " << G4endl;
277     if (fVerbose > 2)
278       G4cout << "___________________________________________"
279                 "___________________________"
280              << G4endl;
281   }
282 #endif
283 
284   if (!fInitialized) {
285     Initialize();
286   }
287   fpModelProcessor->Initialize();
288   fpStepProcessor->Initialize();
289 
290   if (fpGun != nullptr) fpGun->DefineTracks();
291 
292   if (fpTrackingInteractivity != nullptr) fpTrackingInteractivity->Initialize();
293 
294   // ___________________
295   fRunning = true;
296   Reset();
297 
298   if (fResetScavenger) {
299     if (fpUserScavenger != nullptr) {
300       fpUserScavenger->Reset();
301     }
302   }
303 
304   if (fpUserTimeStepAction != nullptr) {
305     fpUserTimeStepAction->StartProcessing();
306   }
307 
308 #ifdef G4VERBOSE
309   G4bool trackFound = false;
310   G4IosFlagsSaver iosfs(G4cout);
311   G4cout.precision(5);
312 #endif
313 
314   //===========================================================================
315   // By default, before the G4Scheduler is launched, the tracks are pushed to
316   // the delayed lists
317   //===========================================================================
318 
319   if (fTrackContainer.DelayListsNOTEmpty()) {
320     fStartTime = fTrackContainer.GetNextTime();
321 #ifdef G4VERBOSE
322     trackFound = true;
323     G4Timer localtimer;
324     if (fVerbose > 1) {
325       localtimer.Start();
326     }
327 #endif
328     SynchronizeTracks();
329 #ifdef G4VERBOSE
330     if (fVerbose > 1) {
331       localtimer.Stop();
332       G4cout << "G4Scheduler: process time= " << localtimer << G4endl;
333     }
334 #endif
335   }
336 #ifdef G4VERBOSE
337   if (fVerbose != 0) {
338     if (trackFound) {
339       G4cout << "*** G4Scheduler ends at time : " << G4BestUnit(fGlobalTime, "Time") << G4endl;
340       G4cout << "___________________________________" << G4endl;
341     }
342     else {
343       G4cout << "*** G4Scheduler did not start because no "
344                 "track was found to be processed"
345              << G4endl;
346       G4cout << "___________________________________" << G4endl;
347     }
348   }
349 #endif
350 
351   fRunning = false;
352 
353   if (fpUserTimeStepAction != nullptr) {
354     fpUserTimeStepAction->EndProcessing();
355   }
356   // ___________________
357   EndTracking();
358   ClearList();
359   Reset();
360 
361   if (fpTrackingInteractivity != nullptr) {
362     fpTrackingInteractivity->Finalize();
363   }
364 }
365 
366 //_________________________________________________________________________
367 
368 G4double G4Scheduler::GetNextWatchedTime() const
369 {
370   auto up = fWatchedTimes.upper_bound(fGlobalTime);
371   if (up == fWatchedTimes.end()) {
372     return DBL_MAX;
373   }
374   return *up;
375 }
376 
377 //_________________________________________________________________________
378 
379 void G4Scheduler::SynchronizeTracks()
380 {
381   fGlobalTime = fTrackContainer.GetNextTime();
382   G4double tmpGlobalTime = fGlobalTime;
383   G4double nextWatchedTime = -1;
384   G4bool carryOn = true;
385   while (fTrackContainer.MergeNextTimeToMainList(tmpGlobalTime) && carryOn) {
386     if (tmpGlobalTime != fGlobalTime) {
387       fGlobalTime = tmpGlobalTime;
388     };
389     fStopTime = min(fTrackContainer.GetNextTime(), fEndTime);
390     while ((nextWatchedTime = GetNextWatchedTime()) < fTrackContainer.GetNextTime()
391            && (carryOn = CanICarryOn()))
392     {
393       fStopTime = min(nextWatchedTime, fEndTime);
394       DoProcess();
395     }
396 
397     carryOn = CanICarryOn();
398 
399     if (nextWatchedTime > fEndTime && carryOn) {
400       fStopTime = min(fTrackContainer.GetNextTime(), fEndTime);
401       DoProcess();
402     }
403   }
404 }
405 
406 //_________________________________________________________________________
407 
408 G4bool G4Scheduler::CanICarryOn()
409 {
410   return fGlobalTime < fEndTime && (fMaxSteps == -1 ? true : fNbSteps < fMaxSteps) && fContinue;
411 }
412 
413 //_________________________________________________________________________
414 
415 void G4Scheduler::PrintWhyDoYouStop()
416 {
417 #ifdef G4VERBOSE
418   if (fWhyDoYouStop) {
419     G4cout << "G4Scheduler has reached a stage: it might be"
420               " a transition or the end"
421            << G4endl;
422 
423     G4bool normalStop = false;
424 
425     if (fGlobalTime >= fStopTime) {
426       G4cout << "== G4Scheduler: I stop because I reached the stop time : "
427              << G4BestUnit(fStopTime, "Time") << " ==" << G4endl;
428       normalStop = true;
429     }
430     if (!fTrackContainer.MainListsNOTEmpty())  // is empty
431     {
432       G4cout << "G4Scheduler: I stop because the current main list of tracks "
433                 "is empty"
434              << G4endl;
435       normalStop = true;
436     }
437     if (fMaxSteps == -1 ? false : fNbSteps >= fMaxSteps) {
438       G4cout << "G4Scheduler: I stop because I reached the maximum allowed "
439                 "number of steps="
440              << fMaxSteps << G4endl;
441       normalStop = true;
442     }
443     if (fContinue && !normalStop) {
444       G4cout << "G4Scheduler: It might be that I stop because "
445                 "I have been told so. You may check "
446                 "member fContinue and usage of the method G4Scheduler::Stop()."
447              << G4endl;
448     }
449   }
450 #endif
451 }
452 
453 //_________________________________________________________________________
454 
455 void G4Scheduler::DoProcess()
456 {
457   if (fpUserTimeStepAction != nullptr) fpUserTimeStepAction->NewStage();
458 
459 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_STEPPING)
460   MemStat mem_first, mem_second, mem_diff;
461 #endif
462 
463 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_STEPPING)
464   mem_first = MemoryUsage();
465 #endif
466 
467   while (fGlobalTime < fStopTime && fTrackContainer.MainListsNOTEmpty()
468          && (fMaxSteps == -1 ? true : fNbSteps < fMaxSteps) && fContinue)
469   {
470     Stepping();
471 
472 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_STEPPING)
473     mem_second = MemoryUsage();
474     mem_diff = mem_second - mem_first;
475     G4cout << "\t || MEM || After step " << fNbSteps << ", diff is : " << mem_diff << G4endl;
476 #endif
477   }
478 
479   PrintWhyDoYouStop();
480 
481 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_STEPPING)
482   mem_second = MemoryUsage();
483   mem_diff = mem_second - mem_first;
484   G4cout << "\t || MEM || After stepping, diff is : " << mem_diff << G4endl;
485 #endif
486 
487 #ifdef G4VERBOSE
488   if (fVerbose > 2)
489     G4cout << "*** G4Scheduler has finished processing a track list at time : "
490            << G4BestUnit(fGlobalTime, "Time") << G4endl;
491 #endif
492 }
493 //_________________________________________________________________________
494 
495 void G4Scheduler::Stepping()
496 {
497   fTimeStep = fMaxTimeStep;
498 
499   fTSTimeStep = DBL_MAX;
500   fILTimeStep = DBL_MAX;
501 
502   fInteractionStep = false;
503   fReachedUserTimeLimit = false;
504 
505   fITStepStatus = eUndefined;
506 
507   // Start of step
508 #ifdef G4VERBOSE
509   if (fVerbose > 2) {
510 #  ifdef USE_COLOR
511     G4cout << LIGHT_RED;
512 #  endif
513     G4cout << "*** Start Of Step N°" << fNbSteps + 1 << " species number : " << GetNTracks()
514            << " ***" << G4endl;
515     G4cout << "Current Global time : " << G4BestUnit(fGlobalTime, "Time") << G4endl;
516 #  ifdef USE_COLOR
517     G4cout << RESET_COLOR;
518 #  endif
519   }
520 #endif
521 
522 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
523   MemStat mem_first, mem_second, mem_diff;
524 #endif
525 
526 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
527   mem_first = MemoryUsage();
528 #endif
529 
530   fDefinedMinTimeStep = GetLimitingTimeStep();
531 
532   if (fUsePreDefinedTimeSteps) {
533 #ifdef G4VERBOSE
534     if (fVerbose > 2) {
535 #  ifdef USE_COLOR
536       G4cout << LIGHT_RED;
537 #  endif
538       G4cout << "*** At time : " << G4BestUnit(fGlobalTime, "Time")
539              << " the chosen user time step is : " << G4BestUnit(fDefinedMinTimeStep, "Time")
540              << " ***" << G4endl;
541 #  ifdef USE_COLOR
542       G4cout << RESET_COLOR;
543 #  endif
544     }
545 #endif
546   }
547 
548   if (fpModelProcessor->GetComputeTimeStep())  // fComputeTimeStep)
549   {
550     fTSTimeStep = fpModelProcessor->CalculateMinTimeStep(fGlobalTime, fDefinedMinTimeStep);
551     // => at least N (N = nb of tracks) loops
552   }
553   else if (fUseDefaultTimeSteps) {
554     fTSTimeStep = fDefinedMinTimeStep;
555   }
556 
557 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
558   mem_second = MemoryUsage();
559   mem_diff = mem_second - mem_first;
560   G4cout << "|| MEM || After computing TS, diff is : " << mem_diff << G4endl;
561 #endif
562 
563 #ifdef G4VERBOSE
564   if (fVerbose > 2) {
565 #  ifdef USE_COLOR
566     G4cout << LIGHT_RED;
567 #  endif
568     G4cout << "*** Time stepper returned : " << G4BestUnit(fTSTimeStep, "Time") << " ***" << G4endl;
569 #  ifdef USE_COLOR
570     G4cout << RESET_COLOR;
571 #  endif
572   }
573 #endif
574 
575 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
576   mem_first = MemoryUsage();
577 #endif
578 
579   // Call IL even if fTSTimeStep == 0
580   // if fILTimeStep == 0 give the priority to DoIt processes
581 
582   fILTimeStep = fpStepProcessor->ComputeInteractionLength(fPreviousTimeStep);
583   // => at least N loops
584   // All process returns the physical step of interaction
585   // The transportation process calculates the corresponding
586   // time step
587 
588 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
589   mem_second = MemoryUsage();
590   mem_diff = mem_second - mem_first;
591   G4cout << "|| MEM || After IL, diff is : " << mem_diff << G4endl;
592 #endif
593 
594 #ifdef G4VERBOSE
595   if (fVerbose > 2) {
596 #  ifdef USE_COLOR
597     G4cout << LIGHT_RED;
598 #  endif
599     G4cout << "*** The minimum time returned by the processes is : "
600            << G4BestUnit(fILTimeStep, "Time") << " ***" << G4endl;
601 #  ifdef USE_COLOR
602     G4cout << RESET_COLOR;
603 #  endif
604   }
605 #endif
606 
607 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
608   mem_first = MemoryUsage();
609 #endif
610 
611   if (fILTimeStep <= fTSTimeStep)
612   // Give the priority to the IL
613   {
614     fInteractionStep = true;
615     fReactionSet->CleanAllReaction();
616     fTimeStep = fILTimeStep;
617     fITStepStatus = eInteractionWithMedium;
618     fpStepProcessor->PrepareLeadingTracks();
619   }
620   else {
621     fInteractionStep = false;
622     fpStepProcessor->ResetLeadingTracks();
623     fTimeStep = fTSTimeStep;
624     fITStepStatus = eCollisionBetweenTracks;
625   }
626 
627   if (fGlobalTime + fTimeStep > fStopTime)
628   // This check is done at every time step
629   {
630     fTimeStep = fStopTime - fGlobalTime;
631     fITStepStatus = eInteractionWithMedium;  // ie: transportation
632     fInteractionStep = true;
633     fReactionSet->CleanAllReaction();
634     fpStepProcessor->ResetLeadingTracks();
635   }
636 
637   if (fTimeStep == 0)  // < fTimeTolerance)
638   {
639     ++fZeroTimeCount;
640     if (fZeroTimeCount >= fMaxNZeroTimeStepsAllowed) {
641       G4ExceptionDescription exceptionDescription;
642 
643       exceptionDescription << "Too many zero time steps were detected. ";
644       exceptionDescription << "The simulation is probably stuck. ";
645       exceptionDescription << "The maximum number of zero time steps is currently : "
646                            << fMaxNZeroTimeStepsAllowed;
647       exceptionDescription << ".";
648 
649       G4Exception("G4Scheduler::Stepping", "SchedulerNullTimeSteps", FatalErrorInArgument,
650                   exceptionDescription);
651     }
652   }
653   else {
654     fZeroTimeCount = 0;
655   }
656 
657   fReachedUserTimeLimit = (fTimeStep <= fDefinedMinTimeStep)
658                           || ((fTimeStep > fDefinedMinTimeStep)
659                               && fabs(fTimeStep - fDefinedMinTimeStep) < fTimeTolerance);
660 
661   if (fpUserTimeStepAction != nullptr) fpUserTimeStepAction->UserPreTimeStepAction();
662     // TODO: pre/post
663 
664 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
665   mem_second = MemoryUsage();
666   mem_diff = mem_second - mem_first;
667   G4cout << "|| MEM || After LeadingTracks and UserPreTimeStepAction: " << mem_diff << G4endl;
668 #endif
669 
670 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
671   mem_first = MemoryUsage();
672 #endif
673 
674   fGlobalTime += fTimeStep;
675 
676   // if fTSTimeStep > 0 => still need to call the transportation process
677   // if fILTimeStep < fTSTimeStep => call only DoIt processes, no reactions
678   // if fILTimeStep == fTSTimeStep => give the priority to the DoIt processes
679   if (fTSTimeStep > 0 || fILTimeStep <= fTSTimeStep) {
680     fpStepProcessor->DoIt(fTimeStep);
681   }
682 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
683   mem_second = MemoryUsage();
684   mem_diff = mem_second - mem_first;
685   G4cout << "|| MEM || After DoIT, diff is : " << mem_diff << G4endl;
686 #endif
687 
688 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
689   mem_first = MemoryUsage();
690 #endif
691 
692   fpModelProcessor->ComputeTrackReaction(fITStepStatus, fGlobalTime, fTimeStep, fPreviousTimeStep,
693                                          fReachedUserTimeLimit, fTimeTolerance,
694                                          fpUserTimeStepAction, fVerbose);
695 
696   ++fNbSteps;
697 
698   if (fpUserTimeStepAction != nullptr) {
699     fpUserTimeStepAction->UserPostTimeStepAction();
700   }
701 
702   fPreviousTimeStep = fTimeStep;
703 
704 #if defined(DEBUG_MEM) && defined(DEBUG_MEM_DETAILED_STEPPING)
705   mem_second = MemoryUsage();
706   mem_diff = mem_second - mem_first;
707   G4cout << "|| MEM || After computing reactions + UserPostTimeStepAction, "
708             "diff is : "
709          << mem_diff << G4endl;
710 #endif
711 
712   // End of step
713 #ifdef G4VERBOSE
714   if (fVerbose >= 2) {
715 #  ifdef USE_COLOR
716     G4cout << LIGHT_RED;
717 #  endif
718 
719     G4String interactionType;
720     GetCollisionType(interactionType);
721 
722     std::stringstream finalOutput;
723 
724     finalOutput << "*** End of step N°" << fNbSteps
725                 << "\t T_i= " << G4BestUnit(fGlobalTime - fTimeStep, "Time")
726                 << "\t dt= " << G4BestUnit(fTimeStep, "Time")
727                 << "\t T_f= " << G4BestUnit(fGlobalTime, "Time") << "\t " << interactionType
728                 << G4endl;
729 
730     if (fVerbose > 2) {
731       if (fReachedUserTimeLimit) {
732         finalOutput << "It has also reached the user time limit" << G4endl;
733       }
734       finalOutput << "_______________________________________________________________"
735                      "_______"
736                   << G4endl;
737     }
738 
739     G4cout << finalOutput.str();
740 
741 #  ifdef USE_COLOR
742     G4cout << RESET_COLOR;
743 #  endif
744   }
745 #endif
746 }
747 //_________________________________________________________________________
748 
749 G4double G4Scheduler::GetLimitingTimeStep() const
750 {
751   if (fpUserTimeSteps == nullptr) return fDefaultMinTimeStep;
752   if (fabs(fGlobalTime - fUserUpperTimeLimit) < fTimeTolerance) return fDefinedMinTimeStep;
753 
754   auto it_fpUserTimeSteps_i = fpUserTimeSteps->upper_bound(fGlobalTime);
755   auto it_fpUserTimeSteps_low = fpUserTimeSteps->lower_bound(fGlobalTime);
756 
757   if (it_fpUserTimeSteps_i == fpUserTimeSteps->end()) {
758     it_fpUserTimeSteps_i--;
759     fUserUpperTimeLimit = fStopTime;
760   }
761   else if (fabs(fGlobalTime - it_fpUserTimeSteps_low->first) < fTimeTolerance) {
762     it_fpUserTimeSteps_i = it_fpUserTimeSteps_low;
763     auto tmp_it = it_fpUserTimeSteps_low;
764     ++tmp_it;
765     if (tmp_it == fpUserTimeSteps->end()) {
766       fUserUpperTimeLimit = fStopTime;
767     }
768     else {
769       fUserUpperTimeLimit = tmp_it->first;
770     }
771   }
772   else if (it_fpUserTimeSteps_i == it_fpUserTimeSteps_low) {
773     fUserUpperTimeLimit = it_fpUserTimeSteps_i->first;
774     if (it_fpUserTimeSteps_i != fpUserTimeSteps->begin()) it_fpUserTimeSteps_i--;
775   }
776   else {
777     fUserUpperTimeLimit = it_fpUserTimeSteps_i->first;
778     it_fpUserTimeSteps_i = it_fpUserTimeSteps_low;
779   }
780   return it_fpUserTimeSteps_i->second;
781 }
782 
783 //_________________________________________________________________________
784 
785 void G4Scheduler::FindUserPreDefinedTimeStep()
786 {
787   if (fpUserTimeSteps == nullptr) {
788     G4ExceptionDescription exceptionDescription;
789     exceptionDescription << "You are asking to use user defined steps but you did not give any.";
790     G4Exception("G4Scheduler::FindUserPreDefinedTimeStep", "Scheduler004", FatalErrorInArgument,
791                 exceptionDescription);
792     return;  // makes coverity happy
793   }
794   auto fpUserTimeSteps_i = fpUserTimeSteps->upper_bound(fGlobalTime);
795   auto fpUserTimeSteps_low = fpUserTimeSteps->lower_bound(fGlobalTime);
796 
797   if (fpUserTimeSteps_i == fpUserTimeSteps->end()) {
798     fpUserTimeSteps_i--;
799   }
800   else if (fabs(fGlobalTime - fpUserTimeSteps_low->first) < fTimeTolerance) {
801     // Case : fGlobalTime = X picosecond
802     // and fpUserTimeSteps_low->first = X picosecond
803     // but the precision is not good enough
804     fpUserTimeSteps_i = fpUserTimeSteps_low;
805   }
806   else if (fpUserTimeSteps_i == fpUserTimeSteps_low) {
807     // "Normal" cases
808     fpUserTimeSteps_i--;
809   }
810   else {
811     fpUserTimeSteps_i = fpUserTimeSteps_low;
812   }
813 
814   fDefinedMinTimeStep = fpUserTimeSteps_i->second;
815 }
816 
817 //_________________________________________________________________________
818 
819 void G4Scheduler::EndTracking()
820 {
821   if (fRunning) {
822     G4ExceptionDescription exceptionDescription;
823     exceptionDescription << "End tracking is called while G4Scheduler is still running." << G4endl;
824 
825     G4Exception("G4Scheduler::EndTracking", "Scheduler017", FatalErrorInArgument,
826                 exceptionDescription);
827   }
828 
829   while (fTrackContainer.DelayListsNOTEmpty()) {
830     auto nextTime = fTrackContainer.GetNextTime();
831     fTrackContainer.MergeNextTimeToMainList(nextTime);
832   }
833 
834   fTrackContainer.MergeSecondariesWithMainList();
835 
836   if (fTrackContainer.MainListsNOTEmpty()) {
837     G4TrackManyList* mainList = fTrackContainer.GetMainList();
838     G4TrackManyList::iterator it = mainList->begin();
839     G4TrackManyList::iterator end = mainList->end();
840     for (; it != end; ++it) {
841       fpTrackingManager->EndTrackingWOKill(*it);
842     }
843   }
844 
845   if (fTrackContainer.SecondaryListsNOTEmpty())  // should be empty
846   {
847     G4TrackManyList* secondaries = fTrackContainer.GetSecondariesList();
848     G4TrackManyList::iterator it = secondaries->begin();
849     G4TrackManyList::iterator end = secondaries->end();
850 
851     for (; it != end; ++it) {
852       fpTrackingManager->EndTrackingWOKill(*it);
853     }
854   }
855 }
856 
857 //_________________________________________________________________________
858 void G4Scheduler::SetInteractivity(G4ITTrackingInteractivity* interactivity)
859 {
860   fpTrackingInteractivity = interactivity;
861   if (fpTrackingManager != nullptr) {
862     fpTrackingManager->SetInteractivity(fpTrackingInteractivity);
863   }
864 }
865 
866 //_________________________________________________________________________
867 void G4Scheduler::ForceReinitialization()
868 {
869   fInitialized = false;
870   Initialize();
871 }
872 
873 size_t G4Scheduler::GetNTracks()
874 {
875   return fTrackContainer.GetNTracks();
876 }
877 //_________________________________________________________________________
878 
879 void G4Scheduler::GetCollisionType(G4String& interactionType)
880 {
881   switch (fITStepStatus) {
882     case eInteractionWithMedium:
883       interactionType = "eInteractionWithMedium";
884       break;
885     case eCollisionBetweenTracks:
886       interactionType = "eCollisionBetweenTracks";
887       break;
888     default:
889       interactionType = "eCollisionBetweenTracks";
890       break;
891   }
892 }
893