Loading...
Searching...
No Matches
OpNoviceDetectorConstruction.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26/// \file OpNovice/src/OpNoviceDetectorConstruction.cc
27/// \brief Implementation of the OpNoviceDetectorConstruction class
28//
29//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
30
33
34#include "G4Box.hh"
35#include "G4Element.hh"
36#include "G4GDMLParser.hh"
37#include "G4LogicalBorderSurface.hh"
38#include "G4LogicalSkinSurface.hh"
39#include "G4LogicalVolume.hh"
40#include "G4Material.hh"
41#include "G4OpticalSurface.hh"
42#include "G4PVPlacement.hh"
43#include "G4SystemOfUnits.hh"
44#include "G4ThreeVector.hh"
45
46//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
53
54//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
59
60//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
62{
63 G4bool checkOverlaps = true;
64 // ------------- Materials -------------
65 G4double a, z, density;
66 G4int nelements;
67
68 // Air
69 auto N = new G4Element("Nitrogen", "N", z = 7, a = 14.01 * g / mole);
70 auto O = new G4Element("Oxygen", "O", z = 8, a = 16.00 * g / mole);
71 auto air = new G4Material("Air", density = 1.29 * mg / cm3, nelements = 2);
72 air->AddElement(N, 70. * perCent);
73 air->AddElement(O, 30. * perCent);
74 //
75 // Water
76 auto H = new G4Element("Hydrogen", "H", z = 1, a = 1.01 * g / mole);
77 auto water = new G4Material("Water", density = 1.0 * g / cm3, nelements = 2);
78 water->AddElement(H, 2);
79 water->AddElement(O, 1);
80
81 // ------------ Generate & Add Material Properties Table ------------
82 //
83 std::vector<G4double> photonEnergy = {
84 2.034 * eV, 2.068 * eV, 2.103 * eV, 2.139 * eV, 2.177 * eV, 2.216 * eV,
85 2.256 * eV, 2.298 * eV, 2.341 * eV, 2.386 * eV, 2.433 * eV, 2.481 * eV,
86 2.532 * eV, 2.585 * eV, 2.640 * eV, 2.697 * eV, 2.757 * eV, 2.820 * eV,
87 2.885 * eV, 2.954 * eV, 3.026 * eV, 3.102 * eV, 3.181 * eV, 3.265 * eV,
88 3.353 * eV, 3.446 * eV, 3.545 * eV, 3.649 * eV, 3.760 * eV, 3.877 * eV,
89 4.002 * eV, 4.136 * eV
90 };
91
92 // Water
93 std::vector<G4double> refractiveIndex1 = {
94 1.3435, 1.344, 1.3445, 1.345, 1.3455, 1.346, 1.3465, 1.347,
95 1.3475, 1.348, 1.3485, 1.3492, 1.35, 1.3505, 1.351, 1.3518,
96 1.3522, 1.3530, 1.3535, 1.354, 1.3545, 1.355, 1.3555, 1.356,
97 1.3568, 1.3572, 1.358, 1.3585, 1.359, 1.3595, 1.36, 1.3608
98 };
99 std::vector<G4double> absorption = {
100 3.448 * m, 4.082 * m, 6.329 * m, 9.174 * m, 12.346 * m, 13.889 * m,
101 15.152 * m, 17.241 * m, 18.868 * m, 20.000 * m, 26.316 * m, 35.714 * m,
102 45.455 * m, 47.619 * m, 52.632 * m, 52.632 * m, 55.556 * m, 52.632 * m,
103 52.632 * m, 47.619 * m, 45.455 * m, 41.667 * m, 37.037 * m, 33.333 * m,
104 30.000 * m, 28.500 * m, 27.000 * m, 24.500 * m, 22.000 * m, 19.500 * m,
105 17.500 * m, 14.500 * m
106 };
107
108 // Material properties can be added as arrays. However, in this case it is
109 // up to the user to make sure both arrays have the same number of elements.
110 G4double scintilFastArray[]{ 1.0, 1.0 };
111 G4double energyArray[]{ 2.034 * eV, 4.136 * eV };
112 G4int lenArray = 2;
113
114 std::vector<G4double> scintilSlow = {
115 0.01, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 8.00,
116 7.00, 6.00, 4.00, 3.00, 2.00, 1.00, 0.01, 1.00, 2.00, 3.00, 4.00,
117 5.00, 6.00, 7.00, 8.00, 9.00, 8.00, 7.00, 6.00, 5.00, 4.00
118 };
119
120 auto myMPT1 = new G4MaterialPropertiesTable();
121
122 // Values can be added to the material property table individually.
123 // With this method, spline interpolation cannot be set. Arguments
124 // createNewKey and spline both take their default values of false.
125 // Need to specify the number of entries (1) in the arrays, as an argument
126 // to AddProperty.
127 G4int numEntries = 1;
128 myMPT1->AddProperty("RINDEX", &photonEnergy[0], &refractiveIndex1[0],
129 numEntries);
130
131 for(size_t i = 1; i < photonEnergy.size(); ++i)
132 {
133 myMPT1->AddEntry("RINDEX", photonEnergy[i], refractiveIndex1[i]);
134 }
135
136 // Check that group velocity is calculated from RINDEX
137 if(myMPT1->GetProperty("RINDEX")->GetVectorLength() !=
138 myMPT1->GetProperty("GROUPVEL")->GetVectorLength())
139 {
140 G4ExceptionDescription ed;
141 ed << "Error calculating group velocities. Incorrect number of entries "
142 "in group velocity material property vector.";
143 G4Exception("OpNovice::OpNoviceDetectorConstruction", "OpNovice001",
144 FatalException, ed);
145 }
146
147 // Adding a property from two std::vectors. Argument createNewKey is false
148 // and spline is true.
149 myMPT1->AddProperty("ABSLENGTH", photonEnergy, absorption, false, true);
150
151 // Adding a property using a C-style array.
152 // Spline interpolation isn't used for scintillation.
153 // Arguments spline and createNewKey both take default value false.
154 myMPT1->AddProperty("SCINTILLATIONCOMPONENT1", energyArray, scintilFastArray,
155 lenArray);
156
157 myMPT1->AddProperty("SCINTILLATIONCOMPONENT2", photonEnergy, scintilSlow,
158 false, true);
159 myMPT1->AddConstProperty("SCINTILLATIONYIELD", 50. / MeV);
160 myMPT1->AddConstProperty("RESOLUTIONSCALE", 1.0);
161 myMPT1->AddConstProperty("SCINTILLATIONTIMECONSTANT1", 1. * ns);
162 myMPT1->AddConstProperty("SCINTILLATIONTIMECONSTANT2", 10. * ns);
163 myMPT1->AddConstProperty("SCINTILLATIONYIELD1", 0.8);
164 myMPT1->AddConstProperty("SCINTILLATIONYIELD2", 0.2);
165 std::vector<G4double> energy_water = {
166 1.56962 * eV, 1.58974 * eV, 1.61039 * eV, 1.63157 * eV, 1.65333 * eV,
167 1.67567 * eV, 1.69863 * eV, 1.72222 * eV, 1.74647 * eV, 1.77142 * eV,
168 1.7971 * eV, 1.82352 * eV, 1.85074 * eV, 1.87878 * eV, 1.90769 * eV,
169 1.93749 * eV, 1.96825 * eV, 1.99999 * eV, 2.03278 * eV, 2.06666 * eV,
170 2.10169 * eV, 2.13793 * eV, 2.17543 * eV, 2.21428 * eV, 2.25454 * eV,
171 2.29629 * eV, 2.33962 * eV, 2.38461 * eV, 2.43137 * eV, 2.47999 * eV,
172 2.53061 * eV, 2.58333 * eV, 2.63829 * eV, 2.69565 * eV, 2.75555 * eV,
173 2.81817 * eV, 2.88371 * eV, 2.95237 * eV, 3.02438 * eV, 3.09999 * eV,
174 3.17948 * eV, 3.26315 * eV, 3.35134 * eV, 3.44444 * eV, 3.54285 * eV,
175 3.64705 * eV, 3.75757 * eV, 3.87499 * eV, 3.99999 * eV, 4.13332 * eV,
176 4.27585 * eV, 4.42856 * eV, 4.59258 * eV, 4.76922 * eV, 4.95999 * eV,
177 5.16665 * eV, 5.39129 * eV, 5.63635 * eV, 5.90475 * eV, 6.19998 * eV
178 };
179
180 // Rayleigh scattering length is calculated by G4OpRayleigh
181
182 // Mie: assume 100 times larger than the rayleigh scattering
183 std::vector<G4double> mie_water = {
184 167024.4 * m, 158726.7 * m, 150742 * m, 143062.5 * m, 135680.2 * m,
185 128587.4 * m, 121776.3 * m, 115239.5 * m, 108969.5 * m, 102958.8 * m,
186 97200.35 * m, 91686.86 * m, 86411.33 * m, 81366.79 * m, 76546.42 * m,
187 71943.46 * m, 67551.29 * m, 63363.36 * m, 59373.25 * m, 55574.61 * m,
188 51961.24 * m, 48527.00 * m, 45265.87 * m, 42171.94 * m, 39239.39 * m,
189 36462.50 * m, 33835.68 * m, 31353.41 * m, 29010.30 * m, 26801.03 * m,
190 24720.42 * m, 22763.36 * m, 20924.88 * m, 19200.07 * m, 17584.16 * m,
191 16072.45 * m, 14660.38 * m, 13343.46 * m, 12117.33 * m, 10977.70 * m,
192 9920.416 * m, 8941.407 * m, 8036.711 * m, 7202.470 * m, 6434.927 * m,
193 5730.429 * m, 5085.425 * m, 4496.467 * m, 3960.210 * m, 3473.413 * m,
194 3032.937 * m, 2635.746 * m, 2278.907 * m, 1959.588 * m, 1675.064 * m,
195 1422.710 * m, 1200.004 * m, 1004.528 * m, 833.9666 * m, 686.1063 * m
196 };
197
198 // Mie: gforward, gbackward, forward backward ratio
199 G4double mie_water_const[3] = { 0.99, 0.99, 0.8 };
200
201 myMPT1->AddProperty("MIEHG", energy_water, mie_water, false, true);
202 myMPT1->AddConstProperty("MIEHG_FORWARD", mie_water_const[0]);
203 myMPT1->AddConstProperty("MIEHG_BACKWARD", mie_water_const[1]);
204 myMPT1->AddConstProperty("MIEHG_FORWARD_RATIO", mie_water_const[2]);
205
206 G4cout << "Water G4MaterialPropertiesTable:" << G4endl;
207 myMPT1->DumpTable();
208
209 water->SetMaterialPropertiesTable(myMPT1);
210
211 // Set the Birks Constant for the Water scintillator
212 water->GetIonisation()->SetBirksConstant(0.126 * mm / MeV);
213
214 // Air
215 std::vector<G4double> refractiveIndex2 = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
216 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
217 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
218 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
219 1.0, 1.0, 1.0, 1.0 };
220
221 auto myMPT2 = new G4MaterialPropertiesTable();
222 myMPT2->AddProperty("RINDEX", photonEnergy, refractiveIndex2);
223
224 G4cout << "Air G4MaterialPropertiesTable:" << G4endl;
225 myMPT2->DumpTable();
226
227 air->SetMaterialPropertiesTable(myMPT2);
228
229 // ------------- Volumes --------------
230 //
231 // The world
232 auto world_box = new G4Box("World", fWorld_x, fWorld_y, fWorld_z);
233 auto world_log = new G4LogicalVolume(world_box, air, "World");
234 G4VPhysicalVolume* world_phys = new G4PVPlacement(
235 nullptr, G4ThreeVector(), world_log, "world", nullptr, false, 0,
236 checkOverlaps);
237
238 // The experimental Hall
239 auto expHall_box = new G4Box("expHall", fExpHall_x, fExpHall_y, fExpHall_z);
240 auto expHall_log = new G4LogicalVolume(expHall_box, air, "expHall");
241 G4VPhysicalVolume* expHall_phys = new G4PVPlacement(
242 nullptr, G4ThreeVector(), expHall_log, "expHall", world_log, false, 0);
243
244 // The Water Tank
245 auto waterTank_box = new G4Box("Tank", fTank_x, fTank_y, fTank_z);
246 auto waterTank_log = new G4LogicalVolume(waterTank_box, water, "Tank");
247 G4VPhysicalVolume* waterTank_phys = new G4PVPlacement(
248 nullptr, G4ThreeVector(), waterTank_log, "Tank", expHall_log, false, 0);
249
250 // The Air Bubble
251 auto bubbleAir_box = new G4Box("Bubble", fBubble_x, fBubble_y, fBubble_z);
252 auto bubbleAir_log = new G4LogicalVolume(bubbleAir_box, air, "Bubble");
253 new G4PVPlacement(nullptr, G4ThreeVector(0, 2.5 * m, 0), bubbleAir_log,
254 "Bubble", waterTank_log, false, 0);
255
256 // ------------- Surfaces --------------
257
258 // Water Tank
259 auto opWaterSurface = new G4OpticalSurface("WaterSurface");
260 opWaterSurface->SetType(dielectric_LUTDAVIS);
261 opWaterSurface->SetFinish(Rough_LUT);
262 opWaterSurface->SetModel(DAVIS);
263
264 auto waterSurface = new G4LogicalBorderSurface(
265 "WaterSurface", waterTank_phys, expHall_phys, opWaterSurface);
266
267 auto opticalSurface = dynamic_cast<G4OpticalSurface*>(
268 waterSurface->GetSurface(waterTank_phys, expHall_phys)
269 ->GetSurfaceProperty());
270 if(opticalSurface)
271 opticalSurface->DumpInfo();
272
273 // Air Bubble
274 auto opAirSurface = new G4OpticalSurface("AirSurface");
275 opAirSurface->SetType(dielectric_dielectric);
276 opAirSurface->SetFinish(polished);
277 opAirSurface->SetModel(glisur);
278
279 auto airSurface =
280 new G4LogicalSkinSurface("AirSurface", bubbleAir_log, opAirSurface);
281
282 opticalSurface = dynamic_cast<G4OpticalSurface*>(
283 airSurface->GetSurface(bubbleAir_log)->GetSurfaceProperty());
284 if(opticalSurface)
285 opticalSurface->DumpInfo();
286
287 // Generate & Add Material Properties Table attached to the optical surfaces
288 //
289 std::vector<G4double> ephoton = { 2.034 * eV, 4.136 * eV };
290
291 // OpticalAirSurface
292 std::vector<G4double> reflectivity = { 0.3, 0.5 };
293 std::vector<G4double> efficiency = { 0.8, 1.0 };
294
295 auto myST2 = new G4MaterialPropertiesTable();
296
297 myST2->AddProperty("REFLECTIVITY", ephoton, reflectivity);
298 myST2->AddProperty("EFFICIENCY", ephoton, efficiency);
299 if(fVerbose)
300 {
301 G4cout << "Air Surface G4MaterialPropertiesTable:" << G4endl;
302 myST2->DumpTable();
303 }
304 opAirSurface->SetMaterialPropertiesTable(myST2);
305
306 if(fDumpGdml)
307 {
308 auto parser = new G4GDMLParser();
309 parser->Write(fDumpGdmlFileName, world_phys);
310 }
311
312 ////////////////////////////////////////////////////////////////////////////
313 // test user-defined properties
314 G4String ed;
315 if(myMPT1->GetProperty("USERDEFINED") != nullptr)
316 {
317 ed = "USERDEFINED != nullptr";
318 PrintError(ed);
319 }
320 myMPT1->AddProperty("USERDEFINED", energy_water, mie_water, true, true);
321 if(myMPT1->GetProperty("USERDEFINED") == nullptr)
322 {
323 ed = "USERDEFINED == nullptr";
324 PrintError(ed);
325 }
326 [[maybe_unused]] G4int index_userdefined = -1;
327 if(myMPT1->GetProperty("USERDEFINED") != nullptr)
328 {
329 index_userdefined = myMPT1->GetPropertyIndex("USERDEFINED");
330 }
331 if(!(index_userdefined >= 0 &&
332 index_userdefined <
333 (G4int) myMPT1->GetMaterialPropertyNames().size()))
334 {
335 ed = "USERDEFINED index out of range";
336 PrintError(ed);
337 }
338 myMPT1->RemoveProperty("USERDEFINED");
339 if(myMPT1->GetProperty("USERDEFINED") != nullptr)
340 {
341 ed = "USERDEFINED != nullptr at end";
342 PrintError(ed);
343 }
344
345 if(myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true)
346 {
347 ed = "ConstProperty USERDEFINEDCONST already exists.";
348 PrintError(ed);
349 }
350 myMPT1->AddConstProperty("USERDEFINEDCONST", 3.14, true);
351 if(myMPT1->ConstPropertyExists("USERDEFINEDCONST") == false)
352 {
353 ed = "ConstProperty USERDEFINEDCONST doesn't exist.";
354 PrintError(ed);
355 }
356 [[maybe_unused]] G4int index_pi = -1;
357 if(myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true)
358 {
359 index_pi = myMPT1->GetConstPropertyIndex("USERDEFINEDCONST");
360 }
361 if (!(index_pi >= 0 &&
362 index_pi < (G4int) myMPT1->GetMaterialConstPropertyNames().size()))
363 {
364 ed = "ConstProperty USERDEFINEDCONST index out of range.";
365 PrintError(ed);
366 }
367 myMPT1->RemoveConstProperty("USERDEFINEDCONST");
368 if (myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true)
369 {
370 ed = "ConstProperty USERDEFINEDCONST still exists.";
371 PrintError(ed);
372 }
373 // done testing user-defined properties
374 ////////////////////////////////////////////////////////////////////////////
375
376 return world_phys;
377}
378
379//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
381
382//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
384
385//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
387
388//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
390
391//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
396
397//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
402
403//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
405{
406 G4Exception("OpNoviceDetectorConstruction:MaterialProperty test", "op001",
407 FatalException, ed);
408}
std::vector< ExP01TrackerHit * > a
Definition of the OpNoviceDetectorConstruction class.
Definition of the OpNoviceDetectorMessenger class.
OpNoviceDetectorMessenger * fDetectorMessenger
G4VPhysicalVolume * Construct() override

Applications | User Support | Publications | Collaboration