g4system
Loading...
Searching...
No Matches
g4materials.cc
Go to the documentation of this file.
1#include "g4world.h"
2
3// geant4
4#include "G4Material.hh"
5#include "G4Element.hh"
6#include "G4Isotope.hh"
8
9bool G4World::createG4Material(const std::shared_ptr<GMaterial> &gmaterial) {
10 auto NISTman = G4NistManager::Instance(); // material G4 Manager
11 auto materialName = gmaterial->getName();
12
13 // Only build the material if it is not already available in Geant4.
14 auto g4material = NISTman->FindMaterial(materialName);
15 if (g4material != nullptr) {
16 log->info(2, "Material <", materialName, "> already exists in G4NistManager");
17 return true;
18 }
19
20 auto components = gmaterial->getComponents();
21 auto amounts = gmaterial->getAmounts();
22 bool isChemical = gmaterial->isChemicalFormula();
23
24 // Scan material components:
25 // return false if any component does not exist yet (caller will retry later).
26 for (auto &componentName: components) {
27 if (isChemical) {
28 if (NISTman->FindOrBuildElement(componentName) == nullptr) {
29 log->info(2, "Element <", componentName, ">, needed by ", materialName, ", not found yet");
30 return false;
31 } else { log->info(2, "Element <", componentName, "> needed by ", materialName, " now found"); }
32 } else {
33 if (NISTman->FindOrBuildMaterial(componentName) == nullptr) {
34 log->info(2, "Material <", componentName, ">, needed by ", materialName, ", not found yet");
35 return false;
36 } else { log->info(2, "Material <", componentName, "> needed by ", materialName, " now found"); }
37 }
38 }
39
40 // Build the composed material from its components.
41 auto density = gmaterial->getDensity();
42 g4materialsMap[materialName] = new G4Material(materialName, density * CLHEP::g / CLHEP::cm3,
43 static_cast<G4int>(components.size()));
44
45 if (isChemical) {
46 log->info(2, "Building material <", materialName, "> with components:");
47 for (size_t i = 0; i < components.size(); i++) {
48 log->info(2, "element <", components[i], "> with amount: ", amounts[i]);
49 }
50
51 for (size_t i = 0; i < components.size(); i++) {
52 auto element = NISTman->FindOrBuildElement(components[i]);
53 g4materialsMap[materialName]->AddElement(element, static_cast<G4int>(amounts[i]));
54 }
55 } else {
56 log->info(2, "Building material <", materialName, "> with components:");
57 for (size_t i = 0; i < components.size(); i++) {
58 log->info(2, "material <", components[i], "> with fractional mass: ", amounts[i]);
59 }
60
61 for (size_t i = 0; i < components.size(); i++) {
62 auto material = NISTman->FindOrBuildMaterial(components[i]);
63 g4materialsMap[materialName]->AddMaterial(material, amounts[i]);
64 }
65 }
66
67 // optical properties
68 auto photonEnergy = gmaterial->getPhotonEnergy();
69 if (!photonEnergy.empty()) {
70 auto *materialPropertiesTable = new G4MaterialPropertiesTable();
71 bool hasOpticalProperties = false;
72
73 auto addProperty = [&](const char *propertyName, const std::vector<double> &values) {
74 if (values.empty()) { return; }
75 if (values.size() != photonEnergy.size()) {
76 log->error(ERR_GMATERIALOPTICALPROPERTYMISMATCH,
77 "material <", materialName, "> optical property <", propertyName, "> has ",
78 values.size(), " entries but photonEnergy has ", photonEnergy.size());
79 }
80 materialPropertiesTable->AddProperty(propertyName, photonEnergy, values);
81 hasOpticalProperties = true;
82 };
83
84 auto addConstantProperty = [&](const char *propertyName, double value, bool isSet) {
85 if (!isSet) { return; }
86 materialPropertiesTable->AddConstProperty(propertyName, value);
87 hasOpticalProperties = true;
88 };
89
90 // optical properties, these
91 addProperty("RINDEX", gmaterial->getIndexOfRefraction());
92 addProperty("ABSLENGTH", gmaterial->getAbsorptionLength());
93 addProperty("REFLECTIVITY", gmaterial->getReflectivity());
94 addProperty("EFFICIENCY", gmaterial->getEfficiency());
95 // Geant4 11.x renamed the scintillation property keys (formerly FASTCOMPONENT etc.)
96 addProperty("SCINTILLATIONCOMPONENT1", gmaterial->getFastComponent());
97 addProperty("SCINTILLATIONCOMPONENT2", gmaterial->getSlowComponent());
98
99 // scalar properties
100 addConstantProperty("SCINTILLATIONYIELD", gmaterial->getScintillationYield(),
101 gmaterial->hasScintillationYield());
102 addConstantProperty("RESOLUTIONSCALE", gmaterial->getResolutionScale(),
103 gmaterial->hasResolutionScale());
104
105 addConstantProperty("SCINTILLATIONTIMECONSTANT1", gmaterial->getFasttimeConstant() * CLHEP::ns,
106 gmaterial->hasFasttimeConstant());
107 addConstantProperty("SCINTILLATIONTIMECONSTANT2", gmaterial->getSlowtimeConstant() * CLHEP::ns,
108 gmaterial->hasSlowtimeConstant());
109 addConstantProperty("SCINTILLATIONYIELD1", gmaterial->getYieldratio(),
110 gmaterial->hasYieldratio());
111
112 double getBirksConstant = gmaterial->getBirksConstant();
113 if (gmaterial->hasBirksConstant()) {
114 g4materialsMap[materialName]->GetIonisation()->SetBirksConstant(getBirksConstant);
115 hasOpticalProperties = true;
116 }
117
118 // leaving RAYLEIGH last for consistency checks in
119 addProperty("RAYLEIGH", gmaterial->getRayleigh());
120
121 if (hasOpticalProperties) {
122 g4materialsMap[materialName]->SetMaterialPropertiesTable(materialPropertiesTable);
123 log->info(2, "Attached optical material properties table to material <", materialName, ">");
124 } else { delete materialPropertiesTable; }
125 }
126
127
128 return true;
129}
130
131void G4World::buildDefaultMaterialsElementsAndIsotopes() {
132 // Create a small set of commonly-used isotopes/elements/materials if they are missing.
133 // These are defined using Geant4 primitives and then registered in the local map for reference.
134 int Z, N;
135 double a, d, T;
136
137 // ---- Hydrogen
138
139 // Hydrogen gas material definition (Hydrogen element + state/gas parameters).
140 if (G4NistManager::Instance()->FindMaterial(HGAS_MATERIAL) == nullptr) {
141 Z = 1;
142 a = 1.01 * CLHEP::g / CLHEP::mole;
143 d = 0.00275 * CLHEP::g / CLHEP::cm3;
144 T = 50.0 * CLHEP::kelvin;
145 auto Hydrogen = new G4Element(HYDROGEN_ELEMENT, HYDROGEN_ELEMENT, Z, a);
146 g4materialsMap[HGAS_MATERIAL] = new G4Material(HGAS_MATERIAL,
147 d,
148 1,
149 kStateGas,
150 T);
151 g4materialsMap[HGAS_MATERIAL]->AddElement(Hydrogen, 1);
152 }
153 log->info(2, "G4World: Hydrogen gas material <", HGAS_MATERIAL, "> created with density <", d, ">");
154
155 // ---- Deuterium
156
157 // Deuteron isotope and Deuterium element definition.
158 if (G4NistManager::Instance()->FindOrBuildElement(DEUTERIUM_ELEMENT) == nullptr) {
159 Z = 1;
160 N = 2;
161 a = 2.0141018 * CLHEP::g / CLHEP::mole;
162 auto Deuteron = new G4Isotope(DEUTERON_ISOTOPE, Z, N, a);
163
164 // Deuterium element: isotope composition is explicitly set to the Deuteron isotope.
165 Deuterium = new G4Element(DEUTERIUM_ELEMENT, DEUTERIUM_ELEMENT, 1);
166 Deuterium->AddIsotope(Deuteron, 1);
167 }
168 log->info(2, "G4World: Deuterium element <", DEUTERIUM_ELEMENT, "> created with density <", d, ">");
169
170 // Deuterium gas material.
171 if (G4NistManager::Instance()->FindMaterial(DEUTERIUMGAS_MATERIAL) == nullptr) {
172 d = 0.000452 * CLHEP::g / CLHEP::cm3;
173 T = 294.25 * CLHEP::kelvin;
174 g4materialsMap[DEUTERIUMGAS_MATERIAL] = new G4Material(DEUTERIUMGAS_MATERIAL,
175 d,
176 1,
177 kStateGas,
178 T);
179 g4materialsMap[DEUTERIUMGAS_MATERIAL]->AddElement(Deuterium, 1);
180 }
181 log->info(2, "G4World: Deuterium gas material <", DEUTERIUMGAS_MATERIAL, "> created with density <", d, ">");
182
183 // Liquid Deuterium material.
184 if (G4NistManager::Instance()->FindMaterial(LD2_MATERIAL) == nullptr) {
185 d = 0.169 * CLHEP::g / CLHEP::cm3;
186 T = 22.0 * CLHEP::kelvin;
187 g4materialsMap[LD2_MATERIAL] = new G4Material(LD2_MATERIAL,
188 d,
189 1,
190 kStateLiquid,
191 T);
192 g4materialsMap[LD2_MATERIAL]->AddElement(Deuterium, 2);
193 }
194 log->info(2, "G4World: Liquid Deuterium material <", LD2_MATERIAL, "> created with density <", d, ">");
195
196 // Ammonia (ND3) material definition.
197 if (G4NistManager::Instance()->FindMaterial(ND3_MATERIAL) == nullptr) {
198 Z = 7;
199 a = 14.01 * CLHEP::g / CLHEP::mole;
200 d = 1.007 * CLHEP::g / CLHEP::cm3;
201 T = 1.0 * CLHEP::kelvin;
202 auto Nitrogen = new G4Element(NITRO_ELEMENT, NITRO_ELEMENT, Z, a);
203 g4materialsMap[ND3_MATERIAL] = new G4Material(ND3_MATERIAL,
204 d,
205 2,
206 kStateLiquid,
207 T);
208 g4materialsMap[ND3_MATERIAL]->AddElement(Nitrogen, 1);
209 g4materialsMap[ND3_MATERIAL]->AddElement(Deuterium, 3);
210 }
211 log->info(2, "G4World: Ammonia material <", ND3_MATERIAL, "> created with density <", d, ">");
212
213 // ---- Helium 3
214
215 // Helion isotope and Helium3 element definition.
216 if (G4NistManager::Instance()->FindOrBuildElement(HELIUM3_ELEMENT) == nullptr) {
217 Z = 2;
218 N = 3;
219 a = 3.0160293 * CLHEP::g / CLHEP::mole;
220 auto Helion = new G4Isotope(HELION_ISOTOPE, Z, N, a);
221
222 // Helium-3 element: isotope composition is explicitly set to the Helion isotope.
223 Helium3 = new G4Element(HELIUM3_ELEMENT, HELIUM3_ELEMENT, 1);
224 Helium3->AddIsotope(Helion, 1);
225 }
226 log->info(2, "G4World: Helium 3 element <", HELIUM3_ELEMENT, "> created with density <", d, ">");
227
228 // Helium-3 gas material definition.
229 if (G4NistManager::Instance()->FindMaterial(HELIUM3GAS_MATERIAL) == nullptr) {
230 // Density at 21.1°C (70°F): 0.1650 kg/m3.
231 d = 0.1650 * CLHEP::mg / CLHEP::cm3;
232 T = 294.25 * CLHEP::kelvin;
233 g4materialsMap[HELIUM3GAS_MATERIAL] = new G4Material(HELIUM3GAS_MATERIAL,
234 d,
235 1,
236 kStateGas,
237 T);
238 g4materialsMap[HELIUM3GAS_MATERIAL]->AddElement(Helium3, 1);
239 }
240 log->info(2, "G4World: Helium 3 gas material <", HELIUM3GAS_MATERIAL, "> created with density <", d, ">");
241
242 // ---- Tritium
243
244 // Triton isotope and Tritium element definition.
245 if (G4NistManager::Instance()->FindOrBuildElement(TRITIUM_ELEMENT) == nullptr) {
246 Z = 1;
247 N = 3;
248 a = 3.0160492 * CLHEP::g / CLHEP::mole;
249 auto Triton = new G4Isotope(TRITON_ISOTOPE, Z, N, a);
250
251 Tritium = new G4Element(TRITIUM_ELEMENT, TRITIUM_ELEMENT, 1);
252 Tritium->AddIsotope(Triton, 1);
253 }
254 log->info(2, "G4World: Tritium element <", TRITIUM_ELEMENT, "> created with density <", d, ">");
255
256 // Tritium gas material definition.
257 if (G4NistManager::Instance()->FindMaterial(TRITIUMGAS_MATERIAL) == nullptr) {
258 d = 0.0034 * CLHEP::g / CLHEP::cm3;
259 T = 40.0 * CLHEP::kelvin;
260 g4materialsMap[TRITIUMGAS_MATERIAL] = new G4Material(TRITIUMGAS_MATERIAL,
261 d,
262 1,
263 kStateGas, T);
264 g4materialsMap[TRITIUMGAS_MATERIAL]->AddElement(Tritium, 1);
265 }
266 log->info(2, "G4World: Tritium gas material <", TRITIUMGAS_MATERIAL, "> created with density <", d, ">");
267}
std::shared_ptr< GLogger > log
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
#define HELION_ISOTOPE
#define DEUTERIUM_ELEMENT
#define LD2_MATERIAL
#define DEUTERIUMGAS_MATERIAL
#define NITRO_ELEMENT
#define TRITON_ISOTOPE
#define TRITIUM_ELEMENT
#define HGAS_MATERIAL
#define HYDROGEN_ELEMENT
#define ND3_MATERIAL
#define HELIUM3GAS_MATERIAL
#define HELIUM3_ELEMENT
#define DEUTERON_ISOTOPE
#define TRITIUMGAS_MATERIAL
High-level builder that turns a GEMC world description into Geant4 geometry.