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()) {
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(g4system::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(g4system::HYDROGEN_ELEMENT, g4system::HYDROGEN_ELEMENT, Z, a);
146 g4materialsMap[g4system::HGAS_MATERIAL] = new G4Material(g4system::HGAS_MATERIAL,
147 d,
148 1,
149 kStateGas,
150 T);
151 g4materialsMap[g4system::HGAS_MATERIAL]->AddElement(Hydrogen, 1);
152 }
153 log->info(2, "G4World: Hydrogen gas material <", g4system::HGAS_MATERIAL, "> created with density <", d, ">");
154
155 // ---- Deuterium
156
157 // Deuteron isotope and Deuterium element definition.
158 if (G4NistManager::Instance()->FindOrBuildElement(g4system::DEUTERIUM_ELEMENT) == nullptr) {
159 Z = 1;
160 N = 2;
161 a = 2.0141018 * CLHEP::g / CLHEP::mole;
162 auto Deuteron = new G4Isotope(g4system::DEUTERON_ISOTOPE, Z, N, a);
163
164 // Deuterium element: isotope composition is explicitly set to the Deuteron isotope.
165 Deuterium = new G4Element(g4system::DEUTERIUM_ELEMENT, g4system::DEUTERIUM_ELEMENT, 1);
166 Deuterium->AddIsotope(Deuteron, 1);
167 }
168 log->info(2, "G4World: Deuterium element <", g4system::DEUTERIUM_ELEMENT, "> created with density <", d, ">");
169
170 // Deuterium gas material.
171 if (G4NistManager::Instance()->FindMaterial(g4system::DEUTERIUMGAS_MATERIAL) == nullptr) {
172 d = 0.000452 * CLHEP::g / CLHEP::cm3;
173 T = 294.25 * CLHEP::kelvin;
175 d,
176 1,
177 kStateGas,
178 T);
179 g4materialsMap[g4system::DEUTERIUMGAS_MATERIAL]->AddElement(Deuterium, 1);
180 }
181 log->info(2, "G4World: Deuterium gas material <", g4system::DEUTERIUMGAS_MATERIAL,
182 "> created with density <", d, ">");
183
184 // Liquid Deuterium material.
185 if (G4NistManager::Instance()->FindMaterial(g4system::LD2_MATERIAL) == nullptr) {
186 d = 0.169 * CLHEP::g / CLHEP::cm3;
187 T = 22.0 * CLHEP::kelvin;
188 g4materialsMap[g4system::LD2_MATERIAL] = new G4Material(g4system::LD2_MATERIAL,
189 d,
190 1,
191 kStateLiquid,
192 T);
193 g4materialsMap[g4system::LD2_MATERIAL]->AddElement(Deuterium, 2);
194 }
195 log->info(2, "G4World: Liquid Deuterium material <", g4system::LD2_MATERIAL, "> created with density <", d,
196 ">");
197
198 // Ammonia (ND3) material definition.
199 if (G4NistManager::Instance()->FindMaterial(g4system::ND3_MATERIAL) == nullptr) {
200 Z = 7;
201 a = 14.01 * CLHEP::g / CLHEP::mole;
202 d = 1.007 * CLHEP::g / CLHEP::cm3;
203 T = 1.0 * CLHEP::kelvin;
204 auto Nitrogen = new G4Element(g4system::NITRO_ELEMENT, g4system::NITRO_ELEMENT, Z, a);
205 g4materialsMap[g4system::ND3_MATERIAL] = new G4Material(g4system::ND3_MATERIAL,
206 d,
207 2,
208 kStateLiquid,
209 T);
210 g4materialsMap[g4system::ND3_MATERIAL]->AddElement(Nitrogen, 1);
211 g4materialsMap[g4system::ND3_MATERIAL]->AddElement(Deuterium, 3);
212 }
213 log->info(2, "G4World: Ammonia material <", g4system::ND3_MATERIAL, "> created with density <", d, ">");
214
215 // ---- Helium 3
216
217 // Helion isotope and Helium3 element definition.
218 if (G4NistManager::Instance()->FindOrBuildElement(g4system::HELIUM3_ELEMENT) == nullptr) {
219 Z = 2;
220 N = 3;
221 a = 3.0160293 * CLHEP::g / CLHEP::mole;
222 auto Helion = new G4Isotope(g4system::HELION_ISOTOPE, Z, N, a);
223
224 // Helium-3 element: isotope composition is explicitly set to the Helion isotope.
225 Helium3 = new G4Element(g4system::HELIUM3_ELEMENT, g4system::HELIUM3_ELEMENT, 1);
226 Helium3->AddIsotope(Helion, 1);
227 }
228 log->info(2, "G4World: Helium 3 element <", g4system::HELIUM3_ELEMENT, "> created with density <", d, ">");
229
230 // Helium-3 gas material definition.
231 if (G4NistManager::Instance()->FindMaterial(g4system::HELIUM3GAS_MATERIAL) == nullptr) {
232 // Density at 21.1°C (70°F): 0.1650 kg/m3.
233 d = 0.1650 * CLHEP::mg / CLHEP::cm3;
234 T = 294.25 * CLHEP::kelvin;
235 g4materialsMap[g4system::HELIUM3GAS_MATERIAL] = new G4Material(g4system::HELIUM3GAS_MATERIAL,
236 d,
237 1,
238 kStateGas,
239 T);
240 g4materialsMap[g4system::HELIUM3GAS_MATERIAL]->AddElement(Helium3, 1);
241 }
242 log->info(2, "G4World: Helium 3 gas material <", g4system::HELIUM3GAS_MATERIAL, "> created with density <",
243 d, ">");
244
245 // ---- Tritium
246
247 // Triton isotope and Tritium element definition.
248 if (G4NistManager::Instance()->FindOrBuildElement(g4system::TRITIUM_ELEMENT) == nullptr) {
249 Z = 1;
250 N = 3;
251 a = 3.0160492 * CLHEP::g / CLHEP::mole;
252 auto Triton = new G4Isotope(g4system::TRITON_ISOTOPE, Z, N, a);
253
254 Tritium = new G4Element(g4system::TRITIUM_ELEMENT, g4system::TRITIUM_ELEMENT, 1);
255 Tritium->AddIsotope(Triton, 1);
256 }
257 log->info(2, "G4World: Tritium element <", g4system::TRITIUM_ELEMENT, "> created with density <", d, ">");
258
259 // Tritium gas material definition.
260 if (G4NistManager::Instance()->FindMaterial(g4system::TRITIUMGAS_MATERIAL) == nullptr) {
261 d = 0.0034 * CLHEP::g / CLHEP::cm3;
262 T = 40.0 * CLHEP::kelvin;
263 g4materialsMap[g4system::TRITIUMGAS_MATERIAL] = new G4Material(g4system::TRITIUMGAS_MATERIAL,
264 d,
265 1,
266 kStateGas, T);
267 g4materialsMap[g4system::TRITIUMGAS_MATERIAL]->AddElement(Tritium, 1);
268 }
269 log->info(2, "G4World: Tritium gas material <", g4system::TRITIUMGAS_MATERIAL, "> created with density <",
270 d, ">");
271
272 // ---- Optical Air
273
274 // Air with a refractive index, used by optical volumes (GEMC2's built-in "Air_Opt").
275 // Without RINDEX Geant4 kills optical photons at the material boundary.
276 if (G4NistManager::Instance()->FindMaterial(g4system::AIROPTICAL_MATERIAL) == nullptr) {
277 auto NISTman = G4NistManager::Instance();
278 d = 1.29 * CLHEP::mg / CLHEP::cm3;
279 g4materialsMap[g4system::AIROPTICAL_MATERIAL] = new G4Material(g4system::AIROPTICAL_MATERIAL, d, 2);
280 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->AddMaterial(NISTman->FindOrBuildMaterial("G4_N"),
281 70 * CLHEP::perCent);
282 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->AddMaterial(NISTman->FindOrBuildMaterial("G4_O"),
283 30 * CLHEP::perCent);
284
285 std::vector<G4double> photonEnergy = {2.034 * CLHEP::eV, 4.136 * CLHEP::eV};
286 std::vector<G4double> refractiveIndex = {1.00, 1.00};
287 auto airOpticalMPT = new G4MaterialPropertiesTable();
288 airOpticalMPT->AddProperty("RINDEX", photonEnergy, refractiveIndex);
289 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->SetMaterialPropertiesTable(airOpticalMPT);
290 }
291 log->info(2, "G4World: Optical air material <", g4system::AIROPTICAL_MATERIAL, "> created with density <",
292 d, ">");
293
294 // ---- Kryptonite
295
296 // Material used to kill every track that touches it (GEMC2's built-in).
297 if (G4NistManager::Instance()->FindMaterial(g4system::KRYPTONITE_MATERIAL) == nullptr) {
298 d = 1.0e-8 * CLHEP::mg / CLHEP::cm3;
299 g4materialsMap[g4system::KRYPTONITE_MATERIAL] = new G4Material(g4system::KRYPTONITE_MATERIAL, d, 1);
300 g4materialsMap[g4system::KRYPTONITE_MATERIAL]->AddMaterial(
301 G4NistManager::Instance()->FindOrBuildMaterial("G4_Ar"), 100 * CLHEP::perCent);
302 }
303 log->info(2, "G4World: Kryptonite material <", g4system::KRYPTONITE_MATERIAL, "> created with density <", d,
304 ">");
305}
std::shared_ptr< GLogger > log
High-level builder that turns a GEMC world description into Geant4 geometry.
constexpr char LD2_MATERIAL[]
constexpr char TRITON_ISOTOPE[]
constexpr char HELIUM3_ELEMENT[]
constexpr char ND3_MATERIAL[]
constexpr char HGAS_MATERIAL[]
constexpr char DEUTERIUM_ELEMENT[]
constexpr char DEUTERON_ISOTOPE[]
constexpr char AIROPTICAL_MATERIAL[]
constexpr char TRITIUM_ELEMENT[]
constexpr char NITRO_ELEMENT[]
constexpr char TRITIUMGAS_MATERIAL[]
constexpr char KRYPTONITE_MATERIAL[]
constexpr char HELIUM3GAS_MATERIAL[]
constexpr char DEUTERIUMGAS_MATERIAL[]
constexpr char HYDROGEN_ELEMENT[]
constexpr char HELION_ISOTOPE[]
constexpr int ERR_GMATERIALOPTICALPROPERTYMISMATCH