-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgemc.cc
More file actions
193 lines (149 loc) · 6.87 KB
/
Copy pathgemc.cc
File metadata and controls
193 lines (149 loc) · 6.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
// geant4
#include "G4RunManagerFactory.hh"
#include "G4VisExecutive.hh"
#include "G4UIterminal.hh"
#include "G4UItcsh.hh"
#include "G4UIQt.hh"
#include "G4TransportationParameters.hh"
// gemc
#include "gemc_options.h"
#include "gemcUtilities.h"
#include "eventDispenser.h"
#include "g4SceneProperties.h"
#include "gphysics.h"
#include "gui.h"
#include "gdetectorConstruction.h"
#include "gaction.h"
#include "gstreamer.h"
#include "gsystem_options.h"
#include "gfield_options.h"
// c++
#include <chrono>
#include <cstdlib>
#if defined(__linux__)
#include <cstdio> // IWYU pragma: keep -- std::fflush on the Linux fast-exit path in main()
#endif
int main(int argc, char* argv[]) {
// Anchor for the optional -print_summary timing report (total wall-clock time).
const auto program_start = std::chrono::steady_clock::now();
auto base_schema = gemc::defineOptions();
base_schema += gemc::collectPluginOptions(argc, argv);
auto gopts = std::make_shared<GOptions>(argc, argv, base_schema);
auto log = std::make_shared<GLogger>(gopts, SFUNCTION_NAME, GENERAL_LOGGER);
if (gfields::runFieldQueries(gopts)) { return EXIT_SUCCESS; }
auto gui = gopts->getSwitch("gui");
auto nthreads = gemc::get_nthreads(gopts, log);
auto has_startup_geometry = !gsystem::getSystems(gopts).empty() ||
!gfields::get_GFieldDefinition(gopts).empty();
// createQtApplication returns a QApplication if gui is true
// otherwise, it returns a QCoreApplication and sets the Geant4 CoutDestination to a GBatch_Session
auto app = gemc::makeQtApplication(argc, argv, gui);
// splash screen - nullptr if in batch mode
auto spash_screen = GSplash::create(gopts, "gemcArchitecture", 0.7);
// random engine set by options
gemc::start_random_engine(gopts, log);
// GUI runs are interactive and short-lived; use the serial run manager to avoid repeatedly
// starting task workers from the Qt event loop on each Run button click.
const auto runManagerType = gui ? G4RunManagerType::SerialOnly : G4RunManagerType::Default;
// init geant4 run manager with then number of threads coming from options. always fails if unavailable
auto runManager = std::unique_ptr<G4RunManager>(
G4RunManagerFactory::CreateRunManager(runManagerType, true, nthreads));
// Pre-load streamer plugins before Geant4 creates worker threads. Sanitized Linux
// builds can fail late dlopen() calls from workers with static TLS exhaustion.
// Declaring this after runManager makes it destruct before runManager at shutdown.
auto preloaded_gstreamer_map = gstreamer::preloadGStreamerPlugins(gopts);
// must be a raw pointer because geant4 takes ownership
auto gdetector = new GDetectorConstruction(gopts);
runManager->SetUserInitialization(gdetector);
// define new units
gemc::define_new_gemc_units();
// starting gphysics, exit immediately if phys list requested
auto gphysics = new GPhysics(gopts);
if (gopts->getSwitch("showPhysics")) { return EXIT_SUCCESS; }
runManager->SetUserInitialization(gphysics->getPhysList());
// instantiate GActionInitialization and initialize the geant4 kernel
runManager->SetUserInitialization(new GAction(gopts, gdetector->get_digitization_routines_map()));
// sets verbosity commands
auto verbosities = gemc::verbosity_commands(gopts, log);
gemc::run_manager_commands(gopts, log, verbosities);
G4double warningE = 10.0 * CLHEP::keV;
G4double importantE = 1 * CLHEP::GeV;
G4int numTrials = 30;
auto transportParams = G4TransportationParameters::Instance();
transportParams->SetWarningEnergy(warningE);
transportParams->SetImportantEnergy(importantE);
transportParams->SetNumberOfTrials(numTrials);
// G4VisExecutive can take a verbosity argument - see /vis/verbose guidance
// notice we initialize this in batch mode as well
auto visManager = new G4VisExecutive("Quiet");
visManager->Initialize();
auto geventDispenser = std::make_shared<EventDispenser>(gopts, gdetector->get_digitization_routines_map());
auto app_result = EXIT_SUCCESS;
auto init_commands = gemc::initial_commands(gopts, log, has_startup_geometry);
if (gui) {
// initializing qt session
spash_screen->message("Starting GUI");
QCoreApplication::processEvents();
// initializing G4UIQt session.
// notice g4SceneProperties has to be declared after this, so we have to duplicate it for batch mode
auto* uiQtSession = new G4UIQt(1, argv);
auto* g4SceneProperties = new G4SceneProperties(gopts);
std::vector<std::string> scene_commands;
if (has_startup_geometry) { scene_commands = g4SceneProperties->scene_commands(gopts); }
// add init_commands to scene_commands
scene_commands.insert(scene_commands.end(), init_commands.begin(), init_commands.end());
// run scene_commands
gemc::run_manager_commands(gopts, log, scene_commands);
GemcGUI gemcGui(gopts, geventDispenser, gdetector, has_startup_geometry);
gemcGui.show();
spash_screen->finish(&gemcGui);
app_result = QApplication::exec();
preloaded_gstreamer_map.reset();
runManager.reset();
delete g4SceneProperties;
delete uiQtSession;
}
else {
auto* session = new G4UIterminal(new G4UItcsh);
auto* g4SceneProperties = new G4SceneProperties(gopts);
std::vector<std::string> scene_commands;
if (has_startup_geometry) { scene_commands = g4SceneProperties->scene_commands(gopts); }
// set display properties in batch mode
scene_commands.insert(scene_commands.end(), init_commands.begin(), init_commands.end());
gemc::run_manager_commands(gopts, log, scene_commands);
// start the session if interactive
if (gopts->getSwitch("i")) { session->SessionStart(); }
geventDispenser->processEvents();
delete g4SceneProperties;
delete session;
}
// print_summary is a switch, on by default; disable with -print_summary=false.
if (gopts->getSwitch("print_summary")) {
const auto now = std::chrono::steady_clock::now();
const double total_s = std::chrono::duration<double>(now - program_start).count();
log->info(0, "Timing summary: total simulation time ", total_s, " seconds.");
if (geventDispenser->beamOnIssued()) {
const double beam_s = std::chrono::duration<double>(now - geventDispenser->beamOnStartTime()).count();
const int total_n = geventDispenser->getTotalNumberOfEvents();
log->info(0, "Timing summary: total time since beamOn was issued ", beam_s, " seconds.");
if (beam_s > 0.0) {
const double avg_rate = static_cast<double>(total_n) / beam_s;
log->info(0, "Timing summary: average event rate ", avg_rate, " events / second (",
total_n, " events / ", beam_s, " seconds).");
}
}
}
geventDispenser.reset();
preloaded_gstreamer_map.reset();
runManager.reset();
// Avoid explicit G4VisExecutive teardown in batch shutdown. On Linux/Geant4 11.4
// this can double-free the process-wide G4Colour table during static exit.
log->info(0, "Simulation completed, arrivederci! ");
#if defined(__linux__)
if (!gui) {
std::fflush(nullptr);
std::_Exit(app_result);
}
#endif
return app_result;
}