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/wls/src/WLSDetectorConstruction.cc 28 /// \brief Implementation of the WLSDetectorConstruction class 29 // 30 // 31 32 #include "WLSDetectorConstruction.hh" 33 34 #include "WLSDetectorMessenger.hh" 35 #include "WLSMaterials.hh" 36 #include "WLSPhotonDetSD.hh" 37 38 #include "G4Box.hh" 39 #include "G4Colour.hh" 40 #include "G4EllipticalTube.hh" 41 #include "G4GeometryManager.hh" 42 #include "G4LogicalBorderSurface.hh" 43 #include "G4LogicalSkinSurface.hh" 44 #include "G4LogicalVolume.hh" 45 #include "G4LogicalVolumeStore.hh" 46 #include "G4Material.hh" 47 #include "G4NistManager.hh" 48 #include "G4OpticalSurface.hh" 49 #include "G4PVPlacement.hh" 50 #include "G4PhysicalConstants.hh" 51 #include "G4PhysicalVolumeStore.hh" 52 #include "G4RunManager.hh" 53 #include "G4SDManager.hh" 54 #include "G4SolidStore.hh" 55 #include "G4SystemOfUnits.hh" 56 #include "G4Tubs.hh" 57 #include "G4UserLimits.hh" 58 #include "G4VisAttributes.hh" 59 #include "G4ios.hh" 60 #include "globals.hh" 61 62 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 63 64 WLSDetectorConstruction::WLSDetectorConstruction() : fVisAttributes() 65 { 66 fDetectorMessenger = new WLSDetectorMessenger(this); 67 68 fMPPCHalfL = fWLSfiberRY; 69 fClrfiberZ = fMPPCZ + 10. * nm; 70 fHoleLength = fBarLength; 71 } 72 73 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 74 75 WLSDetectorConstruction::~WLSDetectorConstruction() 76 { 77 delete fDetectorMessenger; 78 delete fMaterials; 79 for (auto visAttributes : fVisAttributes) { 80 delete visAttributes; 81 } 82 } 83 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 85 86 G4VPhysicalVolume* WLSDetectorConstruction::Construct() 87 { 88 if (fPhysiWorld) { 89 G4GeometryManager::GetInstance()->OpenGeometry(); 90 G4PhysicalVolumeStore::GetInstance()->Clean(); 91 G4LogicalVolumeStore::GetInstance()->Clean(); 92 G4SolidStore::GetInstance()->Clean(); 93 G4LogicalSkinSurface::CleanSurfaceTable(); 94 G4LogicalBorderSurface::CleanSurfaceTable(); 95 } 96 97 fMaterials = WLSMaterials::GetInstance(); 98 UpdateGeometryParameters(); 99 100 return ConstructDetector(); 101 } 102 103 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 104 105 G4VPhysicalVolume* WLSDetectorConstruction::ConstructDetector() 106 { 107 auto air = FindMaterial("G4_AIR"); 108 // G4cout << "\nMaterial Properties Table for G4_AIR:" << G4endl; 109 // air->GetMaterialPropertiesTable()->DumpTable(); 110 111 //-------------------------------------------------- 112 // World 113 //-------------------------------------------------- 114 115 G4VSolid* solidWorld = new G4Box("World", fWorldSizeX, fWorldSizeY, fWorldSizeZ); 116 117 fLogicWorld = new G4LogicalVolume(solidWorld, air, "World"); 118 119 fPhysiWorld = 120 new G4PVPlacement(nullptr, G4ThreeVector(), fLogicWorld, "World", nullptr, false, 0); 121 122 //-------------------------------------------------- 123 // Extrusion 124 //-------------------------------------------------- 125 126 auto coating = FindMaterial("Coating"); 127 128 G4VSolid* solidExtrusion = 129 new G4Box("Extrusion", GetBarBase() / 2., GetBarBase() / 2., GetBarLength() / 2.); 130 131 auto logicExtrusion = new G4LogicalVolume(solidExtrusion, coating, "Extrusion"); 132 133 auto TiO2Surface = 134 new G4OpticalSurface("TiO2Surface", glisur, ground, dielectric_metal, fExtrusionPolish); 135 136 auto TiO2SurfaceProperty = new G4MaterialPropertiesTable(); 137 138 std::vector<G4double> p_TiO2 = {2.00 * eV, 3.47 * eV}; 139 140 std::vector<G4double> refl_TiO2 = {fExtrusionReflectivity, fExtrusionReflectivity}; 141 std::vector<G4double> effi_TiO2 = {0., 0.}; 142 143 TiO2SurfaceProperty->AddProperty("REFLECTIVITY", p_TiO2, refl_TiO2); 144 TiO2SurfaceProperty->AddProperty("EFFICIENCY", p_TiO2, effi_TiO2); 145 146 TiO2Surface->SetMaterialPropertiesTable(TiO2SurfaceProperty); 147 148 new G4PVPlacement(nullptr, G4ThreeVector(), logicExtrusion, "Extrusion", fLogicWorld, false, 0); 149 150 new G4LogicalSkinSurface("TiO2Surface", logicExtrusion, TiO2Surface); 151 152 //-------------------------------------------------- 153 // Scintillator 154 //-------------------------------------------------- 155 156 auto polystyrene = FindMaterial("Polystyrene"); 157 // G4cout << "\nMaterial Properties Table for Polystyrene:" << G4endl; 158 // polystyrene->GetMaterialPropertiesTable()->DumpTable(); 159 160 G4VSolid* solidScintillator = 161 new G4Box("Scintillator", GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(), 162 GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(), GetBarLength() / 2.); 163 164 auto logicScintillator = new G4LogicalVolume(solidScintillator, polystyrene, "Scintillator"); 165 166 new G4PVPlacement(nullptr, G4ThreeVector(), logicScintillator, "Scintillator", logicExtrusion, 167 false, 0); 168 169 G4LogicalVolume* logicScintSide = nullptr; 170 G4LogicalVolume* logicScintCrnr = nullptr; 171 if (GetCoatingRadius() > 0.) { 172 G4VSolid* solidScintside = 173 new G4Box("SideOfBar", GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(), 174 GetCoatingRadius() / 2., GetBarLength() / 2.); 175 176 G4VSolid* solidScintcrnr = new G4Tubs("CrnrOfBar", 0.0 * cm, GetCoatingRadius(), 177 GetBarLength() / 2., 0. * deg, 90. * deg); 178 179 logicScintSide = new G4LogicalVolume(solidScintside, polystyrene, "SideOfBar"); 180 181 logicScintCrnr = new G4LogicalVolume(solidScintcrnr, polystyrene, "CrnrOfBar"); 182 183 G4double pos = GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius() / 2.; 184 185 new G4PVPlacement(nullptr, G4ThreeVector(0., -pos, 0.), logicScintSide, "SideOfBar", 186 logicExtrusion, false, 0); 187 188 new G4PVPlacement(nullptr, G4ThreeVector(0., pos, 0.), logicScintSide, "SideOfBar", 189 logicExtrusion, false, 1); 190 191 auto rot1 = new G4RotationMatrix(); 192 rot1->rotateZ(-90. * deg); 193 194 new G4PVPlacement(rot1, G4ThreeVector(pos, 0., 0.), logicScintSide, "SideOfBar", logicExtrusion, 195 false, 2); 196 197 new G4PVPlacement(rot1, G4ThreeVector(-pos, 0., 0.), logicScintSide, "SideOfBar", 198 logicExtrusion, false, 3); 199 200 pos = GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(); 201 202 new G4PVPlacement(nullptr, G4ThreeVector(pos, pos, 0.), logicScintCrnr, "CrnrOfBar", 203 logicExtrusion, false, 0); 204 205 new G4PVPlacement(rot1, G4ThreeVector(-pos, pos, 0.), logicScintCrnr, "CrnrOfBar", 206 logicExtrusion, false, 1); 207 208 auto rot2 = new G4RotationMatrix(); 209 rot2->rotateZ(-180. * deg); 210 211 new G4PVPlacement(rot2, G4ThreeVector(-pos, -pos, 0.), logicScintCrnr, "CrnrOfBar", 212 logicExtrusion, false, 2); 213 214 auto rot3 = new G4RotationMatrix(); 215 rot3->rotateZ(-270. * deg); 216 217 new G4PVPlacement(rot3, G4ThreeVector(pos, -pos, 0.), logicScintCrnr, "CrnrOfBar", 218 logicExtrusion, false, 3); 219 } 220 221 if (GetFiberRadius() < GetHoleRadius()) { 222 G4VSolid* solidHole = 223 new G4Tubs("Hole", 0., GetHoleRadius(), GetHoleLength() / 2., 0. * deg, 360. * deg); 224 225 fLogicHole = new G4LogicalVolume(solidHole, air, "Hole"); 226 227 fPhysiHole = 228 new G4PVPlacement(nullptr, G4ThreeVector(), fLogicHole, "Hole", logicScintillator, false, 0); 229 } 230 231 //-------------------------------------------------- 232 // Fiber 233 //-------------------------------------------------- 234 235 if (!(fLogicHole) || !(fPhysiHole)) { 236 G4ExceptionDescription ed; 237 ed << "The Fiber Hole has not been constructed"; 238 G4Exception("WLSDetectorConstruction", "wls001", FatalException, ed); 239 } 240 241 // Pointers to the most recently constructed volume 242 G4LogicalVolume* logicPlacement = fLogicHole; 243 G4VPhysicalVolume* physiPlacement = fPhysiHole; 244 245 //-------------------------------------------------- 246 // Fiber Construction 247 //-------------------------------------------------- 248 249 // Boundary Surface Properties 250 G4OpticalSurface* opSurface = nullptr; 251 252 if (fSurfaceRoughness < 1.) 253 opSurface = new G4OpticalSurface("RoughSurface", glisur, ground, dielectric_dielectric, 254 fSurfaceRoughness); 255 256 G4LogicalVolume* logicWLSfiber = nullptr; 257 G4LogicalVolume* logicClad1 = nullptr; 258 G4LogicalVolume* logicClad2 = nullptr; 259 G4VPhysicalVolume* physiClad1 = nullptr; 260 G4VPhysicalVolume* physiClad2 = nullptr; 261 262 auto fpethylene = FindMaterial("FPethylene"); 263 auto pethylene = FindMaterial("Pethylene"); 264 auto pmma = FindMaterial("PMMA"); 265 266 // Determine the number of cladding layers to be built 267 switch (fNumOfCladLayers) { 268 case 2: 269 270 //-------------------------------------------------- 271 // Cladding 2 272 //-------------------------------------------------- 273 274 // G4cout << "\nMaterial Properties Table for fPethylene:" << G4endl; 275 // fpethylene->GetMaterialPropertiesTable()->DumpTable(); 276 277 G4VSolid* solidClad2; 278 279 if (fXYRatio == 1.) 280 solidClad2 = new G4Tubs("Clad2", 0., fClad2RX, fClad2Z, 0., twopi); 281 else 282 solidClad2 = new G4EllipticalTube("Clad2", fClad2RX, fClad2RY, fClad2Z); 283 284 logicClad2 = new G4LogicalVolume(solidClad2, fpethylene, "Clad2"); 285 286 physiClad2 = new G4PVPlacement(nullptr, G4ThreeVector(0.0, 0.0, fWLSfiberOrigin), logicClad2, 287 "Clad2", logicPlacement, false, 0); 288 289 // Place the rough surface only if needed 290 if (opSurface) { 291 new G4LogicalBorderSurface("surfaceClad2Out", physiClad2, physiPlacement, opSurface); 292 new G4LogicalBorderSurface("surfaceClad2In", physiPlacement, physiClad2, opSurface); 293 } 294 295 logicPlacement = logicClad2; 296 physiPlacement = physiClad2; 297 [[fallthrough]]; 298 299 case 1: 300 301 //-------------------------------------------------- 302 // Cladding 1 303 //-------------------------------------------------- 304 305 // G4cout << "\nMaterial Properties Table for Pethylene:" << G4endl; 306 // pethylene->GetMaterialPropertiesTable()->DumpTable(); 307 308 G4VSolid* solidClad1; 309 310 if (fXYRatio == 1.) 311 solidClad1 = new G4Tubs("Clad1", 0., fClad1RX, fClad1Z, 0., twopi); 312 else 313 solidClad1 = new G4EllipticalTube("Clad1", fClad1RX, fClad1RY, fClad1Z); 314 315 logicClad1 = new G4LogicalVolume(solidClad1, pethylene, "Clad1"); 316 317 physiClad1 = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fWLSfiberOrigin), logicClad1, 318 "Clad1", logicPlacement, false, 0); 319 320 // Place the rough surface only if needed 321 if (opSurface) { 322 new G4LogicalBorderSurface("surfaceClad1Out", physiClad1, physiPlacement, opSurface); 323 324 new G4LogicalBorderSurface("surfaceClad1In", physiPlacement, physiClad1, opSurface); 325 } 326 327 logicPlacement = logicClad1; 328 physiPlacement = physiClad1; 329 [[fallthrough]]; 330 331 default: 332 333 //-------------------------------------------------- 334 // WLS Fiber 335 //-------------------------------------------------- 336 337 // G4cout << "\nMaterial Properties Table for PMMA:" << G4endl; 338 // pmma->GetMaterialPropertiesTable()->DumpTable(); 339 340 G4VSolid* solidWLSfiber; 341 342 if (fXYRatio == 1.) { 343 solidWLSfiber = new G4Tubs("WLSFiber", 0., fWLSfiberRX, fWLSfiberZ, 0., twopi); 344 } 345 else { 346 solidWLSfiber = new G4EllipticalTube("WLSFiber", fWLSfiberRX, fWLSfiberRY, fWLSfiberZ); 347 } 348 349 logicWLSfiber = new G4LogicalVolume(solidWLSfiber, pmma, "WLSFiber"); 350 351 logicWLSfiber->SetUserLimits(new G4UserLimits(DBL_MAX, DBL_MAX, 10. * ms)); 352 353 G4VPhysicalVolume* physiWLSfiber = 354 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fWLSfiberOrigin), logicWLSfiber, 355 "WLSFiber", logicPlacement, false, 0); 356 357 // Place the rough surface only if needed 358 if (opSurface) { 359 new G4LogicalBorderSurface("surfaceWLSOut", physiWLSfiber, physiPlacement, opSurface); 360 361 new G4LogicalBorderSurface("surfaceWLSIn", physiPlacement, physiWLSfiber, opSurface); 362 } 363 } 364 365 //-------------------------------------------------- 366 // Mirror for reflection at one of the end 367 //-------------------------------------------------- 368 369 // Place the mirror only if the user wants the mirror 370 G4LogicalVolume* logicMirror = nullptr; 371 372 auto aluminum = FindMaterial("G4_Al"); 373 374 if (fMirrorToggle) { 375 G4VSolid* solidMirror = new G4Box("Mirror", fMirrorRmax, fMirrorRmax, fMirrorZ); 376 377 logicMirror = new G4LogicalVolume(solidMirror, aluminum, "Mirror"); 378 379 auto mirrorSurface = 380 new G4OpticalSurface("MirrorSurface", glisur, ground, dielectric_metal, fMirrorPolish); 381 382 auto mirrorSurfaceProperty = new G4MaterialPropertiesTable(); 383 384 std::vector<G4double> p_mirror = {2.00 * eV, 3.47 * eV}; 385 std::vector<G4double> refl_mirror = {fMirrorReflectivity, fMirrorReflectivity}; 386 std::vector<G4double> effi_mirror = {0., 0.}; 387 388 mirrorSurfaceProperty->AddProperty("REFLECTIVITY", p_mirror, refl_mirror); 389 mirrorSurfaceProperty->AddProperty("EFFICIENCY", p_mirror, effi_mirror); 390 391 mirrorSurface->SetMaterialPropertiesTable(mirrorSurfaceProperty); 392 393 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fMirrorOrigin), logicMirror, "Mirror", 394 fLogicWorld, false, 0); 395 396 new G4LogicalSkinSurface("MirrorSurface", logicMirror, mirrorSurface); 397 } 398 399 //-------------------------------------------------- 400 // Coupling at the read-out end 401 //-------------------------------------------------- 402 403 // Clear Fiber (Coupling Layer) 404 G4VSolid* solidCouple = new G4Box("Couple", fCoupleRX, fCoupleRY, fCoupleZ); 405 406 auto logicCouple = new G4LogicalVolume(solidCouple, air, "Couple"); 407 408 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fCoupleOrigin), logicCouple, "Couple", 409 fLogicWorld, false, 0); 410 411 //-------------------------------------------------- 412 // A logical layer in front of PhotonDet 413 //-------------------------------------------------- 414 415 // Purpose: Preventing direct dielectric to metal contact 416 417 // Check for valid placement of PhotonDet 418 if (fMPPCTheta > std::atan(fMPPCDist / fMPPCHalfL)) { 419 fMPPCTheta = 0.; 420 fMPPCOriginX = std::sin(fMPPCTheta) * (fMPPCDist + fClrfiberZ); 421 fMPPCOriginZ = -fCoupleZ + std::cos(fMPPCTheta) * (fMPPCDist + fClrfiberZ); 422 G4ExceptionDescription ed; 423 ed << "Invalid alignment. Alignment reset to 0."; 424 G4Exception("WLSDetectorConstruction", "wls002", JustWarning, ed); 425 } 426 427 // Clear Fiber (Coupling Layer) 428 G4VSolid* solidClrfiber; 429 430 if (fMPPCShape == "Square") { 431 solidClrfiber = new G4Box("ClearFiber", fClrfiberHalfL, fClrfiberHalfL, fClrfiberZ); 432 } 433 else { 434 solidClrfiber = new G4Tubs("ClearFiber", 0., fClrfiberHalfL, fClrfiberZ, 0., twopi); 435 } 436 437 auto logicClrfiber = new G4LogicalVolume(solidClrfiber, air, "ClearFiber"); 438 439 new G4PVPlacement(new G4RotationMatrix(CLHEP::HepRotationY(-fMPPCTheta)), 440 G4ThreeVector(fMPPCOriginX, 0.0, fMPPCOriginZ), logicClrfiber, "ClearFiber", 441 logicCouple, false, 0); 442 443 //-------------------------------------------------- 444 // PhotonDet (Sensitive Detector) 445 //-------------------------------------------------- 446 447 // Physical Construction 448 G4VSolid* solidPhotonDet = nullptr; 449 450 if (fMPPCShape == "Square") 451 solidPhotonDet = new G4Box("PhotonDet", fMPPCHalfL, fMPPCHalfL, fMPPCZ); 452 else 453 solidPhotonDet = new G4Tubs("PhotonDet", 0., fMPPCHalfL, fMPPCZ, 0., twopi); 454 455 auto logicPhotonDet = new G4LogicalVolume(solidPhotonDet, aluminum, "PhotonDet_LV"); 456 457 new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.), logicPhotonDet, "PhotonDet", logicClrfiber, 458 false, 0); 459 460 // PhotonDet Surface Properties 461 auto photonDetSurface = 462 new G4OpticalSurface("PhotonDetSurface", glisur, ground, dielectric_metal, fMPPCPolish); 463 464 auto photonDetSurfaceProperty = new G4MaterialPropertiesTable(); 465 466 std::vector<G4double> p_mppc = {2.00 * eV, 3.47 * eV}; 467 std::vector<G4double> refl_mppc = {fMPPCReflectivity, fMPPCReflectivity}; 468 std::vector<G4double> effi_mppc = {1., 1.}; 469 470 photonDetSurfaceProperty->AddProperty("REFLECTIVITY", p_mppc, refl_mppc); 471 photonDetSurfaceProperty->AddProperty("EFFICIENCY", p_mppc, effi_mppc); 472 473 photonDetSurface->SetMaterialPropertiesTable(photonDetSurfaceProperty); 474 475 new G4LogicalSkinSurface("PhotonDetSurface", logicPhotonDet, photonDetSurface); 476 477 // visualization attributes ------------------------------------------------- 478 479 auto visAttributes = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0)); 480 visAttributes->SetVisibility(false); 481 fLogicWorld->SetVisAttributes(visAttributes); 482 fVisAttributes.push_back(visAttributes); 483 484 visAttributes = new G4VisAttributes(G4Colour(0.2, 0.2, 0.2, 0.5)); 485 visAttributes->SetVisibility(true); 486 logicExtrusion->SetVisAttributes(visAttributes); 487 fVisAttributes.push_back(visAttributes); 488 489 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 1.0, 0.9)); 490 visAttributes->SetVisibility(true); 491 logicScintillator->SetVisAttributes(visAttributes); 492 fVisAttributes.push_back(visAttributes); 493 494 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.2, 0.2)); 495 visAttributes->SetVisibility(true); 496 logicScintSide->SetVisAttributes(visAttributes); 497 fVisAttributes.push_back(visAttributes); 498 499 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.2, 0.2)); 500 visAttributes->SetVisibility(true); 501 logicScintCrnr->SetVisAttributes(visAttributes); 502 fVisAttributes.push_back(visAttributes); 503 504 visAttributes = new G4VisAttributes(G4Colour(0.4, 0.0, 0.0, 0.5)); 505 visAttributes->SetVisibility(true); 506 fLogicHole->SetVisAttributes(visAttributes); 507 fVisAttributes.push_back(visAttributes); 508 509 if (logicClad1 != nullptr) { 510 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.5, 0.5)); 511 visAttributes->SetVisibility(true); 512 logicClad1->SetVisAttributes(visAttributes); 513 fVisAttributes.push_back(visAttributes); 514 } 515 516 if (logicClad2 != nullptr) { 517 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.5, 0.8, 0.5)); 518 visAttributes->SetVisibility(true); 519 logicClad2->SetVisAttributes(visAttributes); 520 fVisAttributes.push_back(visAttributes); 521 } 522 523 visAttributes = new G4VisAttributes(G4Colour(0.8, 0.8, 1.0)); 524 visAttributes->SetVisibility(true); 525 logicWLSfiber->SetVisAttributes(visAttributes); 526 fVisAttributes.push_back(visAttributes); 527 528 if (fMirrorToggle == true) { 529 visAttributes = new G4VisAttributes(G4Colour(0.3, 0.3, 1.0, 0.3)); 530 visAttributes->SetVisibility(true); 531 logicMirror->SetVisAttributes(visAttributes); 532 fVisAttributes.push_back(visAttributes); 533 } 534 535 visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 0.5, 0.5)); 536 visAttributes->SetVisibility(true); 537 logicCouple->SetVisAttributes(visAttributes); 538 fVisAttributes.push_back(visAttributes); 539 540 visAttributes = new G4VisAttributes(G4Colour(0.3, 0.3, 0.3, 0.5)); 541 visAttributes->SetVisibility(true); 542 logicClrfiber->SetVisAttributes(visAttributes); 543 fVisAttributes.push_back(visAttributes); 544 545 visAttributes = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0, 0.8)); 546 visAttributes->SetVisibility(true); 547 logicPhotonDet->SetVisAttributes(visAttributes); 548 fVisAttributes.push_back(visAttributes); 549 550 return fPhysiWorld; 551 } 552 553 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 554 555 void WLSDetectorConstruction::ConstructSDandField() 556 { 557 if (!fmppcSD.Get()) { 558 G4String mppcSDName = "WLS/PhotonDet"; 559 auto mppcSD = new WLSPhotonDetSD(mppcSDName); 560 G4SDManager::GetSDMpointer()->AddNewDetector(mppcSD); 561 fmppcSD.Put(mppcSD); 562 } 563 SetSensitiveDetector("PhotonDet_LV", fmppcSD.Get(), true); 564 } 565 566 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 567 568 void WLSDetectorConstruction::UpdateGeometryParameters() 569 { 570 fWLSfiberRX = fXYRatio * fWLSfiberRY; 571 572 fClad1RX = fWLSfiberRX + 0.03 * fWLSfiberRX; 573 fClad1RY = fWLSfiberRY + 0.03 * fWLSfiberRY; 574 fClad1Z = fWLSfiberZ; 575 576 fClad2RX = fClad1RX + 0.03 * fWLSfiberRX; 577 fClad2RY = fClad1RY + 0.03 * fWLSfiberRY; 578 fClad2Z = fWLSfiberZ; 579 580 fWorldSizeX = fClad2RX + fMPPCDist + fMPPCHalfL + 1. * cm; 581 fWorldSizeY = fClad2RY + fMPPCDist + fMPPCHalfL + 1. * cm; 582 fWorldSizeZ = fWLSfiberZ + fMPPCDist + fMPPCHalfL + 1. * cm; 583 584 fCoupleRX = fWorldSizeX; 585 fCoupleRY = fWorldSizeY; 586 fCoupleZ = (fWorldSizeZ - fWLSfiberZ) / 2.; 587 588 fClrfiberHalfL = fMPPCHalfL; 589 590 fMirrorRmax = fClad2RY; 591 592 fCoupleOrigin = fWLSfiberOrigin + fWLSfiberZ + fCoupleZ; 593 fMirrorOrigin = fWLSfiberOrigin - fWLSfiberZ - fMirrorZ; 594 fMPPCOriginX = std::sin(fMPPCTheta) * (fMPPCDist + fClrfiberZ); 595 fMPPCOriginZ = -fCoupleZ + std::cos(fMPPCTheta) * (fMPPCDist + fClrfiberZ); 596 } 597 598 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 599 600 void WLSDetectorConstruction::SetPhotonDetGeometry(G4String shape) 601 // Set the Geometry of the PhotonDet detector 602 // Pre: shape must be either "Circle" and "Square" 603 { 604 if (shape == "Circle" || shape == "Square") fMPPCShape = shape; 605 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 606 } 607 608 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 609 610 void WLSDetectorConstruction::SetNumberOfCladding(G4int num) 611 // Set the number of claddings 612 // Pre: 0 <= num <= 2 613 { 614 fNumOfCladLayers = num; 615 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 616 } 617 618 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 619 620 void WLSDetectorConstruction::SetWLSLength(G4double length) 621 // Set the TOTAL length of the WLS fiber 622 { 623 fWLSfiberZ = length; 624 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 625 } 626 627 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 628 629 void WLSDetectorConstruction::SetWLSRadius(G4double radius) 630 // Set the Y radius of WLS fiber 631 { 632 fWLSfiberRY = radius; 633 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 634 } 635 636 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 637 638 void WLSDetectorConstruction::SetClad1Radius(G4double radius) 639 // Set the Y radius of Cladding 1 640 { 641 fClad1RY = radius; 642 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 643 } 644 645 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 646 647 void WLSDetectorConstruction::SetClad2Radius(G4double radius) 648 // Set the Y radius of Cladding 2 649 { 650 fClad2RY = radius; 651 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 652 } 653 654 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 655 656 void WLSDetectorConstruction::SetPhotonDetHalfLength(G4double halfL) 657 // Set the half length of the PhotonDet detector 658 // The half length will be the radius if PhotonDet is circular 659 { 660 fMPPCHalfL = halfL; 661 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 662 } 663 664 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 665 666 void WLSDetectorConstruction::SetGap(G4double gap) 667 // Set the distance between fiber end and PhotonDet 668 { 669 fMPPCDist = gap; 670 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 671 } 672 673 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 674 675 void WLSDetectorConstruction::SetPhotonDetAlignment(G4double theta) 676 // Set the Aligment of PhotonDet with respect to the z axis 677 // If theta is 0 deg, then the detector is perfectly aligned 678 // PhotonDet will be deviated by theta from z axis 679 // facing towards the center of the fiber 680 { 681 fMPPCTheta = theta; 682 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 683 } 684 685 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 686 687 void WLSDetectorConstruction::SetSurfaceRoughness(G4double roughness) 688 // Set the Surface Roughness between Cladding 1 and WLS fiber 689 // Pre: 0 < roughness <= 1 690 { 691 fSurfaceRoughness = roughness; 692 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 693 } 694 695 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 696 697 void WLSDetectorConstruction::SetMirrorPolish(G4double polish) 698 // Set the Polish of the mirror, polish of 1 is a perfect mirror surface 699 // Pre: 0 < polish <= 1 700 { 701 fMirrorPolish = polish; 702 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 703 } 704 705 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 706 707 void WLSDetectorConstruction::SetMirrorReflectivity(G4double reflectivity) 708 // Set the Reflectivity of the mirror, reflectivity of 1 is a perfect mirror 709 // Pre: 0 < reflectivity <= 1 710 { 711 fMirrorReflectivity = reflectivity; 712 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 713 } 714 715 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 716 717 void WLSDetectorConstruction::SetPhotonDetPolish(G4double polish) 718 // Set the Polish of the PhotonDet, polish of 1 is a perfect mirror surface 719 // Pre: 0 < polish <= 1 720 { 721 fMPPCPolish = polish; 722 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 723 } 724 725 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 726 727 void WLSDetectorConstruction::SetPhotonDetReflectivity(G4double reflectivity) 728 // Set the Reflectivity of the PhotonDet, reflectivity of 1 is a perfect mirror 729 // Pre: 0 < reflectivity <= 1 730 { 731 fMPPCReflectivity = reflectivity; 732 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 733 } 734 735 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 736 737 void WLSDetectorConstruction::SetMirror(G4bool flag) 738 // Toggle to place the mirror or not at one end (-z end) of the fiber 739 // True means place the mirror, false means otherwise 740 { 741 fMirrorToggle = flag; 742 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 743 } 744 745 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 746 747 void WLSDetectorConstruction::SetXYRatio(G4double r) 748 // Set the ratio of the x and y radius of the ellipse (x/y) 749 // a ratio of 1 would produce a circle 750 { 751 fXYRatio = r; 752 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 753 } 754 755 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 756 757 void WLSDetectorConstruction::SetBarLength(G4double length) 758 // Set the length of the scintillator bar 759 { 760 fBarLength = length; 761 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 762 } 763 764 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 765 766 void WLSDetectorConstruction::SetBarBase(G4double side) 767 // Set the side of the scintillator bar 768 { 769 fBarBase = side; 770 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 771 } 772 773 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 774 775 void WLSDetectorConstruction::SetHoleRadius(G4double radius) 776 // Set the radius of the fiber hole 777 { 778 fHoleRadius = radius; 779 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 780 } 781 782 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 783 784 void WLSDetectorConstruction::SetCoatingThickness(G4double thick) 785 // Set thickness of the coating on the bars 786 { 787 fCoatingThickness = thick; 788 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 789 } 790 791 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 792 793 void WLSDetectorConstruction::SetCoatingRadius(G4double radius) 794 // Set inner radius of the corner bar coating 795 { 796 fCoatingRadius = radius; 797 G4RunManager::GetRunManager()->GeometryHasBeenModified(); 798 } 799 800 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 801 802 G4double WLSDetectorConstruction::GetWLSFiberLength() 803 { 804 return fWLSfiberZ; 805 } 806 807 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 808 809 G4double WLSDetectorConstruction::GetBarLength() 810 { 811 return fBarLength; 812 } 813 814 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 815 816 G4double WLSDetectorConstruction::GetBarBase() 817 { 818 return fBarBase; 819 } 820 821 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 822 823 G4double WLSDetectorConstruction::GetHoleRadius() 824 { 825 return fHoleRadius; 826 } 827 828 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 829 830 G4double WLSDetectorConstruction::GetHoleLength() 831 { 832 return fHoleLength; 833 } 834 835 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 836 837 G4double WLSDetectorConstruction::GetFiberRadius() 838 { 839 return GetWLSFiberRMax(); 840 } 841 842 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 843 844 G4double WLSDetectorConstruction::GetCoatingThickness() 845 { 846 return fCoatingThickness; 847 } 848 849 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 850 851 G4double WLSDetectorConstruction::GetCoatingRadius() 852 { 853 return fCoatingRadius; 854 } 855 856 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 857 858 G4double WLSDetectorConstruction::GetWLSFiberEnd() 859 { 860 return fWLSfiberOrigin + fWLSfiberZ; 861 } 862 863 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 864 865 G4double WLSDetectorConstruction::GetWLSFiberRMax() 866 { 867 if (fNumOfCladLayers == 2) return fClad2RY; 868 if (fNumOfCladLayers == 1) return fClad1RY; 869 return fWLSfiberRY; 870 } 871 872 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 873 874 G4double WLSDetectorConstruction::GetSurfaceRoughness() 875 { 876 return fSurfaceRoughness; 877 } 878 879 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 880 881 // Return True if the fiber construction is ideal 882 G4bool WLSDetectorConstruction::IsPerfectFiber() 883 { 884 return fSurfaceRoughness == 1. && fXYRatio == 1. 885 && (!fMirrorToggle || (fMirrorPolish == 1. && fMirrorReflectivity == 1.)); 886 } 887 888 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 889 890 G4Material* WLSDetectorConstruction::FindMaterial(G4String name) 891 { 892 G4Material* material = G4Material::GetMaterial(name, true); 893 return material; 894 } 895