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, 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, FUNCTION_NAME, "creating world from options");
85 gworld = std::make_shared<GWorld>(gopt);
86 } else {
87 log->debug(NORMAL, FUNCTION_NAME, "creating world from a gsystem vector of size ", 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(0, "Tally summary: \n - ", gworld->get_number_of_volumes() - 1, " volumes\n - ",
98 g4world->number_of_volumes(), " geant4 built volumes\n - ",
99 nsdetectors, " sensitive detectors\n");
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, 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(1, "No explicit global field selected: using the only configured field <",
166 global_field_name, "> on the ROOT world volume.");
167 }
168 }
169 const bool global_field_set = !disable_all_fields && !is_unset_field_name(global_field_name);
170
171 // First pass: collect the fields that are actually used so only their plugins and maps are loaded.
172 // Volumes (or the global field) reset via -no_field are excluded here and never trigger a load.
173 std::set<std::string> required_fields;
174 std::set<std::string> matched_no_field;
175 if (!disable_all_fields) {
176 for (const auto &[systemName, gsystemPtr]: *gworld->getSystemsMap()) {
177 for (const auto &[volumeName, gvolumePtr]: gsystemPtr->getGVolumesMap()) {
178 const auto &g4name = gvolumePtr->getG4Name();
179 const bool reset = no_field_volumes.count(volumeName) || no_field_volumes.count(g4name);
180 if (no_field_volumes.count(volumeName)) { matched_no_field.insert(volumeName); }
181 if (no_field_volumes.count(g4name)) { matched_no_field.insert(g4name); }
182
183 const auto &field_name = gvolumePtr->getEMField();
184 if (!field_name || reset) { continue; }
185 required_fields.insert(*field_name);
186 }
187 }
188 for (const auto &name: no_field_volumes) {
189 if (!matched_no_field.count(name)) {
190 log->warning("-", gfields::NO_FIELD_OPTION, ": volume <", name, "> not found in the geometry.");
191 }
192 }
193 }
194 if (global_field_set) { required_fields.insert(global_field_name); }
195
196 // Build the magnetic-field registry only when at least one field is needed: if every field was reset
197 // (e.g. -no_field=all) no plugin or field map is loaded at all.
198 if (!required_fields.empty() && gmagneto == nullptr) { gmagneto = new GMagneto(gopt, required_fields); }
199
200 // Loop over all systems and their volumes.
201 for (const auto &[systemName, gsystemPtr]: *gworld->getSystemsMap()) {
202 for (const auto &[volumeName, gvolumePtr]: gsystemPtr->getGVolumesMap()) {
203 auto const &digitizationName = gvolumePtr->getDigitization();
204 auto const &g4name = gvolumePtr->getG4Name();
205
206 // Component volumes are boolean-operation building blocks: they have a
207 // solid but no logical volume, no field, and no sensitivity.
208 if (gvolumePtr->getMaterial() == gsystem::GSYSTEMCOMPONENTMATERIAL) { continue; }
209
210 auto *g4volume = g4world->getG4Volume(g4name)->getLogical();
211
212 // Ensure the Geant4 logical volume exists.
213 // Some GEMC volumes can be "copy-of" another volume; in that case, reuse the
214 // referenced Geant4 logical volume rather than failing.
215 if (g4volume == nullptr) {
216 const auto& copyOf = gvolumePtr->getCopyOf();
217 if (copyOf) {
218 auto gsystem = gvolumePtr->getSystem();
219 auto volume_copy = gsystem + "/" + *copyOf;
220 auto copyG4Volume = g4world->getG4Volume(volume_copy)->getLogical();
221 if (copyG4Volume != nullptr) { g4volume = copyG4Volume; } else {
223 " Logical volume copy <" + volume_copy + "> not found.");
224 }
225 }
226 }
227 if (g4volume == nullptr) {
228 log->error(gsystem::ERR_GVOLUMENOTFOUND, FUNCTION_NAME, " Logical volume <" + g4name + "> not found.");
229 }
230
231 // Skip volumes with no digitization.
232 if (digitizationName) {
233 const std::string& digitization = *digitizationName;
234
235 // Obtain (or create) the sensitive detector for this digitization name.
236 // We reuse an existing SD object already in G4SDManager rather than creating a
237 // new one because AddNewDetector() keeps the OLD object on duplicate names (DET1010).
238 // If we created a new SD, G4SDManager would call Initialize() on the stale object
239 // while SetSensitiveDetector() pointed the logical volume to the new one — leaving
240 // the new SD's gHitsCollection uninitialized when ProcessHits() is called.
241 if (sensitiveDetectorsMap.find(digitization) == sensitiveDetectorsMap.end()) {
242 // Reuse a previously registered SD for this name if one exists on this thread.
243 // AddNewDetector() silently keeps the OLD object on duplicate names (DET1010);
244 // reusing the same pointer avoids that and ensures G4SDManager's Initialize()
245 // fires on the same object that SetSensitiveDetector() wires to the volumes.
246 auto tlIt = tlSDMap->find(digitization);
247 if (tlIt != tlSDMap->end()) {
248 log->info(2, "Reusing existing sensitive detector <", digitization, "> for volume <", g4name, ">");
249 tlIt->second->resetTouchableMap();
250 tlIt->second->Activate(true);
251 sensitiveDetectorsMap[digitization] = tlIt->second;
252 } else {
253 log->info(2, "Creating new sensitive detector <", digitization, "> for volume <", g4name, ">");
254 auto* newSD = new GSensitiveDetector(digitization, gopt);
255 sdManager->AddNewDetector(newSD);
256 sensitiveDetectorsMap[digitization] = newSD;
257 (*tlSDMap)[digitization] = newSD;
258 }
259 } else {
260 log->info(2, "Sensitive detector <", digitization,
261 "> is already created and available for volume <", g4name, ">");
262 }
263
264 // Register the volume touchable with the sensitive detector.
265 // The touchable encodes identity and dimension metadata needed by digitization.
266 const auto &vdimensions = gvolumePtr->getDetectorDimensions();
267 const auto &identity = gvolumePtr->getGIdentity();
268 if (!identity) {
269 log->error(gsystem::ERR_GWRONGNUMBEROFPARS, "Sensitive volume <", g4name,
270 "> has digitization <", digitization, "> but no identifier.");
271 }
272 const auto &mass = g4volume->GetMass();
273 auto this_gtouchable = std::make_shared<
274 GTouchable>(gopt, digitization, *identity, vdimensions, mass);
275 sensitiveDetectorsMap[digitization]->registerGVolumeTouchable(g4name, this_gtouchable);
276
277 // Attach the SD to the logical volume (no AddNewDetector call needed for reused SDs).
278 g4volume->SetSensitiveDetector(sensitiveDetectorsMap[digitization]);
279
280 // auto maxStep =
281
282 //g4volume->SetUserLimits(new G4UserLimits(0.1*mm, 0.1*mm));
283
284 log->info(2, "Logical Volume <" + g4name + "> has been successfully assigned to SD.",
285 sensitiveDetectorsMap[digitization]);
286 }
287
288 // Process electromagnetic fields.
289 // If a volume declares an EM field, install a per-volume field manager configured by the
290 // named field map, unless that field was reset via -no_field (a matching name, or =all).
291 const auto &field_name = gvolumePtr->getEMField();
292 const bool volume_field_present = field_name.has_value();
293 const bool volume_field_reset = disable_all_fields ||
294 no_field_volumes.count(volumeName) || no_field_volumes.count(g4name);
295 if (volume_field_present && volume_field_reset) {
296 log->info(2, "Volume <", volumeName, "> field <", *field_name, "> reset by -",
297 gfields::NO_FIELD_OPTION, ": no field installed.");
298 } else if (volume_field_present) {
299 log->info(2, "Volume <", volumeName, "> has field: <", *field_name,
300 ">. Looking into field map definitions.");
301 log->info(2, "Setting field manager for volume <", g4name, "> with field <", *field_name, ">");
302 g4world->setFieldManagerForVolume(g4name, gmagneto->getFieldMgr(*field_name).get(), true);
303 }
304 }
305 }
306
307 // Process the global field, if requested and not reset via -no_field=all.
308 // A global field is associated with the ROOT world volume and propagated to all daughters, so it
309 // applies everywhere a more specific per-volume field has not been installed.
310 if (global_field_set) {
311 log->info(2, "Setting global field manager for the ROOT world volume <", gsystem::ROOTWORLDGVOLUMENAME,
312 "> with field <", global_field_name, ">");
313 g4world->setFieldManagerForVolume(gsystem::ROOTWORLDGVOLUMENAME,
314 gmagneto->getFieldMgr(global_field_name).get(), true);
315 } else if (disable_all_fields && global_field_name != "" &&
316 !is_unset_field_name(global_field_name)) {
317 log->info(2, "Global field <", global_field_name, "> reset by -", gfields::NO_FIELD_OPTION, "=",
318 gfields::NO_FIELD_ALL, ": none installed.");
319 }
320
321 // Bind each digitization routine to its corresponding sensitive detector.
322 const auto sdetectors = gworld->getSensitiveDetectorsList();
323 for (auto &sdname: sdetectors) {
324 auto digitization_routine = digitization_routines_map->at(sdname);
325
326 sensitiveDetectorsMap[sdname]->assign_digi_routine(digitization_routine);
327 log->info(1, "Digitization routine <" + sdname + "> has been successfully assigned to SD.",
328 sensitiveDetectorsMap[sdname]);
329 }
330}
331
332
333// Installs readout step limits once on the master-owned logical volumes.
334void GDetectorConstruction::assignUserLimits() {
335 const auto sdetectors = gworld->getSensitiveDetectorsList();
336 for (const auto& sdname : sdetectors) {
337 const auto digitization_routine = digitization_routines_map->at(sdname);
338 const auto max_step = digitization_routine->readoutSpecs->getMaxStep();
339 auto limits = std::make_unique<G4UserLimits>(max_step);
340 auto* limits_ptr = limits.get();
341 user_limits.emplace_back(std::move(limits));
342
343 for (const auto& [system_name, system] : *gworld->getSystemsMap()) {
344 for (const auto& [volume_name, volume] : system->getGVolumesMap()) {
345 const auto& digitization_name = volume->getDigitization();
346 if (!digitization_name || *digitization_name != sdname) { continue; }
347
348 const auto& g4name = volume->getG4Name();
349 const auto* g4volume = g4world->getG4Volume(g4name);
350 if (g4volume == nullptr || g4volume->getLogical() == nullptr) {
351 log->error(gsystem::ERR_GVOLUMENOTFOUND, FUNCTION_NAME,
352 " Logical volume <" + g4name + "> not found while assigning user limits.");
353 continue;
354 }
355
356 g4volume->getLogical()->SetUserLimits(limits_ptr);
357 log->info(1, "Setting G4UserLimits for volume <", g4name,
358 "> with maxStep <", max_step, ">");
359 }
360 }
361 }
362}
363
364// Loads (or dynamically resolves) the digitization routine for each sensitive detector.
365void GDetectorConstruction::loadDigitizationPlugins() {
366 // Clear stale entries so a reloaded geometry always gets fresh routines.
367 // emplace() would silently skip existing keys, causing hits not to be recorded
368 // when the geometry is reloaded with the same SD names.
369 digitization_routines_map->clear();
370
371 // Resolve the variation each routine uses to load constants / translation tables.
372 // By default a routine follows the variation of the gsystem it belongs to; the
373 // digitization_variation option, when set, overrides that for every routine.
374 const auto digiVariationOverride = gopt->getOptionalScalarString("digitization_variation");
375
376 // Map each digitization (sensitive-detector) name to its system's variation.
377 std::map<std::string, std::string> systemVariationFor;
378 for (const auto& [systemName, gsystemPtr] : *gworld->getSystemsMap()) {
379 for (const auto& [volumeName, gvolumePtr] : gsystemPtr->getGVolumesMap()) {
380 const auto& digiName = gvolumePtr->getDigitization();
381 if (digiName) {
382 systemVariationFor.emplace(*digiName, gsystemPtr->getVariation());
383 }
384 }
385 }
386
387 const auto sdetectors = gworld->getSensitiveDetectorsList();
388
389 for (auto &sdname: sdetectors) {
390 if (sdname == gtouchable::FLUXNAME) {
391 log->info(1, "Loading flux digitization plugin for routine <" + sdname + ">");
392 digitization_routines_map->emplace(sdname, std::make_shared<GFluxDigitization>(gopt));
393 } else if (sdname == gtouchable::GPHOTON_DETECTORNAME) {
394 log->info(1, "Loading gPhotonDetector digitization plugin for routine <" + sdname + ">");
395 digitization_routines_map->emplace(sdname, std::make_shared<GPhotonDetectorDigitization>(gopt));
396 } else if (sdname == gtouchable::COUNTERNAME) {
397 log->info(1, "Loading particle counter digitization plugin for routine <" + sdname + ">");
398 digitization_routines_map->emplace(sdname, std::make_shared<GParticleCounterDigitization>(gopt));
399 } else if (sdname == gtouchable::DOSIMETERNAME) {
400 log->info(1, "Loading dosimeter digitization plugin for routine <" + sdname + ">");
401 digitization_routines_map->emplace(sdname, std::make_shared<GDosimeterDigitization>(gopt));
402 } else {
403 // if it's not in the map already, add it
404 log->info(0, "Loading new digitization plugin for routine <" + sdname + ">");
405 digitization_routines_map->emplace(sdname, gdynamicdigitization::load_dynamicRoutine(sdname, gopt));
406 }
407
408 // Ensure each routine uses the correct logger and is configured for readout.
409 digitization_routines_map->at(sdname)->set_loggers(gopt);
410
411 // Resolve and store the variation used when loading this routine's constants/TT:
412 // the digitization_variation option when set, otherwise the routine's gsystem variation.
413 std::string variation = "default";
414 if (const auto it = systemVariationFor.find(sdname); it != systemVariationFor.end()) {
415 variation = it->second;
416 }
417 if (digiVariationOverride) { variation = *digiVariationOverride; }
418 digitization_routines_map->at(sdname)->setDigitizationVariation(variation);
419
420 // Resolve whether this system applies threshold / efficiency rejection, from the
421 // global applyThresholds / applyInefficiencies options (default: neither).
422 digitization_routines_map->at(sdname)->setHitRejectionPolicies(sdname);
423
424 if (digitization_routines_map->at(sdname)->defineReadoutSpecs()) {
425 log->info(1, "Digitization routine <" + sdname + "> has been successfully defined.");
426 } else { log->error(ERR_DEFINESPECFAIL, "defineReadoutSpecs failure for <" + sdname + ">"); }
427 }
428}
429
430
431SystemList GDetectorConstruction::cloneSystemDescriptors(const SystemList& systems) const {
432 SystemList descriptors;
433 descriptors.reserve(systems.size());
434
435 for (const auto& system: systems) {
436 if (system != nullptr) {
437 descriptors.emplace_back(system->descriptorClone(gopt));
438 }
439 }
440
441 return descriptors;
442}
443
444
446 // Geometry is changing: ensure Construct() reloads the digitization plugins.
447 digiplugins_need_reload = true;
448
449 // it could be empty for tests
450 if (!sl.empty()) {
451 gsystems = cloneSystemDescriptors(sl);
452 }
453
454 // Reconstruct the master geometry immediately so GUI pages can inspect the
455 // new world without starting worker threads during a setup-tab reload.
456 auto rm = G4RunManager::GetRunManager();
457
458 if (rm) {
459 // Null out the vis manager while we clean and rebuild the geometry stores.
460 // G4*Store::Clean() would otherwise leave the ToolsSG scene graph with
461 // dangling references to deleted Geant4 objects, causing a crash on the
462 // next visualization flush.
463 auto* visManager = G4VVisManager::GetConcreteInstance();
464 GVisManagerGuard::set(nullptr);
465 rm->DefineWorldVolume(Construct());
466 GVisManagerGuard::set(visManager);
468 } else { log->error(1, "GDetectorConstruction::reload_geometry", "Geant4 Run manager not found."); }
469}
470
472 auto rm = G4RunManager::GetRunManager();
473
474 if (rm) {
475 auto* visManager = G4VVisManager::GetConcreteInstance();
476 GVisManagerGuard::set(nullptr);
477 // Geometry is being rebuilt: ensure Construct() reloads the digitization plugins.
478 digiplugins_need_reload = true;
479 rm->ReinitializeGeometry(true, true);
480 rm->GeometryHasBeenModified();
481 // Optical processes such as G4Cerenkov cache material-property tables by
482 // material index. A setup-tab reload can introduce a different variation's
483 // optical material, so force physics tables to rebuild after the new
484 // geometry/material set has been installed.
485 rm->PhysicsHasBeenModified();
486 rm->Initialize();
487 GVisManagerGuard::set(visManager);
488 } else { log->error(1, "GDetectorConstruction::prepare_geometry_for_run", "Geant4 Run manager not found."); }
489}
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[]