GGS(GenericGEANT4Simulation)Software  2.99.0
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Macros
GGSPenny.cpp
1 /*
2  * GGSPenny.cpp
3  *
4  * Created on: 2010-09-29
5  * Authors: Emiliano Mocchiutti and Cecilia Pizzolotto
6  */
7 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
8 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
9 // C++ and STL headers
10 #include <sys/stat.h>
11 #include <vector>
12 
13 // ROOT headers
14 #include "TROOT.h"
15 
16 // GEANT4 headers
17 #include "G4PhysListFactory.hh"
18 #include "G4UImanager.hh"
19 #include "G4Version.hh"
20 #include "Randomize.hh"
21 
22 #ifdef G4VIS_USE
23 #include "G4VisExecutive.hh"
24 #endif
25 
26 #ifdef G4UI_USE
27 #include "G4UIExecutive.hh"
28 #endif
29 
30 // GGS headers
31 #include "GGSVersion.h" //Automatically generated by the CMake configuration system
41 #include "utils/GGSSmartLog.h"
42 
43 #ifdef CRMC
44 #include "montecarlo/physicslists/GGSCRMCPhysicsList.h"
45 #endif
46 
47 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
48 // clang-format off
49 void usage() {
50  std::cout << "Usage: GGSPenny [options] \n";
51  std::cout << "This is the GGS main MonteCarlo program\n\n";
52 
53  std::cout << "Run type selection\n";
54  std::cout << "------------------\n";
55  std::cout << " -X, --interactive interactive mode [default: false]\n\n";
56 
57  std::cout << " -d, --data-card FILE data card filename [default: not set]\n\n";
58 
59  std::cout << "If only -d is specified the program will run in batch mode.\n";
60  std::cout << "If both options are specified, the datacard will be processed before entering the interactive mode.\n\n";
61 
62  std::cout << "Configuration options\n";
63  std::cout << "---------------------\n";
64  std::cout << " -g, --geometry FILE full path and name of the geometry; can be a .so or a .gdml.\n";
65  std::cout << " -gd, --geo-data-card FILE data card filename for geometry configuration [default: not set]\n\n";
66  std::cout << " -pl, --physics-list NAME physics list (standard list name or full path of physics list .so library) [default: QGSP_BERT]\n\n";
67  std::cout << " -pd, --physlist-data-card FILE data card filename for physics list configuration [default: not set]\n\n";
68  std::cout << " -ap, --action-plugin FILE full path and name of the plugin user and generator action library\n";
69  std::cout << " May be repeated to load many libraries: -ap libUserAction.so -ap libGeneratorAction.so\n\n";
70  std::cout << " -st, --single-threaded Force single-threaded run mode for multi-threaded build\n\n";
71  std::cout << " -nt, --n-threads Set the number of threads for multi-threaded run [default: 2]\n\n";
72  std::cout << " -ro, --root-output-file FILE default ROOT output filename (may be overridden in datacard for each action)\n\n";
73  std::cout << " -os, --output-suffix SUFFIX output file suffix [default: ]\n\n";
74  std::cout << " --seed1 INT first random seed [default: 1]\n\n"; // do not put default 0!
75  std::cout << " --seed2 INT second random seed [default: 2]\n\n";
76  std::cout << " -s, --input-seed-file FILE file containing input random seeds [default: not set]\n\n";
77  std::cout << "Configuration options can either be given as command line parameters or placed in an input file.\n";
78  std::cout << "File syntax is the same as the above specified commands, one command per line. Set the input file via command line as:\n\n";
79  std::cout << " -i, --input-file FILE file containing input arguments [default: not set]\n\n";
80 
81  std::cout << "Miscellaneous\n";
82  std::cout << "-------------\n";
83  std::cout << " -v, --verbose be verbose [default: false]\n\n";
84  std::cout << " -V, --version displays software version and exit\n\n";
85  std::cout << " -h, --help display this help and exit\n\n";
86 
87  std::cout << "\nTo run GGSPenny either the -d (data card) or the -X (interactive) option MUST be set!\n";
88  std::cout << "Report bugs to: https://baltig.infn.it/mori/GGSSoftware/-/issues \n";
89 }
90 // clang-format on
91 
92 void GGSPennyVersion() {
93  std::cout << "GGSPenny simulation software";
94 #ifdef GGSMULTITHREADED
95  std::cout << " (MT build)\n";
96 #else
97  std::cout << " (ST build)\n";
98 #endif
99  std::cout << "Using GGS " << GGSVERSION << std::endl;
100 }
101 
103 namespace GGSPenny {
104 G4String rootOutputFile = "";
105 G4String outputSuffix = "";
106 G4String dataCard = "";
107 G4String geoDataCard = "";
108 G4String physListDataCard = "";
109 G4String inputSeedFile = "";
110 G4String geometry = "";
111 G4String physicsListName = "FTFP_BERT";
112 std::vector<G4String> actionPluginFiles;
113 G4bool interactiveMode = false;
114 #ifdef GGSMULTITHREADED
115 G4bool multiThreadedMode = true;
116 G4int nThreads = 2;
117 #else
118 G4bool multiThreadedMode = false;
119 G4int nThreads = 1;
120 #endif
121 G4long seed1 = 1;
122 G4long seed2 = 2;
123 } // namespace GGSPenny
124 using namespace GGSPenny;
125 
126 void DumpGlobals() {
127  std::cout << "==============> MonteCarlo globals used for this run <===============\n";
128  std::cout << "dataCard : " << dataCard.c_str() << "\n";
129  std::cout << "geometry : " << geometry.c_str() << "\n";
130  std::cout << "geoDataCard : " << geoDataCard.c_str() << "\n";
131  std::cout << "physicsListName : " << physicsListName.c_str() << "\n";
132  std::cout << "physListDataCard : " << physListDataCard.c_str() << "\n";
133  std::cout << "rootOutputFile : " << rootOutputFile.c_str() << "\n";
134  std::cout << "outputSuffix : " << outputSuffix.c_str() << "\n";
135  std::cout << "inputSeedFile : " << inputSeedFile.c_str() << "\n";
136  std::cout << "seed1 : " << seed1 << "\n";
137  std::cout << "seed2 : " << seed2 << "\n";
138  std::cout << "interactiveMode : " << interactiveMode << "\n";
139  std::cout << "multiThreadedMode : " << multiThreadedMode << "\n";
140  if (multiThreadedMode) {
141  std::cout << "nThreads : " << nThreads << "\n";
142  }
143  std::cout << "======================================================================" << std::endl;
144 }
145 
146 int HandleInputPar(int argc, char **argv) {
147  static const std::string routineName("HandleInputPar");
148  // Set verbose level to print warnings about unrecognized options
149  GGSSmartLog::verboseLevel = GGSSmartLog::WARNING;
150  int vLevel = GGSSmartLog::INFO;
151  if (argc > 1) {
152  int i = 1;
153  while (i < argc) {
154  if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
155  usage();
156  return 1;
157  }
158  // -----------------------------------------------------//
159  if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
160  GGSPennyVersion();
161  return 1;
162  }
163  // -----------------------------------------------------//
164  if (!strcmp(argv[i], "--")) {
165  return 0;
166  }
167  // -----------------------------------------------------//
168  else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--data-card")) {
169  if (++i >= argc) {
170  usage();
171  return 1;
172  }
173  dataCard = argv[i];
174  }
175  // -----------------------------------------------------//
176  else if (!strcmp(argv[i], "-gd") || !strcmp(argv[i], "--geo-data-card")) {
177  if (++i >= argc) {
178  usage();
179  return 1;
180  }
181  geoDataCard = argv[i];
182  }
183  // -----------------------------------------------------//
184  else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--geometry")) {
185  if (++i >= argc) {
186  usage();
187  return 1;
188  }
189  geometry = argv[i];
190  }
191  // -----------------------------------------------------//
192  else if (!strcmp(argv[i], "-pl") || !strcmp(argv[i], "--physics-list")) {
193  if (++i >= argc) {
194  usage();
195  return 1;
196  }
197  physicsListName = argv[i];
198  }
199  // -----------------------------------------------------//
200  else if (!strcmp(argv[i], "-pd") || !strcmp(argv[i], "--physlist-data-card")) {
201  if (++i >= argc) {
202  usage();
203  return 1;
204  }
205  physListDataCard = argv[i];
206  }
207  // -----------------------------------------------------//
208  else if (!strcmp(argv[i], "-ap") || !strcmp(argv[i], "--action-plugin")) {
209  if (++i >= argc) {
210  usage();
211  return 1;
212  }
213  actionPluginFiles.push_back(G4String(argv[i]));
214  }
215  // -----------------------------------------------------//
216  else if (!strcmp(argv[i], "-st") || !strcmp(argv[i], "--single-threaded")) {
217  multiThreadedMode = false;
218  }
219  // -----------------------------------------------------//
220  else if (!strcmp(argv[i], "-nt") || !strcmp(argv[i], "--n-threads")) {
221  if (++i >= argc) {
222  usage();
223  return 1;
224  }
225  nThreads = std::stoi(argv[i]);
226  }
227  // -----------------------------------------------------//
228  else if (!strcmp(argv[i], "-X") || !strcmp(argv[i], "--interactive")) {
229  interactiveMode = true;
230  }
231  // -----------------------------------------------------//
232  else if (!strcmp(argv[i], "-ro") || !strcmp(argv[i], "--root-output-file")) {
233  if (++i >= argc) {
234  usage();
235  return 1;
236  }
237  rootOutputFile = argv[i];
238  }
239  // -----------------------------------------------------//
240  else if (!strcmp(argv[i], "-os") || !strcmp(argv[i], "--output-suffix")) {
241  if (++i >= argc) {
242  usage();
243  return 1;
244  }
245  outputSuffix = argv[i];
246  }
247  // -----------------------------------------------------//
248  else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--input-seed-file")) {
249  if (++i >= argc) {
250  usage();
251  return 1;
252  }
253  inputSeedFile = argv[i];
254  }
255  // -----------------------------------------------------//
256  else if (!strcmp(argv[i], "--seed1")) {
257  if (++i >= argc) {
258  usage();
259  return 1;
260  }
261  seed1 = std::stol(argv[i]);
262  }
263  // -----------------------------------------------------//
264  else if (!strcmp(argv[i], "--seed2")) {
265  if (++i >= argc) {
266  usage();
267  return 1;
268  }
269  seed2 = std::stol(argv[i]);
270  }
271  // -----------------------------------------------------//
272  else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) {
273  std::string vLevStr(argv[++i]);
274  if (vLevStr == "error")
275  vLevel = GGSSmartLog::ERROR;
276  else if (vLevStr == "warning")
277  vLevel = GGSSmartLog::WARNING;
278  else if (vLevStr == "normal" || vLevStr == "info")
279  vLevel = GGSSmartLog::INFO;
280  else if (vLevStr == "debug")
281  vLevel = GGSSmartLog::DEBUG;
282  else if (vLevStr == "deepdeb")
283  vLevel = GGSSmartLog::DEEPDEB;
284  else {
285  GGSCOUT(WARNING) << "Unrecognized verbosity level: " << vLevStr << ". Ignoring." << GGSENDL;
286  }
287  }
288  // -----------------------------------------------------//
289  else {
290  GGSCOUT(WARNING) << "Unidentified input argument \"" << argv[i] << "\". Ignoring." << std::endl;
291  }
292  i++;
293  }
294  } else {
295  usage();
296  return 1;
297  }
298  GGSSmartLog::verboseLevel = vLevel;
299  return 0;
300 }
301 
302 int main(int argc, char **argv) {
303 
304  static const std::string routineName("GGSPenny");
305 
306  if (HandleInputPar(argc, argv))
307  return 0;
308 
309  GGSPennyVersion();
310 
311  if (!strcmp(dataCard.c_str(), "") && !interactiveMode) {
312  usage();
313  return 1;
314  }
315 
316  if (geometry == "") {
317  GGSCOUT(ERROR) << "No geometry provided. Exit." << GGSENDL;
318  return 1;
319  }
320 
321  // Check the existence of given files
322  {
323  struct stat st;
324  if (dataCard != "" && stat(dataCard.c_str(), &st) != 0) {
325  GGSCOUT(ERROR) << "Datacard " << dataCard << " not found." << GGSENDL;
326  return 1;
327  }
328  if (geoDataCard != "" && stat(geoDataCard.c_str(), &st) != 0) {
329  GGSCOUT(ERROR) << "Geometry datacard " << geoDataCard << " not found." << GGSENDL;
330  return 1;
331  }
332  if (physListDataCard != "" && stat(physListDataCard.c_str(), &st) != 0) {
333  GGSCOUT(ERROR) << "Physics list datacard " << physListDataCard << " not found." << GGSENDL;
334  return 1;
335  }
336  }
337 
338  // print on the screen input to this run
339  DumpGlobals();
340 
341  if (multiThreadedMode) {
342  ROOT::EnableThreadSafety();
343  }
344 
345  GGSCOUT(DEBUG) << "Initialize random generator." << GGSENDL;
346  // Choose the Random engine
347  CLHEP::MixMaxRng rndmEngine;
348  G4Random::setTheEngine(&rndmEngine);
349  G4long seeds[2] = {seed1, seed2};
350  G4Random::setTheSeeds(seeds, 0);
351  G4Random::showEngineStatus();
352 
353  // Construct the default run manager
354  //
355  GGSCOUT(DEBUG) << "Create the run manager." << GGSENDL;
356  G4RunManager *runManager = nullptr;
357  if (multiThreadedMode) {
358  runManager = new GGSMTRunManager;
359  static_cast<GGSMTRunManager *>(runManager)->SetNumberOfThreads(nThreads);
360  } else {
361  runManager = new GGSRunManager;
362  }
363  // Set mandatory initialization classes
364  GGSCOUT(DEBUG) << "Create the detector." << GGSENDL;
365  GGSDetectorConstruction *detector = nullptr;
366  if (geometry.length() > 4 && geometry.substr(geometry.length() - 5) == ".gdml") {
367  detector = new GGSDetectorConstruction(geometry);
368  }
369 #ifdef GGS_USE_DD4HEP
370  else if (geometry.length() > 3 && geometry.substr(geometry.length() - 4) == ".xml") {
371  detector = new GGSDetectorConstruction(geometry);
372  }
373 #endif
374  else {
375  detector = new GGSDetectorConstruction(geometry, geoDataCard);
376  }
377  runManager->SetUserInitialization(detector);
378 
379  G4VUserPhysicsList *physicsList = nullptr;
380  // Try to create reference physics list
381  G4PhysListFactory *physListFactory = new G4PhysListFactory;
382  if (physListFactory->IsReferencePhysList(physicsListName)) {
383  physicsList = physListFactory->GetReferencePhysList(physicsListName);
384  }
385  // Try to create standard GGS physics lists
386  if (physicsList == nullptr) {
387 #ifdef CRMC
388  if (physicsListName == "GGSCRMC") {
389  physicsList = new GGSCRMCPhysicsList;
390  }
391 #endif
392  }
393  // Try to create user-defined physics list
394  if (physicsList == nullptr) {
395  // Try to load user defined list
396  physicsList = GGSMCPluginManager::GetInstance().LoadPhysicsListPlugin(physicsListName);
397  if (physicsList == nullptr) {
398  GGSCOUT(WARNING) << "User physics list has NOT been loaded. Fall back to standard list." << GGSENDL;
399  }
400  }
401  // Build standard list if no list have been selected or library loading wasn't successful
402  if (physicsList == nullptr) {
403  GGSCOUT(INFO) << "Load standard physics list: FTFP_BERT." << GGSENDL;
404  physicsListName = "FTFP_BERT";
405  physicsList = physListFactory->GetReferencePhysList(physicsListName);
406  }
407 
408  // Get the pointer to the User Interface manager
409  G4UImanager *UImanager = G4UImanager::GetUIpointer();
410 
411  // Execute physics list data card
412  if (physListDataCard != "") {
413  GGSCOUT(DEBUG) << "Execute physics list data card" << GGSENDL;
414  G4String command = "/control/execute ";
415  if (UImanager->ApplyCommand(command + physListDataCard) != 0) {
416  GGSCOUT(ERROR) << "Error in executing physics list datacard " << physListDataCard << GGSENDL;
417  return 1;
418  }
419  }
420 
421  runManager->SetUserInitialization(physicsList);
422 
423  // Load user and generator actions plugin libraries
424  // Must be done before creating the GGSMultiUserAction
425  for (unsigned int i = 0; i < actionPluginFiles.size(); i++)
426  GGSMCPluginManager::GetInstance().LoadPlugin(actionPluginFiles[i]);
427 
428  // Set user action initialization
429  if (multiThreadedMode) {
430  GGSCOUT(DEBUG) << "Set the user action initialization." << GGSENDL;
431  static_cast<GGSMTRunManager *>(runManager)->SetUserInitialization(new GGSUserActionInitialization);
432  } else {
433  GGSCOUT(DEBUG) << "Set the user action." << GGSENDL;
434  GGSMultiUserAction *muAction = new GGSMultiUserAction;
435  runManager->SetUserAction((G4UserSteppingAction *)muAction);
436  runManager->SetUserAction((G4UserTrackingAction *)muAction);
437  runManager->SetUserAction((G4UserEventAction *)muAction);
438  runManager->SetUserAction((G4UserRunAction *)muAction);
439  runManager->SetUserAction((G4UserStackingAction *)muAction);
440  }
441 
442  // Set default name, suffix of ROOT files
443  GGSCOUT(DEBUG) << "Initialize output." << GGSENDL;
444  if (rootOutputFile != "")
445  GGSRootFileService::GetInstance().SetDefaultFileBase(rootOutputFile.data());
447  // Set the MC info to be saved on ROOT files
448  GGSTSimInfo simInfo;
449  simInfo.SetName("GGSSimInfo");
450  simInfo.G4Version = G4Version.data();
451  simInfo.GGSVersion = GGSVERSION;
452  simInfo.dataCard = dataCard.data();
453  simInfo.geometry = geometry.data();
454  simInfo.geoDataCard = geoDataCard.data();
455  simInfo.physicsList = physicsListName.data();
456  simInfo.seed1 = seed1;
457  simInfo.seed2 = seed2;
459 
460  if (multiThreadedMode) {
461  static_cast<GGSMTRunManager *>(runManager)->SetUserInitialization(new GGSUserWorkerInitialization);
462  static_cast<GGSMTRunManager *>(runManager)->SetUserInitialization(new GGSUserWorkerThreadInitialization);
463  }
464 
465  // Initialize G4 kernel
466  GGSCOUT(DEBUG) << "Initialize run manager." << GGSENDL;
467  try {
468  runManager->Initialize();
469  } catch (std::runtime_error &exc) {
470  GGSCOUT(ERROR) << "Error while building the geometry: " << exc.what() << GGSENDL;
471  delete runManager;
472  delete physListFactory;
473  return 1;
474  } catch (...) {
475  GGSCOUT(ERROR) << "Impossible to set up the geometry due to an unknown exception. Exit." << GGSENDL;
476  delete runManager;
477  delete physListFactory;
478  return 1;
479  }
480 
481 #ifdef G4VIS_USE
482  // Create the ROOT cling interpreter before opening the graphical UI. This is needed to avoid
483  // loading LLVM symbols (e.g. when using open source Radeon driver for AMD chips) before
484  // creating the interpreter, which would cause a segmentation fault.
485  gROOT->GetInterpreter();
486  // Initialize visualization
487  //
488  G4VisManager *visManager = new G4VisExecutive;
489  visManager->Initialize();
490 #endif
491 
492  if (dataCard != "") { // batch or configured interactive mode
493  if (!interactiveMode) {
494  GGSCOUT(DEBUG) << "Start batch mode." << GGSENDL;
495  }
496  G4String command = "/control/execute ";
497  if (UImanager->ApplyCommand(command + dataCard) != 0) {
498  GGSCOUT(ERROR) << "Error in executing datacard " << dataCard << GGSENDL;
499  return 1;
500  }
501  }
502  if (interactiveMode) { // interactive mode : define UI session
503  if (dataCard != "") {
504  GGSCOUT(DEBUG) << "Start configured interactive mode." << GGSENDL;
505  } else {
506  GGSCOUT(DEBUG) << "Start interactive mode." << GGSENDL;
507  }
508 
509 #ifdef G4UI_USE
510  G4UIExecutive *ui = new G4UIExecutive(argc, argv);
511  struct stat st;
512 #ifdef G4VIS_USE
513  if (stat("vis.mac", &st) == 0) {
514  if (UImanager->ApplyCommand("/control/execute vis.mac") != 0) {
515  GGSCOUT(ERROR) << "Error in executing vis.mac visualization macro." << GGSENDL;
516  return 1;
517  }
518  }
519 #endif
520  if (ui->IsGUI()) {
521  if (stat("visTutor/gui.mac", &st) == 0) {
522  if (UImanager->ApplyCommand("/control/execute visTutor/gui.mac") != 0) {
523  GGSCOUT(ERROR) << "Error in executing visTutor/gui.mac visualization macro." << GGSENDL;
524  return 1;
525  }
526  }
527  }
528  ui->SessionStart();
529  delete ui;
530 #endif
531  }
532 
533  GGSCOUT(DEBUG) << "Job termination." << GGSENDL;
534 
535 #ifdef G4VIS_USE
536  delete visManager;
537 #endif
538  delete runManager;
539 
540  delete physListFactory;
541 
542  return 0;
543 }
544 
545 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
TString geometry
The geometry used for the simulation.
Definition: GGSTSimInfo.h:26
void SetDefaultFileBase(const std::filesystem::path &newFileBase)
Sets the default file name.
static GGSMCPluginManager & GetInstance()
Get the singleton instance.
#define GGSENDL
Definition: GGSSmartLog.h:131
User worker initialization class for GGS.
Class for GGS detector construction.
User action initialization class for GGS.
TString G4Version
Geant 4 version (as defined in G4Version.hh)
Definition: GGSTSimInfo.h:23
bool LoadPlugin(const std::string &libName)
Loads a plugin library.
A multiplexer container for user actions.
TString physicsList
The physics list used for the simulation.
Definition: GGSTSimInfo.h:27
TString geoDataCard
The data card file used for geometry configuration.
Definition: GGSTSimInfo.h:29
A multi-threaded run manager for GGS simulations.
static GGSRootFileService & GetInstance()
Get reference to GGSRootFileService unique instance.
void SetSuffix(const std::string &suffix)
Sets the suffix for file names.
void SetSimInfo(const GGSTSimInfo &simInfo)
Set the simulation info object to be saved on output files.
UInt_t seed2
Second random generator seed.
Definition: GGSTSimInfo.h:32
UInt_t seed1
First random generator seed.
Definition: GGSTSimInfo.h:31
TString dataCard
The data card file used for the simulation.
Definition: GGSTSimInfo.h:28
A class to store simulation informations.
Definition: GGSTSimInfo.h:21
G4VUserPhysicsList * LoadPhysicsListPlugin(const std::string &libName)
Loads a physics list plugin library.
User worker thread initialization class for GGS.
Physics list based on CRMC for high-energy hadron-hadron interactions.
TString GGSVersion
GGS version (as defined by GGSVERSION in Version.h)
Definition: GGSTSimInfo.h:24
A run manager for GGS simulations.
Definition: GGSRunManager.h:25