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.
11
12// gemc
13#include "g4world.h"
14#include "gfactory.h"
15
16// g4system
17#include "g4system_options.h"
18#include "g4systemConventions.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->getOptionalScalarString("useBackupMaterial"),
36 gopts->getRequiredScalarInt("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 previousRemainingVolumes = 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 const std::string defaultG4Factory = g4FactoryNameFromSystemFactory(gsystem->getFactoryName());
56
57 for (auto &[volumeName, gvolumePtr]: gsystem->getGVolumesMap()) {
58 auto *gvolume = gvolumePtr.get();
59 const std::string g4Factory = gvolume->getType() == gsystem::GSYSTEMCADTFACTORYLABEL
61 : defaultG4Factory;
62 auto objectsFactory = get_factory(g4Factory);
63
64 // Try to build; if dependencies are missing, remember it for the next iteration.
65 if (!build_g4volume(gvolume, objectsFactory)) {
66 // Only track volumes that are meant to exist; nonexistent volumes are skipped quietly.
67 if (gvolume->getExistence()) {
68 log->info(2, " >> adding volumeName <%1> to the list of remaining volumes", volumeName);
69 thisIterationRemainingVolumes.push_back(gvolume);
70 }
71 }
72 }
73
74 // Diagnostic listing of the volumes that could not be built due to missing mothers.
75 if (!thisIterationRemainingVolumes.empty()) {
76 log->info(
77 2, "G4World: %1 : %2 remaining motherless g4volumes to be built:", systemName,
78 thisIterationRemainingVolumes.size());
79 for (auto *gvolumeLeft: thisIterationRemainingVolumes) {
80 log->info(
81 2, "G4World: %1 with mother <%2> ", gvolumeLeft->getName(),
82 gvolumeLeft->getG4MotherName());
83 }
84 }
85 }
86
87 // Dependency-stall detection: error only when the remaining count fails to strictly
88 // decrease across iterations (a strictly smaller count means progress was made).
89 if (previousRemainingVolumes != 0 && !thisIterationRemainingVolumes.empty() &&
90 thisIterationRemainingVolumes.size() >= previousRemainingVolumes) {
91 for (auto *gvolumeLeft: thisIterationRemainingVolumes) {
92 log->warning(
93 " >> %1 with mother <%2> not built", gvolumeLeft->getName(),
94 gvolumeLeft->getG4MotherName());
95 }
96 log->error(
98 "dependencies are not being resolved: their number should diminish. Above are the "
99 "outstanding gvolumes");
100 }
101 previousRemainingVolumes = thisIterationRemainingVolumes.size();
102 } while (!thisIterationRemainingVolumes.empty());
103
104 // Phase 5: build optical surfaces (mirrors), now that all logical/physical volumes exist.
105 buildOpticalSurfaces(gsystemMap);
106
107 // Optional diagnostic output: list known materials from the Geant4 NIST manager.
108 if (gopts->getSwitch("showPredefinedMaterials")) { G4NistManager::Instance()->ListMaterials("all"); }
109
110 // Optional diagnostic output: print materials used in the simulation.
111 if (gopts->getSwitch("printSystemsMaterials")) {
112 auto matTable = (G4MaterialTable *) G4Material::GetMaterialTable();
113 for (auto thisMat: *matTable) {
114 log->info(
115 0, "%1G4World: GEMC Material: <%2>, density: %3g/cm3", 2, thisMat->GetName(),
116 thisMat->GetDensity() / (CLHEP::g / CLHEP::cm3));
117
118 // Print each component; negative/zero values mean "fractional mass", positive means "number of atoms".
119 for (auto &[material, component]: thisMat->GetMatComponents()) {
120 if (component > 0.0) {
121 log->info(0, "element%1number of atoms: %2", material->GetName(), component);
122 } else { log->info(0, "element%1fractional mass: %2", material->GetName(), component); }
123 }
124 }
125 }
126}
127
128/*──────────────────────── look-ups ──────────────────────────*/
129
130const G4Volume *G4World::getG4Volume(const std::string &volumeName) const {
131 auto it = g4volumesMap.find(volumeName);
132 return (it != g4volumesMap.end()) ? it->second : nullptr;
133}
134
135void G4World::setFieldManagerForVolume(const std::string &volumeName,
136 G4FieldManager *fm,
137 bool forceToAllDaughters) {
138 auto it = g4volumesMap.find(volumeName);
139 if (it != g4volumesMap.end()) it->second->setFieldManager(fm, forceToAllDaughters);
140}
141
142// ---- g4FactoryNameFromSystemFactory -----------------------------------------------------------
143std::string G4World::g4FactoryNameFromSystemFactory(const std::string &factory) const {
144 // Map GEMC system factory labels to g4system object factory labels.
145 if (factory == gsystem::GSYSTEMASCIIFACTORYLABEL ||
149 log->error(
151 "gsystemFactory factory <%1> is not mapped to any G4SystemFactory", factory);
152 }
153}
154
155void G4World::createG4SystemFactory(const std::shared_ptr<GOptions> &gopts,
156 SystemMap *gsystemsMap,
157 const std::optional<std::string> &backup_material,
158 int check_overlaps) {
159 // Instantiate a manager used to register and create factories.
160 GManager manager(gopts);
161
162 // Creating the native factory no matter what (it is the default for ASCII/SQLite/MySQL systems).
163 log->info(2, "G4World: registering default factory <%1>", g4system::G4SYSTEMNATFACTORY);
164 manager.RegisterObjectFactory<G4NativeSystemFactory>(g4system::G4SYSTEMNATFACTORY, gopts);
165
166 // Register factories based on the system factory label, then create/initialize them lazily.
167 for (auto &[gsystemName, gsystem]: *gsystemsMap) {
168 std::string factory = gsystem->getFactoryName();
169 std::string g4Factory = g4FactoryNameFromSystemFactory(factory);
170
171 log->info(2, "G4World: creating factory <%1> to for system <%2>", g4Factory, gsystemName);
172
173 // Register needed factory types:
174 // this will always be false for the default native label because it was registered above.
177 if (!g4systemFactory.contains(g4Factory)) {
178 manager.RegisterObjectFactory<G4NativeSystemFactory>(g4Factory, gopts);
179 }
180 } else if (factory == gsystem::GSYSTEMCADTFACTORYLABEL) {
181 if (!g4systemFactory.contains(g4system::G4SYSTEMCADFACTORY)) {
182 manager.RegisterObjectFactory<G4CadSystemFactory>(g4Factory, gopts);
183 }
184 }
185
186 // Create and initialize the concrete factory instance once per label.
187 if (!g4systemFactory.contains(g4Factory)) {
188 g4systemFactory[g4Factory] = manager.CreateObject<G4ObjectsFactory>(g4Factory);
189 g4systemFactory[g4Factory]->initialize_context(check_overlaps, backup_material);
190 }
191
192 // SQLite and text systems may mix native and CAD rows. Register the CAD object factory when
193 // any volume in this system declares solid=CAD, independently of the system loading factory.
194 for (const auto &[volumeName, gvolume]: gsystem->getGVolumesMap()) {
195 if (gvolume->getType() != gsystem::GSYSTEMCADTFACTORYLABEL ||
196 g4systemFactory.contains(g4system::G4SYSTEMCADFACTORY)) {
197 continue;
198 }
199
200 manager.RegisterObjectFactory<G4CadSystemFactory>(g4system::G4SYSTEMCADFACTORY, gopts);
201 g4systemFactory[g4system::G4SYSTEMCADFACTORY] =
202 manager.CreateObject<G4ObjectsFactory>(g4system::G4SYSTEMCADFACTORY);
203 g4systemFactory[g4system::G4SYSTEMCADFACTORY]->initialize_context(check_overlaps, backup_material);
204 }
205 }
206}
207
208void G4World::buildMaterials(SystemMap *system_map) {
209 // Build materials across all systems. Some materials may depend on other materials/elements,
210 // so we iterate until all dependencies are resolved or the resolution stalls.
211 std::vector<GMaterial *> thisIterationRemainingMaterials;
212 unsigned long previousRemainingMaterials = 0;
213 do {
214 thisIterationRemainingMaterials.clear();
215
216 for (const auto &[systemName, system]: *system_map) {
217 // Loop over the material map in each system and attempt to build each material.
218 for (const auto &[gmaterialName, gmaterialPtr]: system->getGMaterialMap()) {
219 if (createG4Material(gmaterialPtr) == false) {
220 thisIterationRemainingMaterials.push_back(gmaterialPtr.get());
221 }
222 }
223 }
224
225 // Dependency-stall detection for material building: error only when the remaining
226 // count fails to strictly decrease across iterations.
227 if (previousRemainingMaterials != 0 && !thisIterationRemainingMaterials.empty() &&
228 thisIterationRemainingMaterials.size() >= previousRemainingMaterials) {
229 for (auto &gmaterialLeft: thisIterationRemainingMaterials) {
230 log->warning("%1", gmaterialLeft->getName());
231 }
232 log->error(
234 "Dependencies are not being resolved: their number should diminish. Above are the "
235 "Outstanding gmaterials");
236 }
237 previousRemainingMaterials = thisIterationRemainingMaterials.size();
238 } while (!thisIterationRemainingMaterials.empty());
239}
240
241bool G4World::build_g4volume(const GVolume *s, G4ObjectsFactory *objectsFactory) {
242 log->info(
243 2, "G4World: using factory <%1> to build g4volume <%2>", objectsFactory->className(), s->getG4Name());
244
245 return objectsFactory->build_g4volume(s, &g4volumesMap);
246}
Factory that converts CAD files (PLY / STL) into Geant4 tessellated solids via CADMesh.
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:52
void setFieldManager(G4FieldManager *fm, bool forceToAllDaughters)
Attach a G4FieldManager to the stored logical volume, if present.
Definition g4volume.cc:28
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:135
G4ObjectsFactory * get_factory(const std::string &factoryName)
Retrieve a registered factory by name.
Definition g4world.h:128
const G4Volume * getG4Volume(const std::string &volumeName) const
Return the G4Volume wrapper for a volume name.
Definition g4world.cc:130
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
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.
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
constexpr char G4SYSTEMNATFACTORY[]
constexpr char G4SYSTEMCADFACTORY[]
constexpr int ERR_G4SYSTEMFACTORYNOTFOUND
A required Geant4 system factory was not found/mapped.
constexpr int ERR_G4DEPENDENCIESNOTSOLVED
Geometry/material dependencies could not be resolved.
constexpr char GSYSTEMCADTFACTORYLABEL[]
constexpr char GSYSTEMMYSQLTFACTORYLABEL[]
constexpr char GSYSTEMSQLITETFACTORYLABEL[]
constexpr char GSYSTEMASCIIFACTORYLABEL[]