24#include "G4MaterialTable.hh"
25#include "G4Material.hh"
26#include "G4Element.hh"
27#include "G4Isotope.hh"
38 createG4SystemFactory(gopts,
40 gopts->getScalarString(
"useBackupMaterial"),
41 gopts->getScalarInt(
"check_overlaps")
45 buildMaterials(gsystemMap);
48 buildDefaultMaterialsElementsAndIsotopes();
52 std::vector<GVolume*> thisIterationRemainingVolumes;
53 unsigned long allRemainingVolumes = 0;
56 thisIterationRemainingVolumes.clear();
59 for (
auto& [systemName,
gsystem] : *gsystemMap) {
60 std::string g4Factory = g4FactoryNameFromSystemFactory(
gsystem->getFactoryName());
63 for (
auto& [volumeName, gvolumePtr] :
gsystem->getGVolumesMap()) {
64 auto* gvolume = gvolumePtr.get();
67 if (!build_g4volume(gvolume, objectsFactory)) {
69 if (gvolume->getExistence()) {
70 log->
warning(
" >> adding volumeName <", volumeName,
"> to the list of remaining volumes");
71 thisIterationRemainingVolumes.push_back(gvolume);
77 if (!thisIterationRemainingVolumes.empty()) {
78 log->
info(2,
"G4World: ", systemName,
" : ",
79 thisIterationRemainingVolumes.size(),
80 " remaining motherless g4volumes to be built:");
81 for (
auto* gvolumeLeft : thisIterationRemainingVolumes) {
82 log->
info(2,
"G4World: ", gvolumeLeft->getName(),
83 " with mother <", gvolumeLeft->getG4MotherName(),
"> ");
90 if (allRemainingVolumes != 0 && !thisIterationRemainingVolumes.empty()) {
91 if (allRemainingVolumes >= thisIterationRemainingVolumes.size()) {
92 for (
auto* gvolumeLeft : thisIterationRemainingVolumes) {
94 " with mother <", gvolumeLeft->getG4MotherName(),
"> not built");
97 "dependencies are not being resolved: their number should diminish. "
98 "Above are the outstanding gvolumes");
101 else { allRemainingVolumes = thisIterationRemainingVolumes.size(); }
103 while (!thisIterationRemainingVolumes.empty());
106 if (gopts->getSwitch(
"showPredefinedMaterials")) { G4NistManager::Instance()->ListMaterials(
"all"); }
109 if (gopts->getSwitch(
"printSystemsMaterials")) {
110 auto matTable = (G4MaterialTable*)G4Material::GetMaterialTable();
111 for (
auto thisMat : *matTable) {
112 log->
info(0, 2,
"G4World: GEMC Material: <", thisMat->GetName(),
">, density: ",
113 thisMat->GetDensity() / (CLHEP::g / CLHEP::cm3),
"g/cm3");
116 for (
auto& [material, component] : thisMat->GetMatComponents()) {
117 if (component > 0.0) {
log->
info(0,
"element", material->GetName(),
"number of atoms: ", component); }
118 else {
log->
info(0,
"element", material->GetName(),
"fractional mass: ", component); }
127 auto it = g4volumesMap.find(volumeName);
128 return (it != g4volumesMap.end()) ? it->second :
nullptr;
133 bool forceToAllDaughters) {
134 auto it = g4volumesMap.find(volumeName);
135 if (it != g4volumesMap.end()) it->second->setFieldManager(fm, forceToAllDaughters);
139std::string G4World::g4FactoryNameFromSystemFactory(
const std::string& factory)
const {
141 if (factory == GSYSTEMASCIIFACTORYLABEL ||
142 factory == GSYSTEMSQLITETFACTORYLABEL ||
147 "gsystemFactory factory <", factory,
"> is not mapped to any G4SystemFactory");
151bool G4World::createG4Material(
const std::shared_ptr<GMaterial>& gmaterial) {
152 auto NISTman = G4NistManager::Instance();
153 auto materialName = gmaterial->getName();
156 auto g4material = NISTman->FindMaterial(materialName);
157 if (g4material !=
nullptr) {
158 log->
info(2,
"Material <", materialName,
"> already exists in G4NistManager");
162 auto components = gmaterial->getComponents();
163 auto amounts = gmaterial->getAmounts();
164 bool isChemical = gmaterial->isChemicalFormula();
168 for (
auto& componentName : components) {
170 if (NISTman->FindOrBuildElement(componentName) ==
nullptr) {
171 log->
info(2,
"Element <", componentName,
">, needed by ", materialName,
", not found yet");
174 else {
log->
info(2,
"Element <", componentName,
"> needed by ", materialName,
" now found"); }
177 if (NISTman->FindOrBuildMaterial(componentName) ==
nullptr) {
178 log->
info(2,
"Material <", componentName,
">, needed by ", materialName,
", not found yet");
181 else {
log->
info(2,
"Material <", componentName,
"> needed by ", materialName,
" now found"); }
186 auto density = gmaterial->getDensity();
187 g4materialsMap[materialName] =
new G4Material(materialName, density * CLHEP::g / CLHEP::cm3,
188 static_cast<G4int
>(components.size()));
191 log->
info(2,
"Building material <", materialName,
"> with components:");
192 for (
size_t i = 0; i < components.size(); i++) {
193 log->
info(2,
"element <", components[i],
"> with amount: ", amounts[i]);
196 for (
size_t i = 0; i < components.size(); i++) {
197 auto element = NISTman->FindOrBuildElement(components[i]);
198 g4materialsMap[materialName]->AddElement(element,
static_cast<G4int
>(amounts[i]));
202 log->
info(2,
"Building material <", materialName,
"> with components:");
203 for (
size_t i = 0; i < components.size(); i++) {
204 log->
info(2,
"material <", components[i],
"> with fractional mass: ", amounts[i]);
207 for (
size_t i = 0; i < components.size(); i++) {
208 auto material = NISTman->FindOrBuildMaterial(components[i]);
209 g4materialsMap[materialName]->AddMaterial(material, amounts[i]);
216void G4World::buildDefaultMaterialsElementsAndIsotopes() {
225 if (G4NistManager::Instance()->FindMaterial(
HGAS_MATERIAL) ==
nullptr) {
227 a = 1.01 * CLHEP::g / CLHEP::mole;
228 d = 0.00275 * CLHEP::g / CLHEP::cm3;
229 T = 50.0 * CLHEP::kelvin;
238 log->
info(2,
"G4World: Hydrogen gas material <",
HGAS_MATERIAL,
"> created with density <", d,
">");
243 if (G4NistManager::Instance()->FindOrBuildElement(
DEUTERIUM_ELEMENT) ==
nullptr) {
246 a = 2.0141018 * CLHEP::g / CLHEP::mole;
251 Deuterium->AddIsotope(Deuteron, 1);
257 d = 0.000452 * CLHEP::g / CLHEP::cm3;
258 T = 294.25 * CLHEP::kelvin;
269 if (G4NistManager::Instance()->FindMaterial(
LD2_MATERIAL) ==
nullptr) {
270 d = 0.169 * CLHEP::g / CLHEP::cm3;
271 T = 22.0 * CLHEP::kelvin;
279 log->
info(2,
"G4World: Liquid Deuterium material <",
LD2_MATERIAL,
"> created with density <", d,
">");
282 if (G4NistManager::Instance()->FindMaterial(
ND3_MATERIAL) ==
nullptr) {
284 a = 14.01 * CLHEP::g / CLHEP::mole;
285 d = 1.007 * CLHEP::g / CLHEP::cm3;
286 T = 1.0 * CLHEP::kelvin;
296 log->
info(2,
"G4World: Ammonia material <",
ND3_MATERIAL,
"> created with density <", d,
">");
301 if (G4NistManager::Instance()->FindOrBuildElement(
HELIUM3_ELEMENT) ==
nullptr) {
304 a = 3.0160293 * CLHEP::g / CLHEP::mole;
309 Helium3->AddIsotope(Helion, 1);
316 d = 0.1650 * CLHEP::mg / CLHEP::cm3;
317 T = 294.25 * CLHEP::kelvin;
330 if (G4NistManager::Instance()->FindOrBuildElement(
TRITIUM_ELEMENT) ==
nullptr) {
333 a = 3.0160492 * CLHEP::g / CLHEP::mole;
337 Tritium->AddIsotope(Triton, 1);
343 d = 0.0034 * CLHEP::g / CLHEP::cm3;
344 T = 40.0 * CLHEP::kelvin;
354void G4World::createG4SystemFactory(
const std::shared_ptr<GOptions>& gopts,
356 const std::string& backup_material,
357 int check_overlaps) {
366 for (
auto& [gsystemName,
gsystem] : *gsystemsMap) {
367 std::string factory =
gsystem->getFactoryName();
368 std::string g4Factory = g4FactoryNameFromSystemFactory(factory);
370 log->
info(2,
"G4World: creating factory <", g4Factory,
"> to for system <", gsystemName,
">");
374 if (factory == GSYSTEMASCIIFACTORYLABEL || factory == GSYSTEMSQLITETFACTORYLABEL ||
375 factory == GSYSTEMMYSQLTFACTORYLABEL) {
376 if (g4systemFactory.find(g4Factory) == g4systemFactory.end()) {
380 else if (factory == GSYSTEMCADTFACTORYLABEL) {
381 if (g4systemFactory.find(GSYSTEMCADTFACTORYLABEL) == g4systemFactory.end()) {
387 if (g4systemFactory.find(g4Factory) == g4systemFactory.end()) {
388 g4systemFactory[g4Factory] = manager.CreateObject<
G4ObjectsFactory>(g4Factory);
389 g4systemFactory[g4Factory]->initialize_context(check_overlaps, backup_material);
394void G4World::buildMaterials(
SystemMap* system_map) {
397 std::vector<GMaterial*> thisIterationRemainingMaterials;
398 unsigned long allRemainingMaterials = 0;
400 thisIterationRemainingMaterials.clear();
402 for (
const auto& [systemName, system] : *system_map) {
404 for (
const auto& [gmaterialName, gmaterialPtr] : system->getGMaterialMap()) {
405 if (createG4Material(gmaterialPtr) ==
false) {
406 thisIterationRemainingMaterials.push_back(gmaterialPtr.get());
412 if (allRemainingMaterials != 0 && !thisIterationRemainingMaterials.empty()) {
413 if (allRemainingMaterials >= thisIterationRemainingMaterials.size()) {
414 for (
auto& gmaterialLeft : thisIterationRemainingMaterials) {
log->
warning(gmaterialLeft->getName()); }
416 "Dependencies are not being resolved: their number should diminish. Above are the Outstanding gmaterials");
419 else { allRemainingMaterials = thisIterationRemainingMaterials.size(); }
421 while (!thisIterationRemainingMaterials.empty());
426 "> to build g4volume <", s->
getG4Name(),
">");
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.
G4World(const GWorld *gworld, const std::shared_ptr< GOptions > &gopts)
Construct and build the Geant4 world from a GEMC world.
void setFieldManagerForVolume(const std::string &volumeName, G4FieldManager *fm, bool forceToAllDaughters)
Attach a G4FieldManager to the logical volume of a named volume.
G4ObjectsFactory * get_factory(const std::string &factoryName)
Retrieve a registered factory by name.
const G4Volume * getG4Volume(const std::string &volumeName) const
Return the G4Volume wrapper for a volume name.
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 DEUTERIUM_ELEMENT
#define G4SYSTEMNATFACTORY
#define DEUTERIUMGAS_MATERIAL
#define HELIUM3GAS_MATERIAL
#define TRITIUMGAS_MATERIAL
#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