g4system
Loading...
Searching...
No Matches
g4world.cc
Go to the documentation of this file.
1// g4world.cc : implementation of the Geant4 world builder and material initialization.
12// gemc
13#include "g4world.h"
14#include "gfactory.h"
15
16// g4system
17#include "g4system_options.h"
19#include "gsystemConventions.h"
22
23
24// c++
25#include <vector>
26
27G4World::G4World(const GWorld *gworld, const std::shared_ptr<GOptions> &gopts)
28 : GBase(gopts, G4SYSTEM_LOGGER) {
29 auto gsystemMap = gworld->getSystemsMap();
30
31 // Phase 1: create and initialize a Geant4 object factory for each system.
32 // The factory provides solid/logical/physical creation for volumes in that system.
33 createG4SystemFactory(gopts,
34 gsystemMap,
35 gopts->getScalarString("useBackupMaterial"),
36 gopts->getScalarInt("check_overlaps")
37 );
38
39 // Phase 2: build all materials across systems, resolving dependencies iteratively.
40 buildMaterials(gsystemMap);
41
42 // Phase 3: ensure common isotopes/elements/materials exist (used by typical configurations).
43 buildDefaultMaterialsElementsAndIsotopes();
44
45 // Phase 4: build volumes. Some volumes depend on mothers that may not exist yet,
46 // so we iterate until the remaining list becomes empty or the dependency resolution stalls.
47 std::vector<GVolume *> thisIterationRemainingVolumes;
48 unsigned long allRemainingVolumes = 0;
49
50 do {
51 thisIterationRemainingVolumes.clear();
52
53 // Loop over all systems and attempt to build all volumes in each system.
54 for (auto &[systemName, gsystem]: *gsystemMap) {
55 std::string g4Factory = g4FactoryNameFromSystemFactory(gsystem->getFactoryName());
56 auto objectsFactory = get_factory(g4Factory);
57
58 for (auto &[volumeName, gvolumePtr]: gsystem->getGVolumesMap()) {
59 auto *gvolume = gvolumePtr.get();
60
61 // Try to build; if dependencies are missing, remember it for the next iteration.
62 if (!build_g4volume(gvolume, objectsFactory)) {
63 // Only track volumes that are meant to exist; nonexistent volumes are skipped quietly.
64 if (gvolume->getExistence()) {
65 log->info(2, " >> adding volumeName <", volumeName, "> to the list of remaining volumes");
66 thisIterationRemainingVolumes.push_back(gvolume);
67 }
68 }
69 }
70
71 // Diagnostic listing of the volumes that could not be built due to missing mothers.
72 if (!thisIterationRemainingVolumes.empty()) {
73 log->info(2, "G4World: ", systemName, " : ",
74 thisIterationRemainingVolumes.size(),
75 " remaining motherless g4volumes to be built:");
76 for (auto *gvolumeLeft: thisIterationRemainingVolumes) {
77 log->info(2, "G4World: ", gvolumeLeft->getName(),
78 " with mother <", gvolumeLeft->getG4MotherName(), "> ");
79 }
80 }
81 }
82
83 // Dependency-stall detection:
84 // If the number of remaining volumes does not decrease across iterations, dependencies are not solvable.
85 if (allRemainingVolumes != 0 && !thisIterationRemainingVolumes.empty()) {
86 if (allRemainingVolumes >= thisIterationRemainingVolumes.size()) {
87 for (auto *gvolumeLeft: thisIterationRemainingVolumes) {
88 log->warning(" >> ", gvolumeLeft->getName(),
89 " with mother <", gvolumeLeft->getG4MotherName(), "> not built");
90 }
92 "dependencies are not being resolved: their number should diminish. "
93 "Above are the outstanding gvolumes");
94 }
95 } else { allRemainingVolumes = thisIterationRemainingVolumes.size(); }
96 } while (!thisIterationRemainingVolumes.empty());
97
98 // Optional diagnostic output: list known materials from the Geant4 NIST manager.
99 if (gopts->getSwitch("showPredefinedMaterials")) { G4NistManager::Instance()->ListMaterials("all"); }
100
101 // Optional diagnostic output: print materials used in the simulation.
102 if (gopts->getSwitch("printSystemsMaterials")) {
103 auto matTable = (G4MaterialTable *) G4Material::GetMaterialTable();
104 for (auto thisMat: *matTable) {
105 log->info(0, 2, "G4World: GEMC Material: <", thisMat->GetName(), ">, density: ",
106 thisMat->GetDensity() / (CLHEP::g / CLHEP::cm3), "g/cm3");
107
108 // Print each component; negative/zero values mean "fractional mass", positive means "number of atoms".
109 for (auto &[material, component]: thisMat->GetMatComponents()) {
110 if (component > 0.0) {
111 log->info(0, "element", material->GetName(), "number of atoms: ", component);
112 } else { log->info(0, "element", material->GetName(), "fractional mass: ", component); }
113 }
114 }
115 }
116}
117
118/*──────────────────────── look-ups ──────────────────────────*/
119
120const G4Volume *G4World::getG4Volume(const std::string &volumeName) const {
121 auto it = g4volumesMap.find(volumeName);
122 return (it != g4volumesMap.end()) ? it->second : nullptr;
123}
124
125void G4World::setFieldManagerForVolume(const std::string &volumeName,
126 G4FieldManager *fm,
127 bool forceToAllDaughters) {
128 auto it = g4volumesMap.find(volumeName);
129 if (it != g4volumesMap.end()) it->second->setFieldManager(fm, forceToAllDaughters);
130}
131
132// ---- g4FactoryNameFromSystemFactory -----------------------------------------------------------
133std::string G4World::g4FactoryNameFromSystemFactory(const std::string &factory) const {
134 // Map GEMC system factory labels to g4system object factory labels.
135 if (factory == GSYSTEMASCIIFACTORYLABEL ||
136 factory == GSYSTEMSQLITETFACTORYLABEL ||
137 factory == GSYSTEMMYSQLTFACTORYLABEL) { return G4SYSTEMNATFACTORY; } else if (
138 factory == GSYSTEMCADTFACTORYLABEL) { return G4SYSTEMCADFACTORY; } else {
140 "gsystemFactory factory <", factory, "> is not mapped to any G4SystemFactory");
141 }
142}
143
144void G4World::createG4SystemFactory(const std::shared_ptr<GOptions> &gopts,
145 SystemMap *gsystemsMap,
146 const std::string &backup_material,
147 int check_overlaps) {
148 // Instantiate a manager used to register and create factories.
149 GManager manager(gopts);
150
151 // Creating the native factory no matter what (it is the default for ASCII/SQLite/MySQL systems).
152 log->info(2, "G4World: registering default factory <", G4SYSTEMNATFACTORY, ">");
153 manager.RegisterObjectFactory<G4NativeSystemFactory>(G4SYSTEMNATFACTORY, gopts);
154
155 // Register factories based on the system factory label, then create/initialize them lazily.
156 for (auto &[gsystemName, gsystem]: *gsystemsMap) {
157 std::string factory = gsystem->getFactoryName();
158 std::string g4Factory = g4FactoryNameFromSystemFactory(factory);
159
160 log->info(2, "G4World: creating factory <", g4Factory, "> to for system <", gsystemName, ">");
161
162 // Register needed factory types:
163 // this will always be false for the default native label because it was registered above.
164 if (factory == GSYSTEMASCIIFACTORYLABEL || factory == GSYSTEMSQLITETFACTORYLABEL ||
165 factory == GSYSTEMMYSQLTFACTORYLABEL) {
166 if (g4systemFactory.find(g4Factory) == g4systemFactory.end()) {
167 manager.RegisterObjectFactory<G4NativeSystemFactory>(g4Factory, gopts);
168 }
169 } else if (factory == GSYSTEMCADTFACTORYLABEL) {
170 if (g4systemFactory.find(GSYSTEMCADTFACTORYLABEL) == g4systemFactory.end()) {
171 manager.RegisterObjectFactory<G4CadSystemFactory>(g4Factory, gopts);
172 }
173 }
174
175 // Create and initialize the concrete factory instance once per label.
176 if (g4systemFactory.find(g4Factory) == g4systemFactory.end()) {
177 g4systemFactory[g4Factory] = manager.CreateObject<G4ObjectsFactory>(g4Factory);
178 g4systemFactory[g4Factory]->initialize_context(check_overlaps, backup_material);
179 }
180 }
181}
182
183void G4World::buildMaterials(SystemMap *system_map) {
184 // Build materials across all systems. Some materials may depend on other materials/elements,
185 // so we iterate until all dependencies are resolved or the resolution stalls.
186 std::vector<GMaterial *> thisIterationRemainingMaterials;
187 unsigned long allRemainingMaterials = 0;
188 do {
189 thisIterationRemainingMaterials.clear();
190
191 for (const auto &[systemName, system]: *system_map) {
192 // Loop over the material map in each system and attempt to build each material.
193 for (const auto &[gmaterialName, gmaterialPtr]: system->getGMaterialMap()) {
194 if (createG4Material(gmaterialPtr) == false) {
195 thisIterationRemainingMaterials.push_back(gmaterialPtr.get());
196 }
197 }
198 }
199
200 // Dependency-stall detection for material building.
201 if (allRemainingMaterials != 0 && !thisIterationRemainingMaterials.empty()) {
202 if (allRemainingMaterials >= thisIterationRemainingMaterials.size()) {
203 for (auto &gmaterialLeft: thisIterationRemainingMaterials) { log->warning(gmaterialLeft->getName()); }
205 "Dependencies are not being resolved: their number should diminish. Above are the Outstanding gmaterials");
206 }
207 } else { allRemainingMaterials = thisIterationRemainingMaterials.size(); }
208 } while (!thisIterationRemainingMaterials.empty());
209}
210
211bool G4World::build_g4volume(const GVolume *s, G4ObjectsFactory *objectsFactory) {
212 log->info(2, "G4World: using factory <", objectsFactory->className(),
213 "> to build g4volume <", s->getG4Name(), ">");
214
215 return objectsFactory->build_g4volume(s, &g4volumesMap);
216}
Factory that converts CAD files (PLY / STL) into Geant4 tessellated solids via CADMesh.
Builds a tessellated solid from CAD files using CADMesh.
Implements solid creation for Geant4 CSG primitives and validates constructor parameter counts.
Base class orchestrating the conversion of a GVolume into a Geant4 representation.
bool build_g4volume(const GVolume *s, std::unordered_map< std::string, G4Volume * > *g4s)
Build (or retrieve) solid, logical, and physical volumes for a given GVolume.
virtual std::string_view className() const =0
Short, human-readable factory name for logging.
Convenience container holding a Geant4 solid, logical, and physical volume.
Definition g4volume.h:50
G4World(const GWorld *gworld, const std::shared_ptr< GOptions > &gopts)
Construct and build the Geant4 world from a GEMC world.
Definition g4world.cc:27
void setFieldManagerForVolume(const std::string &volumeName, G4FieldManager *fm, bool forceToAllDaughters)
Attach a G4FieldManager to the logical volume of a named volume.
Definition g4world.cc:125
G4ObjectsFactory * get_factory(const std::string &factoryName)
Retrieve a registered factory by name.
Definition g4world.h:112
const G4Volume * getG4Volume(const std::string &volumeName) const
Return the G4Volume wrapper for a volume name.
Definition g4world.cc:120
std::shared_ptr< GLogger > log
void warning(Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
std::string getG4Name() const
SystemMap * getSystemsMap() const
Factory that builds Geant4 native primitive solids (G4Box, G4Cons, G4Trap, ...) from GEMC GVolume rec...
Conventions, labels, and error codes used by the g4system geometry/material layer.
#define ERR_G4SYSTEMFACTORYNOTFOUND
A required Geant4 system factory was not found/mapped.
#define ERR_G4DEPENDENCIESNOTSOLVED
Geometry/material dependencies could not be resolved.
#define G4SYSTEMNATFACTORY
#define G4SYSTEMCADFACTORY
Option definitions for the g4system module (geometry/material construction layer).
constexpr const char * G4SYSTEM_LOGGER
Logger name used by the module-level builder (e.g. G4World).
High-level builder that turns a GEMC world description into Geant4 geometry.
std::map< std::string, SystemPtr > SystemMap