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