Geant4 Cross Reference |
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 // 27 /// \file optical/LXe/src/LXeDetectorConstruction.cc 28 /// \brief Implementation of the LXeDetectorConstruction class 29 // 30 // 31 #include "LXeDetectorConstruction.hh" 32 33 #include "LXeDetectorMessenger.hh" 34 #include "LXeMainVolume.hh" 35 #include "LXePMTSD.hh" 36 #include "LXeScintSD.hh" 37 #include "LXeWLSSlab.hh" 38 39 #include "G4Box.hh" 40 #include "G4GeometryManager.hh" 41 #include "G4LogicalBorderSurface.hh" 42 #include "G4LogicalSkinSurface.hh" 43 #include "G4LogicalVolume.hh" 44 #include "G4LogicalVolumeStore.hh" 45 #include "G4Material.hh" 46 #include "G4MaterialTable.hh" 47 #include "G4OpticalSurface.hh" 48 #include "G4PVPlacement.hh" 49 #include "G4PhysicalConstants.hh" 50 #include "G4PhysicalVolumeStore.hh" 51 #include "G4RunManager.hh" 52 #include "G4SDManager.hh" 53 #include "G4SolidStore.hh" 54 #include "G4Sphere.hh" 55 #include "G4SystemOfUnits.hh" 56 #include "G4ThreeVector.hh" 57 #include "G4Tubs.hh" 58 #include "G4UImanager.hh" 59 #include "G4VisAttributes.hh" 60 #include "globals.hh" 61 62 G4bool LXeDetectorConstruction::fSphereOn = true; 63 64 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 65 66 LXeDetectorConstruction::LXeDetectorConstruction() 67 { 68 SetDefaults(); 69 DefineMaterials(); 70 fDetectorMessenger = new LXeDetectorMessenger(this); 71 } 72 73 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 74 75 LXeDetectorConstruction::~LXeDetectorConstruction() 76 { 77 delete fMainVolume; 78 delete fLXe_mt; 79 delete fDetectorMessenger; 80 delete fMPTPStyrene; 81 } 82 83 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 84 85 void LXeDetectorConstruction::DefineMaterials() 86 { 87 G4double a; // atomic mass 88 G4double z; // atomic number 89 G4double density; 90 91 G4int polyPMMA = 1; 92 G4int nC_PMMA = 3 + 2 * polyPMMA; 93 G4int nH_PMMA = 6 + 2 * polyPMMA; 94 95 G4int polyeth = 1; 96 G4int nC_eth = 2 * polyeth; 97 G4int nH_eth = 4 * polyeth; 98 99 //***Elements 100 fH = new G4Element("H", "H", z = 1., a = 1.01 * g / mole); 101 fC = new G4Element("C", "C", z = 6., a = 12.01 * g / mole); 102 fN = new G4Element("N", "N", z = 7., a = 14.01 * g / mole); 103 fO = new G4Element("O", "O", z = 8., a = 16.00 * g / mole); 104 105 //***Materials 106 // Liquid Xenon 107 fLXe = new G4Material("LXe", z = 54., a = 131.29 * g / mole, density = 3.020 * g / cm3); 108 // Aluminum 109 fAl = new G4Material("Al", z = 13., a = 26.98 * g / mole, density = 2.7 * g / cm3); 110 // Vacuum 111 fVacuum = new G4Material("Vacuum", z = 1., a = 1.01 * g / mole, density = universe_mean_density, 112 kStateGas, 0.1 * kelvin, 1.e-19 * pascal); 113 // Air 114 fAir = new G4Material("Air", density = 1.29 * mg / cm3, 2); 115 fAir->AddElement(fN, 70 * perCent); 116 fAir->AddElement(fO, 30 * perCent); 117 // Glass 118 fGlass = new G4Material("Glass", density = 1.032 * g / cm3, 2); 119 fGlass->AddElement(fC, 91.533 * perCent); 120 fGlass->AddElement(fH, 8.467 * perCent); 121 // Polystyrene 122 fPstyrene = new G4Material("Polystyrene", density = 1.03 * g / cm3, 2); 123 fPstyrene->AddElement(fC, 8); 124 fPstyrene->AddElement(fH, 8); 125 // Fiber(PMMA) 126 fPMMA = new G4Material("PMMA", density = 1190. * kg / m3, 3); 127 fPMMA->AddElement(fH, nH_PMMA); 128 fPMMA->AddElement(fC, nC_PMMA); 129 fPMMA->AddElement(fO, 2); 130 // Cladding(polyethylene) 131 fPethylene1 = new G4Material("Pethylene1", density = 1200. * kg / m3, 2); 132 fPethylene1->AddElement(fH, nH_eth); 133 fPethylene1->AddElement(fC, nC_eth); 134 // Double cladding(flourinated polyethylene) 135 fPethylene2 = new G4Material("Pethylene2", density = 1400. * kg / m3, 2); 136 fPethylene2->AddElement(fH, nH_eth); 137 fPethylene2->AddElement(fC, nC_eth); 138 139 //***Material properties tables 140 141 std::vector<G4double> lxe_Energy = {7.0 * eV, 7.07 * eV, 7.14 * eV}; 142 143 std::vector<G4double> lxe_SCINT = {0.1, 1.0, 0.1}; 144 std::vector<G4double> lxe_RIND = {1.59, 1.57, 1.54}; 145 std::vector<G4double> lxe_ABSL = {35. * cm, 35. * cm, 35. * cm}; 146 fLXe_mt = new G4MaterialPropertiesTable(); 147 fLXe_mt->AddProperty("SCINTILLATIONCOMPONENT1", lxe_Energy, lxe_SCINT); 148 fLXe_mt->AddProperty("SCINTILLATIONCOMPONENT2", lxe_Energy, lxe_SCINT); 149 fLXe_mt->AddProperty("RINDEX", lxe_Energy, lxe_RIND); 150 fLXe_mt->AddProperty("ABSLENGTH", lxe_Energy, lxe_ABSL); 151 fLXe_mt->AddConstProperty("SCINTILLATIONYIELD", 12000. / MeV); 152 fLXe_mt->AddConstProperty("RESOLUTIONSCALE", 1.0); 153 fLXe_mt->AddConstProperty("SCINTILLATIONTIMECONSTANT1", 20. * ns); 154 fLXe_mt->AddConstProperty("SCINTILLATIONTIMECONSTANT2", 45. * ns); 155 fLXe_mt->AddConstProperty("SCINTILLATIONYIELD1", 1.0); 156 fLXe_mt->AddConstProperty("SCINTILLATIONYIELD2", 0.0); 157 fLXe->SetMaterialPropertiesTable(fLXe_mt); 158 159 // Set the Birks Constant for the LXe scintillator 160 fLXe->GetIonisation()->SetBirksConstant(0.126 * mm / MeV); 161 162 std::vector<G4double> glass_AbsLength = {420. * cm, 420. * cm, 420. * cm}; 163 auto glass_mt = new G4MaterialPropertiesTable(); 164 glass_mt->AddProperty("ABSLENGTH", lxe_Energy, glass_AbsLength); 165 glass_mt->AddProperty("RINDEX", "Fused Silica"); 166 fGlass->SetMaterialPropertiesTable(glass_mt); 167 168 auto vacuum_mt = new G4MaterialPropertiesTable(); 169 vacuum_mt->AddProperty("RINDEX", "Air"); 170 fVacuum->SetMaterialPropertiesTable(vacuum_mt); 171 fAir->SetMaterialPropertiesTable(vacuum_mt); // Give air the same rindex 172 173 std::vector<G4double> wls_Energy = {2.00 * eV, 2.87 * eV, 2.90 * eV, 3.47 * eV}; 174 175 std::vector<G4double> rIndexPstyrene = {1.5, 1.5, 1.5, 1.5}; 176 std::vector<G4double> absorption1 = {2. * cm, 2. * cm, 2. * cm, 2. * cm}; 177 std::vector<G4double> scintilFast = {0.0, 0.0, 1.0, 1.0}; 178 fMPTPStyrene = new G4MaterialPropertiesTable(); 179 fMPTPStyrene->AddProperty("RINDEX", wls_Energy, rIndexPstyrene); 180 fMPTPStyrene->AddProperty("ABSLENGTH", wls_Energy, absorption1); 181 fMPTPStyrene->AddProperty("SCINTILLATIONCOMPONENT1", wls_Energy, scintilFast); 182 fMPTPStyrene->AddConstProperty("SCINTILLATIONYIELD", 10. / keV); 183 fMPTPStyrene->AddConstProperty("RESOLUTIONSCALE", 1.0); 184 fMPTPStyrene->AddConstProperty("SCINTILLATIONTIMECONSTANT1", 10. * ns); 185 fPstyrene->SetMaterialPropertiesTable(fMPTPStyrene); 186 187 // Set the Birks Constant for the Polystyrene scintillator 188 fPstyrene->GetIonisation()->SetBirksConstant(0.126 * mm / MeV); 189 190 std::vector<G4double> AbsFiber = {9.0 * m, 9.0 * m, 0.1 * mm, 0.1 * mm}; 191 std::vector<G4double> EmissionFib = {1.0, 1.0, 0.0, 0.0}; 192 auto fiberProperty = new G4MaterialPropertiesTable(); 193 fiberProperty->AddProperty("RINDEX", "PMMA"); 194 fiberProperty->AddProperty("WLSABSLENGTH", wls_Energy, AbsFiber); 195 fiberProperty->AddProperty("WLSCOMPONENT", wls_Energy, EmissionFib); 196 fiberProperty->AddConstProperty("WLSTIMECONSTANT", 0.5 * ns); 197 fPMMA->SetMaterialPropertiesTable(fiberProperty); 198 199 std::vector<G4double> RefractiveIndexClad1 = {1.49, 1.49, 1.49, 1.49}; 200 auto clad1Property = new G4MaterialPropertiesTable(); 201 clad1Property->AddProperty("RINDEX", wls_Energy, RefractiveIndexClad1); 202 clad1Property->AddProperty("ABSLENGTH", wls_Energy, AbsFiber); 203 fPethylene1->SetMaterialPropertiesTable(clad1Property); 204 205 std::vector<G4double> RefractiveIndexClad2 = {1.42, 1.42, 1.42, 1.42}; 206 auto clad2Property = new G4MaterialPropertiesTable(); 207 clad2Property->AddProperty("RINDEX", wls_Energy, RefractiveIndexClad2); 208 clad2Property->AddProperty("ABSLENGTH", wls_Energy, AbsFiber); 209 fPethylene2->SetMaterialPropertiesTable(clad2Property); 210 } 211 212 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 213 214 G4VPhysicalVolume* LXeDetectorConstruction::Construct() 215 { 216 // The experimental hall walls are all 1m away from housing walls 217 G4double expHall_x = fScint_x + fD_mtl + 1. * m; 218 G4double expHall_y = fScint_y + fD_mtl + 1. * m; 219 G4double expHall_z = fScint_z + fD_mtl + 1. * m; 220 221 // Create experimental hall 222 fExperimentalHall_box = new G4Box("expHall_box", expHall_x, expHall_y, expHall_z); 223 fExperimentalHall_log = new G4LogicalVolume(fExperimentalHall_box, fVacuum, "expHall_log"); 224 fExperimentalHall_phys = new G4PVPlacement(nullptr, G4ThreeVector(), fExperimentalHall_log, 225 "expHall", nullptr, false, 0); 226 227 fExperimentalHall_log->SetVisAttributes(G4VisAttributes::GetInvisible()); 228 229 // Place the main volume 230 if (fMainVolumeOn) { 231 fMainVolume = 232 new LXeMainVolume(nullptr, G4ThreeVector(), fExperimentalHall_log, false, 0, this); 233 } 234 235 // Place the WLS slab 236 if (fWLSslab) { 237 G4VPhysicalVolume* slab = 238 new LXeWLSSlab(nullptr, G4ThreeVector(0., 0., -fScint_z / 2. - fSlab_z - 1. * cm), 239 fExperimentalHall_log, false, 0, this); 240 241 // Surface properties for the WLS slab 242 auto scintWrap = new G4OpticalSurface("ScintWrap"); 243 244 new G4LogicalBorderSurface("ScintWrap", slab, fExperimentalHall_phys, scintWrap); 245 246 scintWrap->SetType(dielectric_metal); 247 scintWrap->SetFinish(polished); 248 scintWrap->SetModel(glisur); 249 250 std::vector<G4double> pp = {2.0 * eV, 3.5 * eV}; 251 std::vector<G4double> reflectivity = {1.0, 1.0}; 252 std::vector<G4double> efficiency = {0.0, 0.0}; 253 254 auto scintWrapProperty = new G4MaterialPropertiesTable(); 255 256 scintWrapProperty->AddProperty("REFLECTIVITY", pp, reflectivity); 257 scintWrapProperty->AddProperty("EFFICIENCY", pp, efficiency); 258 scintWrap->SetMaterialPropertiesTable(scintWrapProperty); 259 } 260 261 return fExperimentalHall_phys; 262 } 263 264 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 265 266 void LXeDetectorConstruction::ConstructSDandField() 267 { 268 if (!fMainVolume) return; 269 270 // PMT SD 271 272 LXePMTSD* pmt = fPmt_SD.Get(); 273 if (!pmt) { 274 // Created here so it exists as pmts are being placed 275 G4cout << "Construction /LXeDet/pmtSD" << G4endl; 276 auto pmt_SD = new LXePMTSD("/LXeDet/pmtSD"); 277 fPmt_SD.Put(pmt_SD); 278 279 pmt_SD->InitPMTs(); 280 pmt_SD->SetPmtPositions(fMainVolume->GetPmtPositions()); 281 } 282 else { 283 pmt->InitPMTs(); 284 pmt->SetPmtPositions(fMainVolume->GetPmtPositions()); 285 } 286 G4SDManager::GetSDMpointer()->AddNewDetector(fPmt_SD.Get()); 287 // sensitive detector is not actually on the photocathode. 288 // processHits gets done manually by the stepping action. 289 // It is used to detect when photons hit and get absorbed & detected at the 290 // boundary to the photocathode (which doesn't get done by attaching it to a 291 // logical volume. 292 // It does however need to be attached to something or else it doesn't get 293 // reset at the begining of events 294 295 SetSensitiveDetector(fMainVolume->GetLogPhotoCath(), fPmt_SD.Get()); 296 297 // Scint SD 298 299 if (!fScint_SD.Get()) { 300 G4cout << "Construction /LXeDet/scintSD" << G4endl; 301 auto scint_SD = new LXeScintSD("/LXeDet/scintSD"); 302 fScint_SD.Put(scint_SD); 303 } 304 G4SDManager::GetSDMpointer()->AddNewDetector(fScint_SD.Get()); 305 SetSensitiveDetector(fMainVolume->GetLogScint(), fScint_SD.Get()); 306 } 307 308 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 309 310 void LXeDetectorConstruction::SetDimensions(G4ThreeVector dims) 311 { 312 fScint_x = dims[0]; 313 fScint_y = dims[1]; 314 fScint_z = dims[2]; 315 G4RunManager::GetRunManager()->ReinitializeGeometry(); 316 } 317 318 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 319 320 void LXeDetectorConstruction::SetHousingThickness(G4double d_mtl) 321 { 322 fD_mtl = d_mtl; 323 G4RunManager::GetRunManager()->ReinitializeGeometry(); 324 } 325 326 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 327 328 void LXeDetectorConstruction::SetNX(G4int nx) 329 { 330 fNx = nx; 331 G4RunManager::GetRunManager()->ReinitializeGeometry(); 332 } 333 334 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 335 336 void LXeDetectorConstruction::SetNY(G4int ny) 337 { 338 fNy = ny; 339 G4RunManager::GetRunManager()->ReinitializeGeometry(); 340 } 341 342 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 343 344 void LXeDetectorConstruction::SetNZ(G4int nz) 345 { 346 fNz = nz; 347 G4RunManager::GetRunManager()->ReinitializeGeometry(); 348 } 349 350 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 351 352 void LXeDetectorConstruction::SetPMTRadius(G4double outerRadius_pmt) 353 { 354 fOuterRadius_pmt = outerRadius_pmt; 355 G4RunManager::GetRunManager()->ReinitializeGeometry(); 356 } 357 358 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 359 360 void LXeDetectorConstruction::SetDefaults() 361 { 362 // Resets to default values 363 fD_mtl = 0.0635 * cm; 364 365 fScint_x = 17.8 * cm; 366 fScint_y = 17.8 * cm; 367 fScint_z = 22.6 * cm; 368 369 fNx = 2; 370 fNy = 2; 371 fNz = 3; 372 373 fOuterRadius_pmt = 2.3 * cm; 374 375 fSphereOn = true; 376 fRefl = 1.0; 377 378 fNfibers = 15; 379 fWLSslab = false; 380 fMainVolumeOn = true; 381 fMainVolume = nullptr; 382 fSlab_z = 2.5 * mm; 383 384 G4UImanager::GetUIpointer()->ApplyCommand("/LXe/detector/scintYieldFactor 1."); 385 386 if (fLXe_mt) fLXe_mt->AddConstProperty("SCINTILLATIONYIELD", 12000. / MeV); 387 if (fMPTPStyrene) fMPTPStyrene->AddConstProperty("SCINTILLATIONYIELD", 10. / keV); 388 } 389 390 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 391 392 void LXeDetectorConstruction::SetSphereOn(G4bool b) 393 { 394 fSphereOn = b; 395 G4RunManager::GetRunManager()->ReinitializeGeometry(); 396 } 397 398 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 399 400 void LXeDetectorConstruction::SetHousingReflectivity(G4double r) 401 { 402 fRefl = r; 403 G4RunManager::GetRunManager()->ReinitializeGeometry(); 404 } 405 406 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 407 408 void LXeDetectorConstruction::SetWLSSlabOn(G4bool b) 409 { 410 fWLSslab = b; 411 G4RunManager::GetRunManager()->ReinitializeGeometry(); 412 } 413 414 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 415 416 void LXeDetectorConstruction::SetMainVolumeOn(G4bool b) 417 { 418 fMainVolumeOn = b; 419 G4RunManager::GetRunManager()->ReinitializeGeometry(); 420 } 421 422 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 423 424 void LXeDetectorConstruction::SetNFibers(G4int n) 425 { 426 fNfibers = n; 427 G4RunManager::GetRunManager()->ReinitializeGeometry(); 428 } 429 430 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 431 432 void LXeDetectorConstruction::SetMainScintYield(G4double y) 433 { 434 fLXe_mt->AddConstProperty("SCINTILLATIONYIELD", y / MeV); 435 } 436 437 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 438 439 void LXeDetectorConstruction::SetWLSScintYield(G4double y) 440 { 441 fMPTPStyrene->AddConstProperty("SCINTILLATIONYIELD", y / MeV); 442 } 443 444 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 445 446 void LXeDetectorConstruction::SetSaveThreshold(G4int save) 447 { 448 // Sets the save threshold for the random number seed. If the number of 449 // photons generated in an event is lower than this, then save the seed for 450 // this event in a file called run###evt###.rndm 451 452 fSaveThreshold = save; 453 G4RunManager::GetRunManager()->SetRandomNumberStore(true); 454 } 455 456 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 457