GGS(GenericGEANT4Simulation)Software  2.99.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Macros
GGSRunManagerExtensions.cpp
1 /*
2  * GGSRunManagerExtensions.cpp
3  *
4  * Created on: 5 Nov 2020
5  * Author: Nicola Mori
6  */
7 
8 #include "montecarlo/mccore/GGSRunManagerExtensions.h"
9 #include "utils/GGSSmartLog.h"
10 
11 #include "G4LogicalVolumeStore.hh"
12 #include "G4Run.hh"
13 
15  : _nDiscardedEvsInKilledEvs(0), _nKilledEvs(0), _isCurrEvKilled(false), _simAgainKilledEv(false),
16  _ggsGeneratorAction(nullptr), _eventRandomFileBase(""), _eventRandomFilePath(""), _restoredFrom(""),
17  _readEventRngStateFromFile(false), _saveEventRngStateToFile(false), _messenger(this, "/GGS/"),
18  _randomMessenger(this, "/GGS/random/") {
19 
20  _messenger.DeclareMethod("printLogVols", &GGSRunManagerExtensions::PrintLogVols, "Print a list of logical volumes.");
21  _messenger.DeclareProperty("rndmPrintModulo", _printModulo,
22  "Set the number of events between two dumps on screen of the random engine status "
23  "(set to 0 to disable the dump).");
24 
25  _randomMessenger.DeclareProperty("eventRngStateFileBase", _eventRandomFileBase,
26  "Base name for random generator state files of each event");
27  _randomMessenger.DeclareProperty("eventRngStateFilePath", _eventRandomFilePath,
28  "Path for random generator state files of each event");
29  _randomMessenger.DeclareProperty("readEventRngStateFromFile", _readEventRngStateFromFile,
30  "Read the random number generator state for each event from file");
31  _randomMessenger.DeclareProperty("saveEventRngStateToFile", _saveEventRngStateToFile,
32  "Save the random number generator state for each event to file");
33 }
34 
36  static const std::string routineName("GGSRunManager::KillEvent");
37  if (!_isCurrEvKilled) {
38  GGSCOUT(DEEPDEB) << "Kill event" << std::endl;
39  G4EventManager::GetEventManager()->AbortCurrentEvent();
40  _isCurrEvKilled = true;
41  _nKilledEvs++;
42  if (_ggsGeneratorAction)
43  _nDiscardedEvsInKilledEvs += _ggsGeneratorAction->GetNDiscarded();
44  }
45 }
46 
48  std::stringstream buffer;
49  G4Random::getTheEngine()->put(buffer);
50  _stateAtBeginOfEvent = std::move(buffer.str());
51  _nKilledEvs = 0;
52 }
53 
55  _isCurrEvKilled = false;
56  _simAgainKilledEv = false;
57 }
58 
60  auto Indent = [](const std::string &str) {
61  std::string indentedStr;
62  size_t pos = 0;
63  while (true) {
64  auto newlinePos = str.find_first_of('\n', pos);
65  if (newlinePos != std::string::npos) {
66  indentedStr.append(" ").append(str, pos, newlinePos - pos + 1);
67  pos = newlinePos + 1;
68  } else {
69  break;
70  }
71  }
72  return indentedStr;
73  };
74 
75  if (_printModulo != 0) {
76  if (eventID % _printModulo == 0 && eventID > _lastPrinted) {
77  std::stringstream outSS, bufferSS;
78  outSS << "---> Begin of event: " << eventID << "\n";
79  outSS << "--------- " << G4Random::getTheEngine()->name() << " random engine state ---------\n";
80  if (RngStateRestoredFrom() != "") {
81  outSS << "--- Restored from: " << RngStateRestoredFrom() << "\n";
82  }
83  outSS << " State at begin of event generation:\n" << Indent(GetRandomStateAtBeginOfEvent()) << "\n";
84  outSS << " State at begin of event tracking: \n";
85  G4Random::getTheEngine()->put(bufferSS);
86  outSS << Indent(bufferSS.str());
87  outSS << "----------------------------------------\n";
88  G4cout << outSS.str() << G4endl;
89  _lastPrinted = eventID;
90  }
91  }
92 }
93 
95  static const char *routineName = "GGSRunManagerExtensions::IsKilledAndToBeSimulatedAgain";
96  if (_isCurrEvKilled) {
97  GGSCOUT(DEEPDEB) << "Event " << ev->GetEventID() << " has been killed. " << GGSENDL;
98  if (_ggsGeneratorAction) {
99  GGSCCOUT(DEEPDEB) << "Discarded at generation: " << _ggsGeneratorAction->GetNDiscarded()
100  << " (total: " << _nDiscardedEvsInKilledEvs << ")" << GGSENDL;
101  }
102  if (_simAgainKilledEv) {
103  GGSCCOUT(DEEPDEB) << "Will be simulated again." << GGSENDL;
104  return true;
105  }
106  } else {
107  GGSCOUT(DEEPDEB) << "Finished simulating event " << ev->GetEventID() << GGSENDL;
108  if (_ggsGeneratorAction) {
109  GGSCCOUT(DEEPDEB) << "Discarded at generation: " << _ggsGeneratorAction->GetNDiscarded()
110  << " (total: " << GetNDiscardedEvents() << ")" << GGSENDL;
111  }
112  GGSCCOUT(DEEPDEB) << "Killed: " << _nKilledEvs << GGSENDL;
113  // Reset discarded and killed event counters
114  _nDiscardedEvsInKilledEvs = 0;
115  _nKilledEvs = 0;
116  if (_simAgainKilledEv) {
117  static bool printDone = false;
118  if (!printDone) {
119  GGSCOUT(WARNING) << "Request to re-simulate an event which has not been flagged as killed. Ignoring."
120  << GGSENDL;
121  GGSCCOUT(WARNING) << "This message will be printed only once." << GGSENDL;
122  printDone = true;
123  }
124  }
125  }
126  return false;
127 }
128 
129 void GGSRunManagerExtensions::SetGGSGeneratorAction(G4VUserPrimaryGeneratorAction *userAction) {
130  // dynamic_cast to references to throw exceptions in case of errors
131  _ggsGeneratorAction = &(dynamic_cast<GGSGeneratorAction &>(*userAction));
132  auto &rmExt = dynamic_cast<G4RunManager &>(*this);
133  rmExt.SetUserAction(userAction);
134 }
135 
137  if (_ggsGeneratorAction) {
138  return _nDiscardedEvsInKilledEvs + _ggsGeneratorAction->GetNDiscarded();
139  }
140  return 0;
141 }
142 
144  static const std::string routineName("GGSRunManagerExtensions::PrintLogVols");
145  G4LogicalVolumeStore *logVolStore = G4LogicalVolumeStore::GetInstance();
146 
147  GGSCOUT(INFO) << "Logical volumes in current geometry:" << GGSENDL;
148  for (auto &logVol : *logVolStore) {
149  GGSCCOUT(INFO) << " * " << logVol->GetName() << GGSENDL;
150  }
151 }
152 
154  _restoredFrom = "";
155  if (_saveEventRngStateToFile || _readEventRngStateFromFile) {
156 
157  const std::string fileName = _eventRandomFilePath + _eventRandomFileBase + "run" + std::to_string(runID) + "evt" +
158  std::to_string(eventID) + ".rndm";
159 
160  if (_readEventRngStateFromFile) {
161  // The different concrete random engines implement error handling in get() differently: some simply print a
162  // message on cerr, some others throw exceptions. Handle this redirecting cerr to a dummy buffer before calling
163  // get() and then check if it's empty or not (other than the usual try-catch block for eventual exceptions).
164  std::stringstream cerrDummyBuf;
165  std::streambuf *cerrBuf = std::cerr.rdbuf();
166  std::cerr.rdbuf(cerrDummyBuf.rdbuf());
167  std::ifstream stateFile(fileName);
168  if (stateFile) { // File valid and readable
169  bool error = false;
170  std::string errorMessage;
171  try {
172  G4Random::getTheEngine()->get(stateFile);
173  std::cerr.rdbuf(cerrBuf);
174  if (cerrDummyBuf.str() != "") {
175  error = true;
176  errorMessage = cerrDummyBuf.str();
177  }
178  } catch (std::exception &exc) {
179  error = true;
180  errorMessage = exc.what();
181  } catch (...) {
182  error = true;
183  errorMessage = "unknown";
184  }
185  if (error) {
186  G4Exception("GGSRunManagerExtensions::HandleEventRngStateFile", "Can't read state file",
187  G4ExceptionSeverity::FatalException,
188  (("Error when restoring the state of the random engine from file ") + fileName +
189  "\nReason: " + errorMessage)
190  .c_str());
191  } else {
192  _restoredFrom = fileName;
193  }
194  } else {
195  G4Exception("GGSRunManagerExtensions::HandleEventRngStateFile", "Missing state file",
196  G4ExceptionSeverity::FatalException,
197  (("Can't find the random engine state file ") + fileName).c_str());
198  }
199  }
200 
201  if (_saveEventRngStateToFile && !_readEventRngStateFromFile) { // If reading from file, avoid to rewrite the same
202  std::ofstream stateFile(fileName);
203  G4Random::getTheEngine()->put(stateFile);
204  }
205  }
206 }
void PrintLogVols()
Print a list of logical volumes in current geometries.
#define GGSCCOUT(level)
Smart log utility which prints no header at the beginning of the line.
Definition: GGSSmartLog.h:126
void SetGGSGeneratorAction(G4VUserPrimaryGeneratorAction *userAction)
Replacement of the SetUserAction method.
bool IsKilledAndToBeSimulatedAgain(const G4Event *ev)
Checks if the event has been killed and has to be re-simulated.
Base class for GGS generator actions.
#define GGSENDL
Definition: GGSSmartLog.h:131
void HandleEventRngStateFile(int runID, int eventID)
Handles the read/write operations to/from the random generator state file for each event...
int GetNDiscardedEvents()
Getter method for number of discarded events.
void DumpStatus(G4int eventID)
Prints the status of the random number generator.
const std::string & GetRandomStateAtBeginOfEvent()
Getter method for random engine state at the beginning of the current event.
unsigned int GetNDiscarded() const
Returns the number of discarded events for the current event generation.
void BeginOfEventSimulation()
Reset the internal flags at the beginning of event simulation.
void BeginOfEventProcessing()
Method for storing the random engine state and resetting the internal flags at the beginning event ge...
const std::string & RngStateRestoredFrom()
The random engine state file for this event.
void KillEvent()
Kills the current event.