ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4ITModelProcessor.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4ITModelProcessor.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 // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
28 //
29 // History:
30 // -----------
31 // 10 Oct 2011 M.Karamitros created
32 //
33 // -------------------------------------------------------------------
34 
35 #include "G4ITModelProcessor.hh"
36 #include "G4VITTimeStepComputer.hh"
37 #include "G4VITReactionProcess.hh"
38 #include "G4ITReaction.hh"
39 #include "G4ITTrackHolder.hh"
40 #include "G4ITTrackingManager.hh"
41 #include "G4VITStepModel.hh"
42 #include "G4UserTimeStepAction.hh"
43 #include "G4UnitsTable.hh"
44 #include <vector>
45 
46 //#define DEBUG_MEM
47 
48 #ifdef DEBUG_MEM
49 #include "G4MemStat.hh"
50 using namespace G4MemStat;
51 #endif
52 
54 {
55  fpTrack = nullptr;
56  fInitialized = false;
57  fUserMinTimeStep = -1.;
58  fTSTimeStep = DBL_MAX;
59  fpTrackingManager = nullptr;
60  fReactionSet = nullptr;
61  fpTrackContainer = nullptr;
62  fpModelHandler = nullptr;
63  fpActiveModelWithMinTimeStep = nullptr;
64  fComputeTimeStep = false;
65  fComputeReaction = false;
66 }
67 
69 
71 {
72  fpModelHandler->RegisterModel(model, time);
73 }
74 
76 {
77  fpModelHandler->Initialize();
78  fReactionSet = G4ITReactionSet::Instance();
79  fpTrackContainer = G4ITTrackHolder::Instance();
80  fInitialized = true;
81  fComputeTimeStep = false;
82  fComputeReaction = false;
83  if (fpModelHandler->GetTimeStepComputerFlag())
84  {
85  fComputeTimeStep = true;
86  }
87  if (fpModelHandler->GetReactionProcessFlag())
88  {
89  fComputeReaction = true;
90  }
91 }
92 
94  G4double definedMinTimeStep)
95 {
96 
97 #if defined (DEBUG_MEM) && defined (DEBUG_MEM_DETAILED_STEPPING)
98  MemStat mem_first, mem_second, mem_diff;
99  mem_first = MemoryUsage();
100 #endif
101 
102  fpActiveModelWithMinTimeStep = nullptr;
103  fTSTimeStep = DBL_MAX;
104 
105  InitializeStepper(currentGlobalTime, definedMinTimeStep);
106 
107 #if defined (DEBUG_MEM) && defined (DEBUG_MEM_DETAILED_STEPPING)
108  mem_second = MemoryUsage();
109  mem_diff = mem_second-mem_first;
110  G4cout << "\t || MEM || G4Scheduler::CalculateMinTimeStep || After "
111  "computing fpModelProcessor -> InitializeStepper, diff is : "
112  << mem_diff
113  << G4endl;
114 #endif
115 
116  for (auto pTrack : *fpTrackContainer->GetMainList())
117  {
118  if (pTrack == nullptr)
119  {
120  G4ExceptionDescription exceptionDescription;
121  exceptionDescription << "No track found.";
122  G4Exception("G4Scheduler::CalculateMinStep", "ITScheduler006",
123  FatalErrorInArgument, exceptionDescription);
124  continue;
125  }
126 
127 #ifdef DEBUG
128  G4cout << "*_* " << GetIT(track)->GetName()
129  << " ID: " << track->GetTrackID()
130  << " at time : " << track->GetGlobalTime()
131  << G4endl;
132 #endif
133 
134  G4TrackStatus trackStatus = pTrack->GetTrackStatus();
135  if (trackStatus == fStopAndKill || trackStatus == fStopButAlive)
136  {
137  continue;
138  }
139 
140  CalculateTimeStep(pTrack, definedMinTimeStep);
141  // if MT mode at track level, this command should be displaced
142  ExtractTimeStepperData();
143  }
144 
145 #if defined (DEBUG_MEM) && defined (DEBUG_MEM_DETAILED_STEPPING)
146  mem_second = MemoryUsage();
147  mem_diff = mem_second-mem_first;
148  G4cout << "\t || MEM || G4Scheduler::CalculateMinTimeStep || "
149  "After looping on tracks, diff is : " << mem_diff << G4endl;
150 #endif
151  return fTSTimeStep;
152 }
153 
154 //_________________________________________________________________________
155 
157 {
158  if (fpTrack == nullptr)
159  {
160  CleanProcessor();
161  return;
162  }
163 
164  for (auto pStepModel : fActiveModels)
165  {
166  if (pStepModel == nullptr)
167  {
168  continue;
169  }
170 
171  auto pTimeStepper = pStepModel->GetTimeStepper();
172  G4double sampledMinTimeStep = pTimeStepper->GetSampledMinTimeStep();
173  G4TrackVectorHandle reactants = pTimeStepper->GetReactants();
174 
175  if (sampledMinTimeStep < fTSTimeStep)
176  {
177  fpActiveModelWithMinTimeStep = pStepModel;
178  fTSTimeStep = sampledMinTimeStep;
179  //fReactingTracks.clear();
180 
181  fReactionSet->CleanAllReaction();
182  if (reactants)
183  {
184  // fReactingTracks.insert(make_pair(track, reactants));
185  fReactionSet->AddReactions(fTSTimeStep,
186  const_cast<G4Track*>(fpTrack),
187  reactants);
188  pTimeStepper->ResetReactants();
189  }
190  }
191  else if (fTSTimeStep == sampledMinTimeStep && bool(reactants))
192  {
193  // fReactingTracks.insert(make_pair(track, reactants));
194  fReactionSet->AddReactions(fTSTimeStep,
195  const_cast<G4Track*>(fpTrack),
196  reactants);
197  pTimeStepper->ResetReactants();
198  }
199  else if (reactants)
200  {
201  pTimeStepper->ResetReactants();
202  }
203  }
204 
205  CleanProcessor();
206 }
207 
208 //______________________________________________________________________________
209 
211  G4double userMinTime)
212 {
213  G4VITTimeStepComputer::SetTimes(currentGlobalTime, userMinTime);
214 
215 #if defined (DEBUG_MEM)
216  MemStat mem_first, mem_second, mem_diff;
217  mem_first = MemoryUsage();
218 #endif
219 
220  fActiveModels = fpModelHandler->GetActiveModels(currentGlobalTime);
221 
222  for (auto& pModel : fActiveModels)
223  {
224  pModel->PrepareNewTimeStep();
225  }
226 
227 #if defined (DEBUG_MEM)
228  mem_second = MemoryUsage();
229  mem_diff = mem_second-mem_first;
230  G4cout << "\t || MEM || G4ITModelProcessor::InitializeStepper || After computing stepper -> Prepare(), diff is : " << mem_diff << G4endl;
231 #endif
232 
233 }
234 
235 //______________________________________________________________________________
237  const G4double userMinTimeStep)
238 {
239  CleanProcessor();
240  if (pTrack == nullptr)
241  {
242  G4ExceptionDescription exceptionDescription;
243  exceptionDescription << "No track was passed to the method.";
244  G4Exception("G4ITModelProcessor::CalculateStep",
245  "ITModelProcessor004",
247  exceptionDescription);
248  }
249  SetTrack(pTrack);
250  fUserMinTimeStep = userMinTimeStep;
251 
252  DoCalculateStep();
253 }
254 
255 //______________________________________________________________________________
256 
258 {
259  for (auto& pStepModel : fActiveModels)
260  {
261  pStepModel->GetTimeStepper()->CalculateStep(*fpTrack, fUserMinTimeStep);
262  }
263 }
264 
265 //_________________________________________________________________________
266 
268  G4double fGlobalTime,
269  G4double currentTimeStep,
270  G4double previousTimeStep,
271  G4bool reachedUserTimeLimit,
272  G4double fTimeTolerance,
273  G4UserTimeStepAction* fpUserTimeStepAction,
274  G4int
275 #ifdef G4VERBOSE
276 fVerbose
277 #endif
278 )
279 {
280 // if (fReactingTracks.empty())
281  if (fReactionSet->Empty())
282  {
283  return;
284  }
285 
286  if (fITStepStatus == eCollisionBetweenTracks)
287  // if(fInteractionStep == false)
288  {
289  // TODO
290  FindReaction(fReactionSet,
291  currentTimeStep,
292  previousTimeStep,
293  reachedUserTimeLimit);
294  // TODO
295  // A ne faire uniquement si le temps choisis est celui calculĂ© par le time stepper
296  // Sinon utiliser quelque chose comme : fModelProcessor->FindReaction(&fMainList);
297 
298  for (auto& pChanges : fReactionInfo)
299  {
300  auto pTrackA = const_cast<G4Track*>(pChanges->GetTrackA());
301  auto pTrackB = const_cast<G4Track*>(pChanges->GetTrackB());
302 
303  if (pTrackA == nullptr
304  || pTrackB == nullptr
305  || pTrackA->GetTrackStatus() == fStopAndKill
306  || pTrackB->GetTrackStatus() == fStopAndKill)
307  {
308  continue;
309  }
310 
311  G4int nbSecondaries = pChanges->GetNumberOfSecondaries();
312  const std::vector<G4Track*>* productsVector = pChanges->GetfSecondary();
313 
314  if (fpUserTimeStepAction)
315  {
316  fpUserTimeStepAction->UserReactionAction(*pTrackA,
317  *pTrackB,
318  productsVector);
319  }
320 
321 #ifdef G4VERBOSE
322  if (fVerbose)
323  {
324  G4cout << "At time : " << std::setw(7) << G4BestUnit(fGlobalTime, "Time")
325  << " Reaction : " << GetIT(pTrackA)->GetName() << " ("
326  << pTrackA->GetTrackID() << ") + " << GetIT(pTrackB)->GetName() << " ("
327  << pTrackB->GetTrackID() << ") -> ";
328  }
329 #endif
330 
331  if (nbSecondaries > 0)
332  {
333  for (int i = 0; i < nbSecondaries; ++i)
334  {
335 #ifdef G4VERBOSE
336  if (fVerbose && i != 0)
337  {
338  G4cout << " + ";
339  }
340 #endif
341 
342  G4Track* secondary = (*productsVector)[i]; //changes->GetSecondary(i);
343  fpTrackContainer->_PushTrack(secondary);
344  GetIT(secondary)->SetParentID(pTrackA->GetTrackID(),
345  pTrackB->GetTrackID());
346 
347  if (secondary->GetGlobalTime() - fGlobalTime > fTimeTolerance)
348  {
349  G4ExceptionDescription exceptionDescription;
350  exceptionDescription << "The time of the secondary should not be bigger than the"
351  " current global time."
352  << " This may cause synchronization problem. If the process you"
353  " are using required "
354  << "such feature please contact the developpers." << G4endl
355  << "The global time in the step manager : "
356  << G4BestUnit(fGlobalTime, "Time")
357  << G4endl
358  << "The global time of the track : "
359  << G4BestUnit(secondary->GetGlobalTime(), "Time")
360  << G4endl;
361 
362  G4Exception("G4Scheduler::ComputeInteractionBetweenTracks",
363  "ITScheduler010",
365  exceptionDescription);
366  }
367 
368 #ifdef G4VERBOSE
369  if (fVerbose)
370  {
371  G4cout << GetIT(secondary)->GetName() << " ("
372  << secondary->GetTrackID() << ")";
373  }
374 #endif
375  }
376  }
377  else
378  {
379 #ifdef G4VERBOSE
380  if (fVerbose)
381  {
382  G4cout << "No product";
383  }
384 #endif
385  }
386 #ifdef G4VERBOSE
387  if (fVerbose)
388  {
389  G4cout << G4endl;
390  }
391 #endif
392  if (pTrackA->GetTrackID() == 0 || pTrackB->GetTrackID() == 0)
393  {
394  G4Track* pTrack = nullptr;
395  if (pTrackA->GetTrackID() == 0)
396  {
397  pTrack = pTrackA;
398  }
399  else
400  {
401  pTrack = pTrackB;
402  }
403 
404  G4ExceptionDescription exceptionDescription;
405  exceptionDescription
406  << "The problem was found for the reaction between tracks :"
407  << pTrackA->GetParticleDefinition()->GetParticleName() << " ("
408  << pTrackA->GetTrackID() << ") & "
409  << pTrackB->GetParticleDefinition()->GetParticleName() << " ("
410  << pTrackB->GetTrackID() << "). \n";
411 
412  if (pTrack->GetStep() == nullptr)
413  {
414  exceptionDescription << "Also no step was found"
415  << " ie track->GetStep() == 0 \n";
416  }
417 
418  exceptionDescription << "Parent ID of trackA : "
419  << pTrackA->GetParentID() << "\n";
420  exceptionDescription << "Parent ID of trackB : "
421  << pTrackB->GetParentID() << "\n";
422 
423  exceptionDescription
424  << "The ID of one of the reaction track was not setup.";
425  G4Exception("G4Scheduler::ComputeInteractionBetweenTracks",
426  "ITScheduler011",
428  exceptionDescription);
429  }
430 
431  if (pChanges->WereParentsKilled())
432  {
433  pTrackA->SetTrackStatus(fStopAndKill);
434  pTrackB->SetTrackStatus(fStopAndKill);
435 
436  fpTrackingManager->EndTracking(pTrackA);
437  fpTrackingManager->EndTracking(pTrackB);
438  }
439 
440  pChanges.reset(nullptr);
441  }
442 
443  fReactionInfo.clear();
444  }
445 
446  fReactionSet->CleanAllReaction();
447 
448  fpTrackContainer->MergeSecondariesWithMainList();
449  fpTrackContainer->KillTracks();
450 }
451 
452 //______________________________________________________________________________
454  const double currentStepTime,
455  const double /*previousStepTime*/,
456  const bool reachedUserStepTimeLimit)
457 {
458  if (pReactionSet == nullptr || fActiveModels.empty())
459  {
460  return;
461  }
462 
463  G4ITReactionPerTrackMap& reactionPerTrackMap = pReactionSet->GetReactionMap();
464  G4VITReactionProcess* pReactionProcess = fpActiveModelWithMinTimeStep->GetReactionProcess();
465 
466  for (auto tracks_i = reactionPerTrackMap.begin();
467  tracks_i != reactionPerTrackMap.end();
468  tracks_i = reactionPerTrackMap.begin())
469  {
470  G4Track* pTrackA = tracks_i->first;
471  if (pTrackA->GetTrackStatus() == fStopAndKill)
472  {
473  continue;
474  }
475 
476  G4ITReactionPerTrackPtr reactionPerTrack = tracks_i->second;
477  G4ITReactionList& reactionList = reactionPerTrack->GetReactionList();
478 
479  assert(reactionList.begin() != reactionList.end());
480 
481  for (auto it = reactionList.begin(); it != reactionList.end(); it = reactionList.begin())
482  {
483  G4ITReactionPtr reaction(*it);
484  G4Track* pTrackB = reaction->GetReactant(pTrackA);
485  if (pTrackB->GetTrackStatus() == fStopAndKill)
486  {
487  continue;
488  }
489 
490  if (pTrackB == pTrackA)
491  {
492  G4ExceptionDescription exceptionDescription;
493  exceptionDescription
494  << "The IT reaction process sent back a reaction between trackA and trackB. ";
495  exceptionDescription << "The problem is trackA == trackB";
496  G4Exception("G4ITModelProcessor::FindReaction",
497  "ITModelProcessor005",
499  exceptionDescription);
500  }
501 
502  pReactionSet->SelectThisReaction(reaction);
503 
504  if (pReactionProcess && pReactionProcess->TestReactibility(*pTrackA,
505  *pTrackB,
506  currentStepTime,
507  reachedUserStepTimeLimit))
508  {
509  auto pReactionChange = pReactionProcess->MakeReaction(*pTrackA, *pTrackB);
510 
511  if (pReactionChange)
512  {
513  fReactionInfo.push_back(std::move(pReactionChange));
514  break;
515  }
516  }
517  }
518  }
519 
520  //assert(G4ITReaction::gAll->empty() == true);
521 }
522 
524 {
525  fpTrack = track;
526 }
527 
529 {
530  if (fInitialized)
531  {
532  G4ExceptionDescription exceptionDescription;
533  exceptionDescription
534  << "You are trying to set a new model while the model processor has alreaday be initialized";
535  G4Exception("G4ITModelProcessor::SetModelHandler", "ITModelProcessor001",
536  FatalErrorInArgument, exceptionDescription);
537  }
538  fpModelHandler = pModelHandler;
539 }
540 
542 {
543  fpTrack = nullptr;
544 }
545 
547 {
548  return fComputeTimeStep;
549 }
550 
552 {
553  return fpTrack;
554 }
555 
557 {
558  fpTrackingManager = pTrackingManager;
559 }
560