Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 /// \file DetectorConstruction.hh 27 /// \brief Definition of the DetectorConstruct 28 // 29 // 30 31 //....oooOO0OOooo........oooOO0OOooo........oo 32 //....oooOO0OOooo........oooOO0OOooo........oo 33 34 #include "DetectorConstruction.hh" 35 36 #include "DetectorMessenger.hh" 37 #include "PrimaryGeneratorAction.hh" 38 39 #include "G4Box.hh" 40 #include "G4Cons.hh" 41 #include "G4FieldManager.hh" 42 #include "G4GeometryManager.hh" 43 #include "G4LogicalVolume.hh" 44 #include "G4LogicalVolumeStore.hh" 45 #include "G4Material.hh" 46 #include "G4PVPlacement.hh" 47 #include "G4PVReplica.hh" 48 #include "G4PhysicalConstants.hh" 49 #include "G4PhysicalVolumeStore.hh" 50 #include "G4RotationMatrix.hh" 51 #include "G4RunManager.hh" 52 #include "G4SDManager.hh" 53 #include "G4SolidStore.hh" 54 #include "G4SystemOfUnits.hh" 55 #include "G4ThreeVector.hh" 56 #include "G4TransportationManager.hh" 57 #include "G4Tubs.hh" 58 #include "G4UniformMagField.hh" 59 #include "globals.hh" 60 61 //....oooOO0OOooo........oooOO0OOooo........oo 62 63 DetectorConstruction::DetectorConstruction() 64 : fVacuum(nullptr), 65 fIron(nullptr), 66 fCopper(nullptr), 67 fTungsten(nullptr), 68 fLead(nullptr), 69 fUranium(nullptr), 70 fPbWO4(nullptr), 71 fPolystyrene(nullptr), 72 fLiquidArgon(nullptr), 73 fSilicon(nullptr), 74 fQuartz(nullptr), 75 fBrass(nullptr), 76 fAluminium(nullptr), 77 fGraphite(nullptr), 78 fAbsorberMaterial(nullptr), 79 fActiveMaterial(nullptr), 80 fExperimentalHall_log(nullptr), 81 fExperimentalHall_phys(nullptr), 82 fLogicCalo(nullptr), 83 fPhysiCalo(nullptr), 84 fLogicModule(nullptr), 85 fPhysiModule(nullptr), 86 fLogicAbsorber(nullptr), 87 fPhysiAbsorber(nullptr), 88 fLogicActive(nullptr), 89 fPhysiActive(nullptr), 90 fFieldMgr(nullptr), 91 fUniformMagField(nullptr), 92 fDetectorMessenger(nullptr), 93 // Default values. ***LOOKHERE*** 94 fIsCalHomogeneous(false), // Sampling cal 95 fIsUnitInLambda(false), // Unit of length 96 fAbsorberTotalLength(2.0 * CLHEP::m), 97 fCalorimeterRadius(1.0 * CLHEP::m), 98 fActiveLayerNumber(50), 99 fActiveLayerSize(4.0 * CLHEP::mm), 100 fIsRadiusUnitInLambda(false), // Unit of 101 // Extra 102 fCaloLength(2.0 * CLHEP::m), 103 // Scoring part 104 fLogicScoringUpDown(nullptr), 105 fPhysiScoringUpstream(nullptr), 106 fPhysiScoringDownstream(nullptr), 107 fLogicScoringSide(nullptr), 108 fPhysiScoringSide(nullptr) 109 { 110 fFieldMgr = G4TransportationManager::GetTran 111 DefineMaterials(); 112 fAbsorberMaterial = fIron; 113 fActiveMaterial = fPolystyrene; 114 fDetectorMessenger = new DetectorMessenger(t 115 } 116 117 //....oooOO0OOooo........oooOO0OOooo........oo 118 119 DetectorConstruction::~DetectorConstruction() 120 { 121 delete fDetectorMessenger; 122 delete fUniformMagField; 123 } 124 125 //....oooOO0OOooo........oooOO0OOooo........oo 126 127 G4VPhysicalVolume* DetectorConstruction::Const 128 { 129 return ConstructCalorimeter(); 130 } 131 132 //....oooOO0OOooo........oooOO0OOooo........oo 133 134 void DetectorConstruction::ConstructSDandField 135 136 //....oooOO0OOooo........oooOO0OOooo........oo 137 138 void DetectorConstruction::DefineMaterials() 139 { 140 G4double a; // atomic mass 141 G4double z; // atomic number 142 G4double density, pressure, temperature, fra 143 G4String name, symbol; 144 G4int nel, natoms; 145 146 //--- elements 147 148 a = 1.01 * g / mole; 149 G4Element* elH = new G4Element(name = "Hydro 150 151 a = 2.01 * g / mole; 152 // G4Element* elD = new G4Element( name="Deu 153 154 a = 4. * g / mole; 155 // G4Element* elHe = new G4Element( name="He 156 157 a = 6.94 * g / mole; 158 // G4Element* elLi = new G4Element( name="Li 159 160 a = 9.01 * g / mole; 161 // G4Element* elBe = new G4Element( name="Be 162 163 a = 12.01 * g / mole; 164 G4Element* elC = new G4Element(name = "Carbo 165 166 a = 14.01 * g / mole; 167 G4Element* elN = new G4Element(name = "Nitro 168 169 a = 16. * g / mole; 170 G4Element* elO = new G4Element(name = "Oxyge 171 172 a = 20.18 * g / mole; 173 // G4Element* elNe = new G4Element( name="Ne 174 175 a = 22.99 * g / mole; 176 // G4Element* elNa = new G4Element( name="So 177 178 a = 26.98 * g / mole; 179 // G4Element* elAl = new G4Element( name="Al 180 181 a = 28.085 * g / mole; 182 G4Element* elSi = new G4Element(name = "Sili 183 184 a = 40.08 * g / mole; 185 // G4Element* elCa = new G4Element( name="Ca 186 187 a = 55.850 * g / mole; 188 // G4Element* elFe = new G4Element( name="Ir 189 190 a = 63.54 * g / mole; 191 G4Element* elCu = new G4Element(name = "Copp 192 193 a = 65.41 * g / mole; 194 G4Element* elZn = new G4Element(name = "Zinc 195 196 a = 183.85 * g / mole; 197 G4Element* elW = new G4Element(name = "Tungs 198 199 a = 207.19 * g / mole; 200 G4Element* elPb = new G4Element(name = "Lead 201 202 a = 238.03 * g / mole; 203 // G4Element* elU = new G4Element(name="Uran 204 205 //--- simple materials 206 207 // Iron has a X0 = 1.7585 cm and lambda_I 208 density = 7.87 * g / cm3; 209 a = 55.85 * g / mole; 210 fIron = new G4Material(name = "Iron", z = 26 211 212 // Copper has a X0 = 1.4353 cm and lambda 213 density = 8.96 * g / cm3; 214 a = 63.54 * g / mole; 215 fCopper = new G4Material(name = "Copper", z 216 217 // Tungsten has a X0 = 0.35 cm and lambda 218 density = 19.3 * g / cm3; 219 a = 183.85 * g / mole; 220 fTungsten = new G4Material(name = "Tungsten" 221 222 // Lead has a X0 = 0.56120 cm and lambda_ 223 density = 11.35 * g / cm3; 224 a = 207.19 * g / mole; 225 fLead = new G4Material(name = "Lead", z = 82 226 227 // Uranium has a X0 = 0.31662 cm and lamb 228 density = 18.95 * g / cm3; 229 a = 238.03 * g / mole; 230 fUranium = new G4Material(name = "Uranium", 231 232 // Liquid Argon has a X0 = 10.971 cm and 233 density = 1.4 * g / cm3; 234 a = 39.95 * g / mole; 235 fLiquidArgon = new G4Material(name = "Liquid 236 237 density = 0.002 * g / cm3; 238 a = 39.95 * g / mole; 239 // G4Material* ArgonGas = new G4Material( na 240 241 // Silicon has a X0 = 9.3688 cm and lambd 242 density = 2.33 * g / cm3; 243 a = 28.085 * g / mole; 244 fSilicon = new G4Material(name = "Silicon", 245 246 // Aluminium has a X0 = 8.8959 cm and lam 247 density = 2.7 * g / cm3; 248 a = 26.98 * g / mole; 249 fAluminium = new G4Material(name = "Aluminiu 250 251 // Graphite has a X0 = 19.3213 cm and lam 252 density = 2.210 * g / cm3; 253 a = 12.0107 * g / mole; 254 fGraphite = new G4Material(name = "Graphite" 255 256 density = 8.96 * g / cm3; 257 a = 58.69 * g / mole; 258 // G4Material* Nickel = new G4Material( name 259 260 //--- mixtures 261 262 density = 1.290 * mg / cm3; 263 G4Material* Air = new G4Material(name = "Air 264 Air->AddElement(elN, 0.7); 265 Air->AddElement(elO, 0.3); 266 267 density = 1.e-5 * g / cm3; 268 pressure = 2.e-2 * bar; 269 temperature = STP_Temperature; // From Phys 270 fVacuum = new G4Material(name = "Vacuum", de 271 fVacuum->AddMaterial(Air, fractionmass = 1.) 272 273 // Plastic scintillator tiles (used both in 274 // and ATLAS hadron barrel calorimeter): 275 // X0 = 42.4 cm and lambda_I = 79.360 276 density = 1.032 * g / cm3; 277 fPolystyrene = new G4Material(name = "Polyst 278 fPolystyrene->AddElement(elC, natoms = 19); 279 fPolystyrene->AddElement(elH, natoms = 21); 280 281 // PbWO4 CMS crystals. It has a X0 = 0.89 c 282 density = 8.28 * g / cm3; 283 fPbWO4 = new G4Material(name = "PbWO4", dens 284 fPbWO4->AddElement(elPb, natoms = 1); 285 fPbWO4->AddElement(elW, natoms = 1); 286 fPbWO4->AddElement(elO, natoms = 4); 287 288 fQuartz = new G4Material(name = "Quartz", de 289 fQuartz->AddElement(elSi, 1); 290 fQuartz->AddElement(elO, 2); 291 292 fBrass = new G4Material(name = "Brass", dens 293 fBrass->AddElement(elCu, 0.7); 294 fBrass->AddElement(elZn, 0.3); 295 } 296 297 //....oooOO0OOooo........oooOO0OOooo........oo 298 299 G4VPhysicalVolume* DetectorConstruction::Const 300 { 301 if (!AreParametersOK()) { 302 G4cout << " DetectorConstruction::Construc 303 << "\t PARAMETERS NOT WELL-DEFINED! 304 return fExperimentalHall_phys; 305 } 306 307 // Clean old geometry, if any. 308 G4GeometryManager::GetInstance()->OpenGeomet 309 G4PhysicalVolumeStore::GetInstance()->Clean( 310 G4LogicalVolumeStore::GetInstance()->Clean() 311 G4SolidStore::GetInstance()->Clean(); 312 313 G4double lambda = 0.0; // G4double X0 = 0.0 314 if (fIsUnitInLambda) { 315 if (fAbsorberMaterial == fIron) { 316 lambda = 16.760 * cm; // X0 = 1.758 317 } 318 else if (fAbsorberMaterial == fCopper) { 319 lambda = 15.056 * cm; // X0 = 1.435 320 } 321 else if (fAbsorberMaterial == fBrass) { 322 lambda = 15.056 * cm; // Lack of PDG da 323 } 324 else if (fAbsorberMaterial == fTungsten) { 325 lambda = 9.5855 * cm; // X0 = 0.35* 326 } 327 else if (fAbsorberMaterial == fLead) { 328 lambda = 17.092 * cm; // X0 = 0.561 329 } 330 else if (fAbsorberMaterial == fPbWO4) { 331 lambda = 22.4 * cm; // X0 = 0.89*cm 332 } 333 else if (fAbsorberMaterial == fUranium) { 334 lambda = 10.501 * cm; // X0 = 0.316 335 } 336 else if (fAbsorberMaterial == fGraphite) { 337 lambda = 38.82 * cm; // X0 = 19.32* 338 } 339 else { 340 std::cout << "ERROR: absorber material n 341 } 342 } 343 344 //------------------- volumes -------------- 345 346 G4double absorberTotalLength = fAbsorberTota 347 G4double calorimeterRadius = fCalorimeterRad 348 if (fIsUnitInLambda) { 349 absorberTotalLength *= lambda; 350 calorimeterRadius *= lambda; 351 } 352 353 // --- experimental hall (world volume) * 354 // beam line along the Z-axis 355 G4double expHall_x = 10.0 * m; // half dime 356 G4double expHall_y = 10.0 * m; // half dime 357 G4double expHall_z = 10.0 * m; // half dime 358 359 G4Box* experimentalHall_box = new G4Box("exp 360 fExperimentalHall_log = new G4LogicalVolume( 361 362 363 364 365 366 fExperimentalHall_phys = new G4PVPlacement(0 367 G 368 " 369 f 370 0 371 f 372 0 373 374 // --- Detector 375 // The idea is to use Replica placement. 376 // To do that, we have to define two extra v 377 // and the "module". The former, which has t 378 // is the mother of the module volume. The c 379 // filled by a number (theActiveLayerNumber) 380 // A module volume, in its turn, is the moth 381 // active layer. 382 383 // --- absorber layer : logical 384 G4double zAbsorber = absorberTotalLength / s 385 // In the case of homogenous calorimeter the 386 // subtracted because it is made of the same 387 // (the material of the "active" part is set 388 // the aborber). 389 if (fIsCalHomogeneous) { 390 fActiveMaterial = fAbsorberMaterial; 391 zAbsorber -= fActiveLayerSize; 392 } 393 zAbsorber /= 2.0; // half dimension along z 394 G4Tubs* solidAbsorber = new G4Tubs("solidAbs 395 0.0, // 396 calorimet 397 zAbsorber 398 0.0, // 399 2.0 * pi) 400 fLogicAbsorber = new G4LogicalVolume(solidAb 401 fAbsorb 402 "logicA 403 0, // 404 0, // 405 0); // 406 407 // --- active layer : logical 408 G4double zActive = fActiveLayerSize / 2.0; 409 G4Tubs* solidActive = new G4Tubs("solidActiv 410 0.0, // in 411 calorimeter 412 zActive, / 413 0.0, // st 414 2.0 * pi); 415 fLogicActive = new G4LogicalVolume(solidActi 416 fActiveMa 417 "logicAct 418 0, // fi 419 0, // se 420 0); // u 421 422 // --- module : logical 423 G4double zModule = zAbsorber + zActive; // 424 G4Tubs* solidModule = new G4Tubs("solidModul 425 0.0, // in 426 calorimeter 427 zModule, / 428 0.0, // st 429 2.0 * pi); 430 fLogicModule = new G4LogicalVolume(solidModu 431 fLead, / 432 "logicMod 433 0, // fi 434 0, // se 435 0); // u 436 437 // --- calorimeter : logical 438 G4int numberOfModules = fActiveLayerNumber; 439 G4double zCalo = numberOfModules * zModule; 440 fCaloLength = 2.0 * zCalo; 441 G4Tubs* solidCalo = new G4Tubs("solidCalo", 442 0.0, // inne 443 calorimeterRa 444 zCalo, // ha 445 0.0, // star 446 2.0 * pi); / 447 fLogicCalo = new G4LogicalVolume(solidCalo, 448 fLead, // 449 "logicCalo" 450 0, // fiel 451 0, // sens 452 0); // use 453 454 // --- absorber layer : physical 455 G4double zpos = -zActive; 456 fPhysiAbsorber = new G4PVPlacement(0, // ro 457 G4ThreeVe 458 fLogicAbs 459 "physiAbs 460 fLogicMod 461 false, / 462 1000); / 463 464 // --- active layer : physical 465 zpos += zAbsorber + zActive; 466 fPhysiActive = new G4PVPlacement(0, // rota 467 G4ThreeVect 468 fLogicActiv 469 "physiActiv 470 fLogicModul 471 false, // 472 2000); // 473 474 // --- module : physical (using repli 475 fPhysiModule = new G4PVReplica("Calo", // n 476 fLogicModule, 477 fLogicCalo, 478 kZAxis, // a 479 numberOfModul 480 2 * (zAbsorbe 481 482 // --- calorimeter : physical 483 fPhysiCalo = new G4PVPlacement(0, // rotati 484 G4ThreeVector 485 "physiCalo", 486 fLogicCalo, 487 fExperimental 488 false, // bo 489 100); // cop 490 491 // Three scoring volumes: one thin layer dow 492 // one thin layer sur 493 // one thin layer ups 494 G4Tubs* solidScoringUpDown = new G4Tubs("sol 495 0.0, 496 calo 497 0.5 498 0.0, 499 2.0 500 fLogicScoringUpDown = new G4LogicalVolume(so 501 fV 502 "l 503 0, 504 0, 505 0) 506 G4double zScoringUpDown = 0.5 * (fCaloLength 507 fPhysiScoringUpstream = new G4PVPlacement(0, 508 G4 509 // 510 "p 511 fL 512 fE 513 fa 514 0) 515 fPhysiScoringDownstream = new G4PVPlacement( 516 517 518 519 520 521 522 523 524 G4Tubs* solidScoringSide = new G4Tubs("solid 525 calori 526 calori 527 0.5 * 528 0.0, 529 2.0 * 530 fLogicScoringSide = new G4LogicalVolume(soli 531 fVac 532 "log 533 0, 534 0, 535 0); 536 fPhysiScoringSide = new G4PVPlacement(0, // 537 G4Thre 538 "physi 539 fLogic 540 fExper 541 false, 542 0); / 543 544 return fExperimentalHall_phys; 545 } 546 547 //....oooOO0OOooo........oooOO0OOooo........oo 548 549 G4bool DetectorConstruction::AreParametersOK() 550 { 551 bool isOk = true; 552 if (!fAbsorberMaterial) { 553 isOk = false; 554 G4cout << " DetectorConstruction::AreParam 555 } 556 if (!fActiveMaterial) { 557 isOk = false; 558 G4cout << " DetectorConstruction::AreParam 559 } 560 if (fAbsorberTotalLength <= 0.0) { 561 isOk = false; 562 G4cout << " DetectorConstruction::AreParam 563 << fAbsorberTotalLength << G4endl; 564 } 565 if (fCalorimeterRadius <= 0.0) { 566 isOk = false; 567 G4cout << " DetectorConstruction::AreParam 568 << fCalorimeterRadius << G4endl; 569 } 570 if (fActiveLayerNumber <= 0) { 571 isOk = false; 572 G4cout << " DetectorConstruction::AreParam 573 << fActiveLayerNumber << G4endl; 574 } 575 if (fActiveLayerSize <= 0.0) { 576 isOk = false; 577 G4cout << " DetectorConstruction::AreParam 578 << G4endl; 579 } 580 return isOk; 581 } 582 583 //....oooOO0OOooo........oooOO0OOooo........oo 584 585 void DetectorConstruction::SetMagField(const G 586 { 587 if (fUniformMagField) { 588 delete fUniformMagField; 589 } 590 if (std::abs(fieldValue) > 0.0) { 591 // Apply a global uniform magnetic field a 592 // Notice that only if the magnetic field 593 // transportion in field gets activated. 594 fUniformMagField = new G4UniformMagField(G 595 fFieldMgr->SetDetectorField(fUniformMagFie 596 fFieldMgr->CreateChordFinder(fUniformMagFi 597 } 598 } 599 600 //....oooOO0OOooo........oooOO0OOooo........oo 601 602 void DetectorConstruction::SetAbsorberMaterial 603 { 604 if (name == "Fe" || name == "Iron" || name = 605 fAbsorberMaterial = fIron; 606 } 607 else if (name == "Cu" || name == "Copper" || 608 fAbsorberMaterial = fCopper; 609 } 610 else if (name == "Brass" || name == "brass") 611 fAbsorberMaterial = fBrass; 612 } 613 else if (name == "Pb" || name == "Lead" || n 614 fAbsorberMaterial = fLead; 615 } 616 else if (name == "PbWO4") { 617 fAbsorberMaterial = fPbWO4; 618 } 619 else if (name == "W" || name == "Tungsten" | 620 fAbsorberMaterial = fTungsten; 621 } 622 else if (name == "U" || name == "Uranium" || 623 fAbsorberMaterial = fUranium; 624 } 625 else if (name == "C" || name == "Graphite" | 626 fAbsorberMaterial = fGraphite; 627 } 628 else { 629 G4cout << G4endl << G4endl << "WARNING: th 630 << G4endl << " ===> the default 631 fAbsorberMaterial = fIron; 632 } 633 fLogicAbsorber->SetMaterial(fAbsorberMateria 634 } 635 636 //....oooOO0OOooo........oooOO0OOooo........oo 637 638 void DetectorConstruction::SetActiveMaterial(c 639 { 640 if (name == "Scintillator" || name == "scint 641 fActiveMaterial = fPolystyrene; 642 } 643 else if (name == "LAr" || name == "LiquidArg 644 fActiveMaterial = fLiquidArgon; 645 } 646 else if (name == "PbWO4") { 647 fActiveMaterial = fPbWO4; 648 } 649 else if (name == "Si" || name == "Silicon" | 650 fActiveMaterial = fSilicon; 651 } 652 else if (name == "Quartz" || name == "quartz 653 fActiveMaterial = fQuartz; 654 } 655 else if (name == "C" || name == "Graphite" | 656 fActiveMaterial = fGraphite; 657 } 658 else { 659 G4cout << G4endl << G4endl << "WARNING: th 660 << G4endl << " ===> the default 661 << G4endl; 662 fActiveMaterial = fPolystyrene; 663 } 664 fLogicActive->SetMaterial(fActiveMaterial); 665 } 666 667 //....oooOO0OOooo........oooOO0OOooo........oo 668 669 void DetectorConstruction::UpdateGeometry() 670 { 671 // G4RunManager::GetRunManager()->DefineWorl 672 G4RunManager::GetRunManager()->ReinitializeG 673 PrintParameters(); 674 // Update also the position of the gun 675 const PrimaryGeneratorAction* pPrimaryAction 676 G4RunManager::GetRunManager()->GetUserPrim 677 if (pPrimaryAction) pPrimaryAction->SetGunPo 678 } 679 680 //....oooOO0OOooo........oooOO0OOooo........oo 681 682 void DetectorConstruction::PrintParameters() 683 { 684 G4cout << G4endl << G4endl << " ------ Dete 685 << " Absorber Material = "; 686 if (fAbsorberMaterial) { 687 G4cout << fAbsorberMaterial->GetName(); 688 } 689 else { 690 G4cout << " UNDEFINED "; 691 } 692 G4cout << G4endl << " Active Material = "; 693 if (fActiveMaterial) { 694 G4cout << fActiveMaterial->GetName(); 695 } 696 else { 697 G4cout << " UNDEFINED "; 698 } 699 G4cout << G4endl << " Is the Calorimeter Hom 700 G4cout << G4endl << " Is the Unit in Lambda 701 G4cout << G4endl << " Absorber Total Length 702 if (fIsUnitInLambda) { 703 G4cout << fAbsorberTotalLength << " lambd 704 } 705 else { 706 G4cout << fAbsorberTotalLength / m << " m" 707 } 708 G4cout << G4endl << " Calorimeter Radius = " 709 if (fIsUnitInLambda) { 710 G4cout << fCalorimeterRadius << " lambdas 711 } 712 else { 713 G4cout << fCalorimeterRadius / m << " m"; 714 } 715 G4cout << G4endl << " Active Layer Number 716 G4cout << G4endl << " Active Layer Size 717 G4cout << G4endl << " Is the Radius Unit in 718 G4cout << G4endl << " Radius Bin Size 719 G4cout << G4endl << " Magnetic field [T] 720 if (fUniformMagField) { 721 G4cout << fUniformMagField->GetConstantFie 722 } 723 else { 724 G4cout << "(0,0,0)"; 725 } 726 727 G4cout << G4endl << " ---------------------- 728 << G4endl; 729 } 730 731 //....oooOO0OOooo........oooOO0OOooo........oo 732