gdetector
Loading...
Searching...
No Matches
gdetectorConstruction.cc
Go to the documentation of this file.
1// gdetectorConstruction
3#include "gdetector_options.h"
4
5// gemc
9#include "gsystem_options.h"
11#include "gFluxDigitization.h"
14#include "gfield_options.h"
15
16// geant4
17#include "G4SDManager.hh"
18#include "G4RunManager.hh"
19#include "G4Threading.hh"
20#include "G4UserLimits.hh"
21#include "G4VVisManager.hh"
22
23namespace {
24bool is_unset_field_name(const std::string& name) {
25 return name.empty() || name == UNINITIALIZEDSTRINGQUANTITY || name == "NULL" || name == "not provided";
26}
27
28class GVisManagerGuard : public G4VVisManager {
29public:
30 static void set(G4VVisManager* visManager) { SetConcreteInstance(visManager); }
31
32 void Draw(const G4Circle&, const G4Transform3D&) override {}
33 void Draw(const G4Polyhedron&, const G4Transform3D&) override {}
34 void Draw(const G4Polyline&, const G4Transform3D&) override {}
35 void Draw(const G4Polymarker&, const G4Transform3D&) override {}
36 void Draw(const G4Square&, const G4Transform3D&) override {}
37 void Draw(const G4Text&, const G4Transform3D&) override {}
38 void Draw2D(const G4Circle&, const G4Transform3D&) override {}
39 void Draw2D(const G4Polyhedron&, const G4Transform3D&) override {}
40 void Draw2D(const G4Polyline&, const G4Transform3D&) override {}
41 void Draw2D(const G4Polymarker&, const G4Transform3D&) override {}
42 void Draw2D(const G4Square&, const G4Transform3D&) override {}
43 void Draw2D(const G4Text&, const G4Transform3D&) override {}
44 void Draw(const G4VTrajectory&) override {}
45 void Draw(const G4VHit&) override {}
46 void Draw(const G4VDigi&) override {}
47 void Draw(const G4LogicalVolume&, const G4VisAttributes&, const G4Transform3D&) override {}
48 void Draw(const G4VPhysicalVolume&, const G4VisAttributes&, const G4Transform3D&) override {}
49 void Draw(const G4VSolid&, const G4VisAttributes&, const G4Transform3D&) override {}
50 void BeginDraw(const G4Transform3D&) override {}
51 void EndDraw() override {}
52 void BeginDraw2D(const G4Transform3D&) override {}
53 void EndDraw2D() override {}
54 void GeometryHasChanged() override {}
55 void DispatchToModel(const G4VTrajectory&) override {}
56 G4bool FilterTrajectory(const G4VTrajectory&) override { return true; }
57 G4bool FilterHit(const G4VHit&) override { return true; }
58 G4bool FilterDigi(const G4VDigi&) override { return true; }
59};
60}
61
62G4ThreadLocal GMagneto *GDetectorConstruction::gmagneto = nullptr;
63G4ThreadLocal std::map<std::string, GSensitiveDetector*>* GDetectorConstruction::tlSDMap = nullptr;
64
65GDetectorConstruction::GDetectorConstruction(std::shared_ptr<GOptions> gopts)
66 : GBase(gopts, GDETECTOR_LOGGER),
67 G4VUserDetectorConstruction(), // Geant4 base class.
68 gopt(gopts) {
69 // Map is populated after SDs exist, in the SD/field construction path.
70 digitization_routines_map = std::make_shared<gdynamicdigitization::dRoutinesMap>();
71}
72
73// Builds (or rebuilds) the GEMC world and then the Geant4 world.
76
77 // Delete old geometry objects if they exist.
78 // These shared_ptr resets guarantee we won't keep references to stale world objects.
79 gworld.reset();
80 g4world.reset();
81
82 // - if no systems are provided, we just launched gemc: create from options
83 // - otherwise, it's a geometry re-load. use existing systems.
84 if (gsystems.empty()) {
85 log->debug(NORMAL, FUNCTION_NAME, "creating world from options");
86 gworld = std::make_shared<GWorld>(gopt);
87 } else {
88 log->debug(NORMAL, FUNCTION_NAME, "creating world from a gsystem vector of size ", gsystems.size());
89 gworld = std::make_shared<GWorld>(gopt, cloneSystemDescriptors(gsystems));
90 }
91
92 // Build Geant4 world (solids, logical and physical volumes) based on the GEMC world.
93 g4world = std::make_shared<G4World>(gworld.get(), gopt);
94
95 auto nsdetectors = gworld->getSensitiveDetectorsList().size();
96
97 // tally with number :
98 log->info(0, "Tally summary: \n - ", gworld->get_number_of_volumes() - 1, " volumes\n - ",
99 g4world->number_of_volumes(), " geant4 built volumes\n - ",
100 nsdetectors, " sensitive detectors\n");
101
102
103 // Return the physical volume for the ROOT world volume.
104 return g4world->getG4Volume(ROOTWORLDGVOLUMENAME)->getPhysical();
105}
106
107// Installs sensitive detectors and EM fields for the constructed geometry.
109 auto sdManager = G4SDManager::GetSDMpointer();
110
112
113 // Deactivate all SDs this thread registered in prior geometry loads.
114 // G4SDManager retains SDs indefinitely across reloads; an active stale SD has
115 // Initialize() called at the start of every event even when no volume uses it,
116 // producing orphan hit collections whose names are absent from the digitization map.
117 // We deactivate them here and reactivate only those needed for the current geometry.
118 if (!tlSDMap) {
119 tlSDMap = new std::map<std::string, GSensitiveDetector*>();
120 }
121 for (auto& [name, sd] : *tlSDMap) {
122 sd->Activate(false);
123 }
124
125 // Local cache of sensitive detectors keyed by digitization name.
126 // Multiple volumes can share the same digitization name and therefore reuse one SD instance.
127 std::unordered_map<std::string, GSensitiveDetector *> sensitiveDetectorsMap;
128
129 // --- Electromagnetic field reset (-no_field) --------------------------------------------------
130 // Parse -no_field: a gvolume name, a whitespace/comma-separated list of gvolume names, or 'all'.
131 // 'all' resets every per-volume field and the global field; a name resets only that volume's field.
132 bool disable_all_fields = false;
133 std::set<std::string> no_field_volumes;
134 {
135 auto no_field_value = gopt->getScalarString(NO_FIELD_OPTION);
136 if (no_field_value != "" && no_field_value != UNINITIALIZEDSTRINGQUANTITY && no_field_value != "NULL") {
137 if (no_field_value == NO_FIELD_ALL) { disable_all_fields = true; }
138 else {
139 for (auto &c : no_field_value) { if (c == ',') { c = ' '; } }
140 for (const auto &v : gutilities::getStringVectorFromString(no_field_value)) {
141 no_field_volumes.insert(v);
142 }
143 }
144 }
145 }
146
147 // Global field name, honoring -no_field=all.
148 const bool no_system_selected = gsystems.empty() && gsystem::getSystems(gopt).empty();
149 auto global_field_name = gopt->getScalarString(GLOBAL_FIELD_OPTION);
150 if (no_system_selected && !disable_all_fields && is_unset_field_name(global_field_name)) {
151 std::vector<std::string> configured_fields;
152 for (const auto& field_definition : gfields::get_GFieldDefinition(gopt)) {
153 if (!is_unset_field_name(field_definition.name) && field_definition.name != goptions::NODFLT) {
154 configured_fields.push_back(field_definition.name);
155 }
156 }
157 if (configured_fields.size() == 1) {
158 global_field_name = configured_fields.front();
159 log->info(1, "No explicit global field selected: using the only configured field <",
160 global_field_name, "> on the ROOT world volume.");
161 }
162 }
163 const bool global_field_set = !disable_all_fields && !is_unset_field_name(global_field_name);
164
165 // First pass: collect the fields that are actually used so only their plugins and maps are loaded.
166 // Volumes (or the global field) reset via -no_field are excluded here and never trigger a load.
167 std::set<std::string> required_fields;
168 std::set<std::string> matched_no_field;
169 if (!disable_all_fields) {
170 for (const auto &[systemName, gsystemPtr]: *gworld->getSystemsMap()) {
171 for (const auto &[volumeName, gvolumePtr]: gsystemPtr->getGVolumesMap()) {
172 const auto &g4name = gvolumePtr->getG4Name();
173 const bool reset = no_field_volumes.count(volumeName) || no_field_volumes.count(g4name);
174 if (no_field_volumes.count(volumeName)) { matched_no_field.insert(volumeName); }
175 if (no_field_volumes.count(g4name)) { matched_no_field.insert(g4name); }
176
177 const auto &field_name = gvolumePtr->getEMField();
178 if (is_unset_field_name(field_name) || reset) { continue; }
179 required_fields.insert(field_name);
180 }
181 }
182 for (const auto &name: no_field_volumes) {
183 if (!matched_no_field.count(name)) {
184 log->warning("-", NO_FIELD_OPTION, ": volume <", name, "> not found in the geometry.");
185 }
186 }
187 }
188 if (global_field_set) { required_fields.insert(global_field_name); }
189
190 // Build the magnetic-field registry only when at least one field is needed: if every field was reset
191 // (e.g. -no_field=all) no plugin or field map is loaded at all.
192 if (!required_fields.empty() && gmagneto == nullptr) { gmagneto = new GMagneto(gopt, required_fields); }
193
194 // Loop over all systems and their volumes.
195 for (const auto &[systemName, gsystemPtr]: *gworld->getSystemsMap()) {
196 for (const auto &[volumeName, gvolumePtr]: gsystemPtr->getGVolumesMap()) {
197 auto const &digitizationName = gvolumePtr->getDigitization();
198 auto const &g4name = gvolumePtr->getG4Name();
199
200 // Component volumes are boolean-operation building blocks: they have a
201 // solid but no logical volume, no field, and no sensitivity.
202 if (gvolumePtr->getMaterial() == GSYSTEMCOMPONENTMATERIAL) { continue; }
203
204 auto *g4volume = g4world->getG4Volume(g4name)->getLogical();
205
206 // Ensure the Geant4 logical volume exists.
207 // Some GEMC volumes can be "copy-of" another volume; in that case, reuse the
208 // referenced Geant4 logical volume rather than failing.
209 if (g4volume == nullptr) {
210 std::string copyOf = gvolumePtr->getCopyOf();
211 if (copyOf != "" && copyOf != UNINITIALIZEDSTRINGQUANTITY) {
212 auto gsystem = gvolumePtr->getSystem();
213 auto volume_copy = gsystem + "/" + copyOf;
214 auto copyG4Volume = g4world->getG4Volume(volume_copy)->getLogical();
215 if (copyG4Volume != nullptr) { g4volume = copyG4Volume; } else {
217 " Logical volume copy <" + volume_copy + "> not found.");
218 }
219 }
220 }
221 if (g4volume == nullptr) {
222 log->error(ERR_GVOLUMENOTFOUND, FUNCTION_NAME, " Logical volume <" + g4name + "> not found.");
223 }
224
225 // Skip volumes with no digitization.
226 if (digitizationName != "" && digitizationName != UNINITIALIZEDSTRINGQUANTITY) {
227 // Obtain (or create) the sensitive detector for this digitization name.
228 // We reuse an existing SD object already in G4SDManager rather than creating a
229 // new one because AddNewDetector() keeps the OLD object on duplicate names (DET1010).
230 // If we created a new SD, G4SDManager would call Initialize() on the stale object
231 // while SetSensitiveDetector() pointed the logical volume to the new one — leaving
232 // the new SD's gHitsCollection uninitialized when ProcessHits() is called.
233 if (sensitiveDetectorsMap.find(digitizationName) == sensitiveDetectorsMap.end()) {
234 // Reuse a previously registered SD for this name if one exists on this thread.
235 // AddNewDetector() silently keeps the OLD object on duplicate names (DET1010);
236 // reusing the same pointer avoids that and ensures G4SDManager's Initialize()
237 // fires on the same object that SetSensitiveDetector() wires to the volumes.
238 auto tlIt = tlSDMap->find(digitizationName);
239 if (tlIt != tlSDMap->end()) {
240 log->info(2, "Reusing existing sensitive detector <", digitizationName, "> for volume <", g4name, ">");
241 tlIt->second->resetTouchableMap();
242 tlIt->second->Activate(true);
243 sensitiveDetectorsMap[digitizationName] = tlIt->second;
244 } else {
245 log->info(2, "Creating new sensitive detector <", digitizationName, "> for volume <", g4name, ">");
246 auto* newSD = new GSensitiveDetector(digitizationName, gopt);
247 sdManager->AddNewDetector(newSD);
248 sensitiveDetectorsMap[digitizationName] = newSD;
249 (*tlSDMap)[digitizationName] = newSD;
250 }
251 } else {
252 log->info(2, "Sensitive detector <", digitizationName,
253 "> is already created and available for volume <", g4name, ">");
254 }
255
256 // Register the volume touchable with the sensitive detector.
257 // The touchable encodes identity and dimension metadata needed by digitization.
258 const auto &vdimensions = gvolumePtr->getDetectorDimensions();
259 const auto &identity = gvolumePtr->getGIdentity();
260 const auto &mass = g4volume->GetMass();
261 auto this_gtouchable = std::make_shared<
262 GTouchable>(gopt, digitizationName, identity, vdimensions, mass);
263 sensitiveDetectorsMap[digitizationName]->registerGVolumeTouchable(g4name, this_gtouchable);
264
265 // Attach the SD to the logical volume (no AddNewDetector call needed for reused SDs).
266 g4volume->SetSensitiveDetector(sensitiveDetectorsMap[digitizationName]);
267
268 // auto maxStep =
269
270 //g4volume->SetUserLimits(new G4UserLimits(0.1*mm, 0.1*mm));
271
272 log->info(2, "Logical Volume <" + g4name + "> has been successfully assigned to SD.",
273 sensitiveDetectorsMap[digitizationName]);
274 }
275
276 // Process electromagnetic fields.
277 // If a volume declares an EM field, install a per-volume field manager configured by the
278 // named field map, unless that field was reset via -no_field (a matching name, or =all).
279 const auto &field_name = gvolumePtr->getEMField();
280 const bool volume_field_present = !is_unset_field_name(field_name);
281 const bool volume_field_reset = disable_all_fields ||
282 no_field_volumes.count(volumeName) || no_field_volumes.count(g4name);
283 if (volume_field_present && volume_field_reset) {
284 log->info(2, "Volume <", volumeName, "> field <", field_name, "> reset by -",
285 NO_FIELD_OPTION, ": no field installed.");
286 } else if (volume_field_present) {
287 log->info(2, "Volume <", volumeName, "> has field: <", field_name,
288 ">. Looking into field map definitions.");
289 log->info(2, "Setting field manager for volume <", g4name, "> with field <", field_name, ">");
290 g4world->setFieldManagerForVolume(g4name, gmagneto->getFieldMgr(field_name).get(), true);
291 }
292 }
293 }
294
295 // Process the global field, if requested and not reset via -no_field=all.
296 // A global field is associated with the ROOT world volume and propagated to all daughters, so it
297 // applies everywhere a more specific per-volume field has not been installed.
298 if (global_field_set) {
299 log->info(2, "Setting global field manager for the ROOT world volume <", ROOTWORLDGVOLUMENAME,
300 "> with field <", global_field_name, ">");
302 gmagneto->getFieldMgr(global_field_name).get(), true);
303 } else if (disable_all_fields && global_field_name != "" &&
304 !is_unset_field_name(global_field_name)) {
305 log->info(2, "Global field <", global_field_name, "> reset by -", NO_FIELD_OPTION, "=",
306 NO_FIELD_ALL, ": none installed.");
307 }
308
309 // Load digitization plugins only when geometry has changed and only on the master thread.
310 // digiplugins_need_reload is set true by reload_geometry() and prepare_geometry_for_run()
311 // so that routine BeamOn re-initializations (which also call ConstructSDandField() on the
312 // master) do not clear the shared map while worker threads may be concurrently reading it.
313 if (G4Threading::IsMasterThread() && digiplugins_need_reload) {
314 loadDigitizationPlugins();
315 digiplugins_need_reload = false;
316 }
317
318 // Bind each digitization routine to its corresponding sensitive detector.
319 const auto sdetectors = gworld->getSensitiveDetectorsList();
320 for (auto &sdname: sdetectors) {
321 auto digitization_routine = digitization_routines_map->at(sdname);
322 double maxStep = digitization_routine->readoutSpecs->getMaxStep();
323
324 sensitiveDetectorsMap[sdname]->assign_digi_routine(digitization_routine);
325 log->info(1, "Digitization routine <" + sdname + "> has been successfully assigned to SD.",
326 sensitiveDetectorsMap[sdname]);
327
328 // Loop over all systems and their volumes.
329 // and assign max step to the corresponding logical volume
330 for (const auto &[systemName, gsystemPtr]: *gworld->getSystemsMap()) {
331 for (const auto &[volumeName, gvolumePtr]: gsystemPtr->getGVolumesMap()) {
332 auto const &digitizationName = gvolumePtr->getDigitization();
333 if (digitizationName == sdname) {
334 auto const &g4name = gvolumePtr->getG4Name();
335 auto *g4volume = g4world->getG4Volume(g4name)->getLogical();
336
337 // g4volume->SetUserLimits(new G4UserLimits(maxStep, maxStep)); // this will also kill track cause
338 // the second argument is max track length
339 g4volume->SetUserLimits(new G4UserLimits(maxStep));
340
341 log->info(1, "Setting G4UserLimits for volume <", g4name, "> with maxStep <", maxStep, ">");
342 }
343 }
344 }
345 }
346}
347
348// Loads (or dynamically resolves) the digitization routine for each sensitive detector.
349void GDetectorConstruction::loadDigitizationPlugins() {
350 // Clear stale entries so a reloaded geometry always gets fresh routines.
351 // emplace() would silently skip existing keys, causing hits not to be recorded
352 // when the geometry is reloaded with the same SD names.
353 digitization_routines_map->clear();
354
355 // Resolve the variation each routine uses to load constants / translation tables.
356 // By default a routine follows the variation of the gsystem it belongs to; the
357 // digitization_variation option, when set, overrides that for every routine.
358 const std::string digiVariationOverride = gopt->getScalarString("digitization_variation");
359 const bool overrideVariation = (digiVariationOverride != UNINITIALIZEDSTRINGQUANTITY);
360
361 // Map each digitization (sensitive-detector) name to its system's variation.
362 std::map<std::string, std::string> systemVariationFor;
363 for (const auto& [systemName, gsystemPtr] : *gworld->getSystemsMap()) {
364 for (const auto& [volumeName, gvolumePtr] : gsystemPtr->getGVolumesMap()) {
365 const auto& digiName = gvolumePtr->getDigitization();
366 if (digiName != "" && digiName != UNINITIALIZEDSTRINGQUANTITY) {
367 systemVariationFor.emplace(digiName, gsystemPtr->getVariation());
368 }
369 }
370 }
371
372 const auto sdetectors = gworld->getSensitiveDetectorsList();
373
374 for (auto &sdname: sdetectors) {
375 if (sdname == FLUXNAME) {
376 log->info(1, "Loading flux digitization plugin for routine <" + sdname + ">");
377 digitization_routines_map->emplace(sdname, std::make_shared<GFluxDigitization>(gopt));
378 } else if (sdname == GPHOTON_DETECTORNAME) {
379 log->info(1, "Loading gPhotonDetector digitization plugin for routine <" + sdname + ">");
380 digitization_routines_map->emplace(sdname, std::make_shared<GPhotonDetectorDigitization>(gopt));
381 } else if (sdname == COUNTERNAME) {
382 log->info(1, "Loading particle counter digitization plugin for routine <" + sdname + ">");
383 digitization_routines_map->emplace(sdname, std::make_shared<GParticleCounterDigitization>(gopt));
384 } else if (sdname == DOSIMETERNAME) {
385 log->info(1, "Loading dosimeter digitization plugin for routine <" + sdname + ">");
386 digitization_routines_map->emplace(sdname, std::make_shared<GDosimeterDigitization>(gopt));
387 } else {
388 // if it's not in the map already, add it
389 log->info(0, "Loading new digitization plugin for routine <" + sdname + ">");
390 digitization_routines_map->emplace(sdname, gdynamicdigitization::load_dynamicRoutine(sdname, gopt));
391 }
392
393 // Ensure each routine uses the correct logger and is configured for readout.
394 digitization_routines_map->at(sdname)->set_loggers(gopt);
395
396 // Resolve and store the variation used when loading this routine's constants/TT:
397 // the digitization_variation option when set, otherwise the routine's gsystem variation.
398 std::string variation = "default";
399 if (const auto it = systemVariationFor.find(sdname); it != systemVariationFor.end()) {
400 variation = it->second;
401 }
402 if (overrideVariation) { variation = digiVariationOverride; }
403 digitization_routines_map->at(sdname)->setDigitizationVariation(variation);
404
405 // Resolve whether this system applies threshold / efficiency rejection, from the
406 // global applyThresholds / applyInefficiencies options (default: neither).
407 digitization_routines_map->at(sdname)->setHitRejectionPolicies(sdname);
408
409 if (digitization_routines_map->at(sdname)->defineReadoutSpecs()) {
410 log->info(1, "Digitization routine <" + sdname + "> has been successfully defined.");
411 } else { log->error(ERR_DEFINESPECFAIL, "defineReadoutSpecs failure for <" + sdname + ">"); }
412 }
413}
414
415
416SystemList GDetectorConstruction::cloneSystemDescriptors(const SystemList& systems) const {
417 SystemList descriptors;
418 descriptors.reserve(systems.size());
419
420 for (const auto& system: systems) {
421 if (system != nullptr) {
422 descriptors.emplace_back(system->descriptorClone(gopt));
423 }
424 }
425
426 return descriptors;
427}
428
429
431 // Geometry is changing: ensure loadDigitizationPlugins() runs on the next ConstructSDandField().
432 digiplugins_need_reload = true;
433
434 // it could be empty for tests
435 if (!sl.empty()) {
436 gsystems = cloneSystemDescriptors(sl);
437 }
438
439 // Reconstruct the master geometry immediately so GUI pages can inspect the
440 // new world without starting worker threads during a setup-tab reload.
441 auto rm = G4RunManager::GetRunManager();
442
443 if (rm) {
444 // Null out the vis manager while we clean and rebuild the geometry stores.
445 // G4*Store::Clean() would otherwise leave the ToolsSG scene graph with
446 // dangling references to deleted Geant4 objects, causing a crash on the
447 // next visualization flush.
448 auto* visManager = G4VVisManager::GetConcreteInstance();
449 GVisManagerGuard::set(nullptr);
450 rm->DefineWorldVolume(Construct());
451 GVisManagerGuard::set(visManager);
453 } else { log->error(1, "GDetectorConstruction::reload_geometry", "Geant4 Run manager not found."); }
454}
455
457 auto rm = G4RunManager::GetRunManager();
458
459 if (rm) {
460 auto* visManager = G4VVisManager::GetConcreteInstance();
461 GVisManagerGuard::set(nullptr);
462 // Geometry is being rebuilt: ensure loadDigitizationPlugins() runs inside Initialize().
463 digiplugins_need_reload = true;
464 rm->ReinitializeGeometry(true, true);
465 rm->GeometryHasBeenModified();
466 // Optical processes such as G4Cerenkov cache material-property tables by
467 // material index. A setup-tab reload can introduce a different variation's
468 // optical material, so force physics tables to rebuild after the new
469 // geometry/material set has been installed.
470 rm->PhysicsHasBeenModified();
471 rm->Initialize();
472 GVisManagerGuard::set(visManager);
473 } else { log->error(1, "GDetectorConstruction::prepare_geometry_for_run", "Geant4 Run manager not found."); }
474}
G4VPhysicalVolume * getPhysical() const noexcept
G4LogicalVolume * getLogical() const noexcept
std::size_t number_of_volumes() const noexcept
void setFieldManagerForVolume(const std::string &volumeName, G4FieldManager *fm, bool forceToAllDaughters)
const G4Volume * getG4Volume(const std::string &volumeName) const
std::shared_ptr< GLogger > log
GDetectorConstruction(std::shared_ptr< GOptions > gopts)
Constructs a detector builder configured by the provided options.
void reload_geometry(SystemList sl)
Reloads the geometry using a new list of GSystem objects.
G4VPhysicalVolume * Construct() override
Geant4 geometry construction hook.
void ConstructSDandField() override
Geant4 SD/field construction hook.
void prepare_geometry_for_run()
Reinitializes geometry through Geant4 before running events.
void warning(Args &&... args) const
void debug(debug_type type, Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
std::shared_ptr< G4FieldManager > getFieldMgr(std::string name)
std::string getScalarString(const std::string &tag) const
int get_number_of_volumes() const
std::vector< std::string > getSensitiveDetectorsList()
SystemMap * getSystemsMap() const
Defines the GDetectorConstruction class, the Geant4 detector-construction entry point for the gdetect...
Declares the gdetector module option aggregation entry point.
constexpr const char * GDETECTOR_LOGGER
Logger name used by the gdetector module.
#define FUNCTION_NAME
NORMAL
#define NO_FIELD_ALL
#define NO_FIELD_OPTION
#define GLOBAL_FIELD_OPTION
#define ERR_GVOLUMENOTFOUND
#define GSYSTEMCOMPONENTMATERIAL
#define ROOTWORLDGVOLUMENAME
std::vector< SystemPtr > SystemList
#define UNINITIALIZEDSTRINGQUANTITY
std::shared_ptr< GDynamicDigitization > load_dynamicRoutine(const std::string &plugin_name, const std::shared_ptr< GOptions > &gopts)
std::vector< GFieldDefinition > get_GFieldDefinition(const std::shared_ptr< GOptions > &gopts)
const std::string NODFLT
SystemList getSystems(const std::shared_ptr< GOptions > &gopts)
vector< std::string > getStringVectorFromString(const std::string &input)