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