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 <%1> already exists in G4NistManager", materialName);
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 <%1>, needed by %2, not found yet", componentName, materialName);
30 return false;
31 } else { log->info(2, "Element <%1> needed by %2 now found", componentName, materialName); }
32 } else {
33 if (NISTman->FindOrBuildMaterial(componentName) == nullptr) {
34 log->info(2, "Material <%1>, needed by %2, not found yet", componentName, materialName);
35 return false;
36 } else { log->info(2, "Material <%1> needed by %2 now found", componentName, materialName); }
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 <%1> with components:", materialName);
47 for (size_t i = 0; i < components.size(); i++) {
48 log->info(2, "element <%1> with amount: %2", components[i], 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 <%1> with components:", materialName);
57 for (size_t i = 0; i < components.size(); i++) {
58 log->info(2, "material <%1> with fractional mass: %2", components[i], 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(
78 "material <%1> optical property <%2> has %3 entries but photonEnergy has %4", materialName,
79 propertyName, values.size(), photonEnergy.size());
80 }
81 materialPropertiesTable->AddProperty(propertyName, photonEnergy, values);
82 hasOpticalProperties = true;
83 };
84
85 auto addConstantProperty = [&](const char *propertyName, double value, bool isSet) {
86 if (!isSet) { return; }
87 materialPropertiesTable->AddConstProperty(propertyName, value);
88 hasOpticalProperties = true;
89 };
90
91 // optical properties, these
92 addProperty("RINDEX", gmaterial->getIndexOfRefraction());
93 addProperty("ABSLENGTH", gmaterial->getAbsorptionLength());
94 addProperty("REFLECTIVITY", gmaterial->getReflectivity());
95 addProperty("EFFICIENCY", gmaterial->getEfficiency());
96 // Geant4 11.x renamed the scintillation property keys (formerly FASTCOMPONENT etc.)
97 addProperty("SCINTILLATIONCOMPONENT1", gmaterial->getFastComponent());
98 addProperty("SCINTILLATIONCOMPONENT2", gmaterial->getSlowComponent());
99
100 // scalar properties
101 addConstantProperty("SCINTILLATIONYIELD", gmaterial->getScintillationYield(),
102 gmaterial->hasScintillationYield());
103 addConstantProperty("RESOLUTIONSCALE", gmaterial->getResolutionScale(),
104 gmaterial->hasResolutionScale());
105
106 addConstantProperty("SCINTILLATIONTIMECONSTANT1", gmaterial->getFasttimeConstant() * CLHEP::ns,
107 gmaterial->hasFasttimeConstant());
108 addConstantProperty("SCINTILLATIONTIMECONSTANT2", gmaterial->getSlowtimeConstant() * CLHEP::ns,
109 gmaterial->hasSlowtimeConstant());
110 addConstantProperty("SCINTILLATIONYIELD1", gmaterial->getYieldratio(),
111 gmaterial->hasYieldratio());
112
113 double getBirksConstant = gmaterial->getBirksConstant();
114 if (gmaterial->hasBirksConstant()) {
115 g4materialsMap[materialName]->GetIonisation()->SetBirksConstant(getBirksConstant);
116 hasOpticalProperties = true;
117 }
118
119 // leaving RAYLEIGH last for consistency checks in
120 addProperty("RAYLEIGH", gmaterial->getRayleigh());
121 addProperty("MIEHG", gmaterial->getMie());
122 if (gmaterial->hasMieForward()) {
123 materialPropertiesTable->AddConstProperty("MIEHG_FORWARD", gmaterial->getMieForward());
124 }
125 if (gmaterial->hasMieBackward()) {
126 materialPropertiesTable->AddConstProperty("MIEHG_BACKWARD", gmaterial->getMieBackward());
127 }
128 if (gmaterial->hasMieRatio()) {
129 materialPropertiesTable->AddConstProperty("MIEHG_FORWARD_RATIO", gmaterial->getMieRatio());
130 }
131
132 if (hasOpticalProperties) {
133 g4materialsMap[materialName]->SetMaterialPropertiesTable(materialPropertiesTable);
134 log->info(2, "Attached optical material properties table to material <%1>", materialName);
135 } else { delete materialPropertiesTable; }
136 }
137
138
139 return true;
140}
141
142void G4World::buildDefaultMaterialsElementsAndIsotopes() {
143 // Create a small set of commonly-used isotopes/elements/materials if they are missing.
144 // These are defined using Geant4 primitives and then registered in the local map for reference.
145 int Z, N;
146 double a, d, T;
147
148 // ---- Hydrogen
149
150 // Hydrogen gas material definition (Hydrogen element + state/gas parameters).
151 if (G4NistManager::Instance()->FindMaterial(g4system::HGAS_MATERIAL) == nullptr) {
152 Z = 1;
153 a = 1.01 * CLHEP::g / CLHEP::mole;
154 d = 0.00275 * CLHEP::g / CLHEP::cm3;
155 T = 50.0 * CLHEP::kelvin;
156 auto Hydrogen = new G4Element(g4system::HYDROGEN_ELEMENT, g4system::HYDROGEN_ELEMENT, Z, a);
157 g4materialsMap[g4system::HGAS_MATERIAL] = new G4Material(g4system::HGAS_MATERIAL,
158 d,
159 1,
160 kStateGas,
161 T);
162 g4materialsMap[g4system::HGAS_MATERIAL]->AddElement(Hydrogen, 1);
163 }
164 log->info(2, "G4World: Hydrogen gas material <%1> created with density <%2>", g4system::HGAS_MATERIAL, d);
165
166 // ---- Deuterium
167
168 // Deuteron isotope and Deuterium element definition.
169 if (G4NistManager::Instance()->FindOrBuildElement(g4system::DEUTERIUM_ELEMENT) == nullptr) {
170 Z = 1;
171 N = 2;
172 a = 2.0141018 * CLHEP::g / CLHEP::mole;
173 auto Deuteron = new G4Isotope(g4system::DEUTERON_ISOTOPE, Z, N, a);
174
175 // Deuterium element: isotope composition is explicitly set to the Deuteron isotope.
176 Deuterium = new G4Element(g4system::DEUTERIUM_ELEMENT, g4system::DEUTERIUM_ELEMENT, 1);
177 Deuterium->AddIsotope(Deuteron, 1);
178 }
179 log->info(2, "G4World: Deuterium element <%1> created with density <%2>", g4system::DEUTERIUM_ELEMENT, d);
180
181 // Deuterium gas material.
182 if (G4NistManager::Instance()->FindMaterial(g4system::DEUTERIUMGAS_MATERIAL) == nullptr) {
183 d = 0.000452 * CLHEP::g / CLHEP::cm3;
184 T = 294.25 * CLHEP::kelvin;
186 d,
187 1,
188 kStateGas,
189 T);
190 g4materialsMap[g4system::DEUTERIUMGAS_MATERIAL]->AddElement(Deuterium, 1);
191 }
192 log->info(
193 2, "G4World: Deuterium gas material <%1> created with density <%2>", g4system::DEUTERIUMGAS_MATERIAL,
194 d);
195
196 // Liquid Deuterium material.
197 if (G4NistManager::Instance()->FindMaterial(g4system::LD2_MATERIAL) == nullptr) {
198 d = 0.169 * CLHEP::g / CLHEP::cm3;
199 T = 22.0 * CLHEP::kelvin;
200 g4materialsMap[g4system::LD2_MATERIAL] = new G4Material(g4system::LD2_MATERIAL,
201 d,
202 1,
203 kStateLiquid,
204 T);
205 g4materialsMap[g4system::LD2_MATERIAL]->AddElement(Deuterium, 2);
206 }
207 log->info(
208 2, "G4World: Liquid Deuterium material <%1> created with density <%2>", g4system::LD2_MATERIAL, d);
209
210 // Ammonia (ND3) material definition.
211 if (G4NistManager::Instance()->FindMaterial(g4system::ND3_MATERIAL) == nullptr) {
212 Z = 7;
213 a = 14.01 * CLHEP::g / CLHEP::mole;
214 d = 1.007 * CLHEP::g / CLHEP::cm3;
215 T = 1.0 * CLHEP::kelvin;
216 auto Nitrogen = new G4Element(g4system::NITRO_ELEMENT, g4system::NITRO_ELEMENT, Z, a);
217 g4materialsMap[g4system::ND3_MATERIAL] = new G4Material(g4system::ND3_MATERIAL,
218 d,
219 2,
220 kStateLiquid,
221 T);
222 g4materialsMap[g4system::ND3_MATERIAL]->AddElement(Nitrogen, 1);
223 g4materialsMap[g4system::ND3_MATERIAL]->AddElement(Deuterium, 3);
224 }
225 log->info(2, "G4World: Ammonia material <%1> created with density <%2>", g4system::ND3_MATERIAL, d);
226
227 // ---- Helium 3
228
229 // Helion isotope and Helium3 element definition.
230 if (G4NistManager::Instance()->FindOrBuildElement(g4system::HELIUM3_ELEMENT) == nullptr) {
231 Z = 2;
232 N = 3;
233 a = 3.0160293 * CLHEP::g / CLHEP::mole;
234 auto Helion = new G4Isotope(g4system::HELION_ISOTOPE, Z, N, a);
235
236 // Helium-3 element: isotope composition is explicitly set to the Helion isotope.
237 Helium3 = new G4Element(g4system::HELIUM3_ELEMENT, g4system::HELIUM3_ELEMENT, 1);
238 Helium3->AddIsotope(Helion, 1);
239 }
240 log->info(2, "G4World: Helium 3 element <%1> created with density <%2>", g4system::HELIUM3_ELEMENT, d);
241
242 // Helium-3 gas material definition.
243 if (G4NistManager::Instance()->FindMaterial(g4system::HELIUM3GAS_MATERIAL) == nullptr) {
244 // Density at 21.1°C (70°F): 0.1650 kg/m3.
245 d = 0.1650 * CLHEP::mg / CLHEP::cm3;
246 T = 294.25 * CLHEP::kelvin;
247 g4materialsMap[g4system::HELIUM3GAS_MATERIAL] = new G4Material(g4system::HELIUM3GAS_MATERIAL,
248 d,
249 1,
250 kStateGas,
251 T);
252 g4materialsMap[g4system::HELIUM3GAS_MATERIAL]->AddElement(Helium3, 1);
253 }
254 log->info(
255 2, "G4World: Helium 3 gas material <%1> created with density <%2>", g4system::HELIUM3GAS_MATERIAL, d);
256
257 // ---- Tritium
258
259 // Triton isotope and Tritium element definition.
260 if (G4NistManager::Instance()->FindOrBuildElement(g4system::TRITIUM_ELEMENT) == nullptr) {
261 Z = 1;
262 N = 3;
263 a = 3.0160492 * CLHEP::g / CLHEP::mole;
264 auto Triton = new G4Isotope(g4system::TRITON_ISOTOPE, Z, N, a);
265
266 Tritium = new G4Element(g4system::TRITIUM_ELEMENT, g4system::TRITIUM_ELEMENT, 1);
267 Tritium->AddIsotope(Triton, 1);
268 }
269 log->info(2, "G4World: Tritium element <%1> created with density <%2>", g4system::TRITIUM_ELEMENT, d);
270
271 // Tritium gas material definition.
272 if (G4NistManager::Instance()->FindMaterial(g4system::TRITIUMGAS_MATERIAL) == nullptr) {
273 d = 0.0034 * CLHEP::g / CLHEP::cm3;
274 T = 40.0 * CLHEP::kelvin;
275 g4materialsMap[g4system::TRITIUMGAS_MATERIAL] = new G4Material(g4system::TRITIUMGAS_MATERIAL,
276 d,
277 1,
278 kStateGas, T);
279 g4materialsMap[g4system::TRITIUMGAS_MATERIAL]->AddElement(Tritium, 1);
280 }
281 log->info(
282 2, "G4World: Tritium gas material <%1> created with density <%2>", g4system::TRITIUMGAS_MATERIAL, d);
283
284 // ---- Optical Air
285
286 // Air with a refractive index, used by optical volumes (GEMC2's built-in "Air_Opt").
287 // Without RINDEX Geant4 kills optical photons at the material boundary.
288 if (G4NistManager::Instance()->FindMaterial(g4system::AIROPTICAL_MATERIAL) == nullptr) {
289 auto NISTman = G4NistManager::Instance();
290 d = 1.29 * CLHEP::mg / CLHEP::cm3;
291 g4materialsMap[g4system::AIROPTICAL_MATERIAL] = new G4Material(g4system::AIROPTICAL_MATERIAL, d, 2);
292 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->AddMaterial(NISTman->FindOrBuildMaterial("G4_N"),
293 70 * CLHEP::perCent);
294 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->AddMaterial(NISTman->FindOrBuildMaterial("G4_O"),
295 30 * CLHEP::perCent);
296
297 std::vector<G4double> photonEnergy = {2.034 * CLHEP::eV, 4.136 * CLHEP::eV};
298 std::vector<G4double> refractiveIndex = {1.00, 1.00};
299 auto airOpticalMPT = new G4MaterialPropertiesTable();
300 airOpticalMPT->AddProperty("RINDEX", photonEnergy, refractiveIndex);
301 g4materialsMap[g4system::AIROPTICAL_MATERIAL]->SetMaterialPropertiesTable(airOpticalMPT);
302 }
303 log->info(
304 2, "G4World: Optical air material <%1> created with density <%2>", g4system::AIROPTICAL_MATERIAL, d);
305
306 // ---- Kryptonite
307
308 // Material used to kill every track that touches it (GEMC2's built-in).
309 if (G4NistManager::Instance()->FindMaterial(g4system::KRYPTONITE_MATERIAL) == nullptr) {
310 d = 1.0e-8 * CLHEP::mg / CLHEP::cm3;
311 g4materialsMap[g4system::KRYPTONITE_MATERIAL] = new G4Material(g4system::KRYPTONITE_MATERIAL, d, 1);
312 g4materialsMap[g4system::KRYPTONITE_MATERIAL]->AddMaterial(
313 G4NistManager::Instance()->FindOrBuildMaterial("G4_Ar"), 100 * CLHEP::perCent);
314 }
315 log->info(
316 2, "G4World: Kryptonite material <%1> created with density <%2>", g4system::KRYPTONITE_MATERIAL, d);
317}
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