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 /// \file electromagnetic/TestEm3/src/DetectorConstruction.cc 27 /// \brief Implementation of the DetectorConstruction class 28 // 29 // 30 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 31 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 32 33 #include "DetectorConstruction.hh" 34 35 #include "DetectorMessenger.hh" 36 37 #include "G4Box.hh" 38 #include "G4GeometryManager.hh" 39 #include "G4LogicalVolume.hh" 40 #include "G4LogicalVolumeStore.hh" 41 #include "G4Material.hh" 42 #include "G4NistManager.hh" 43 #include "G4PVPlacement.hh" 44 #include "G4PVReplica.hh" 45 #include "G4PhysicalConstants.hh" 46 #include "G4PhysicalVolumeStore.hh" 47 #include "G4RunManager.hh" 48 #include "G4SolidStore.hh" 49 #include "G4SystemOfUnits.hh" 50 #include "G4UnitsTable.hh" 51 52 #include <iomanip> 53 54 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 55 56 DetectorConstruction::DetectorConstruction() 57 { 58 for (G4int i = 0; i < kMaxAbsor; ++i) { 59 fAbsorMaterial[i] = nullptr; 60 fAbsorThickness[i] = 0.0; 61 fSolidAbsor[i] = nullptr; 62 fLogicAbsor[i] = nullptr; 63 fPhysiAbsor[i] = nullptr; 64 } 65 66 // default parameter values of the calorimeter 67 fNbOfAbsor = 2; 68 fAbsorThickness[1] = 2.3 * mm; 69 fAbsorThickness[2] = 5.7 * mm; 70 fNbOfLayers = 50; 71 fCalorSizeYZ = 40. * cm; 72 ComputeCalorParameters(); 73 74 // materials 75 DefineMaterials(); 76 SetWorldMaterial("Galactic"); 77 SetAbsorMaterial(1, "G4_Pb"); 78 SetAbsorMaterial(2, "G4_lAr"); 79 80 // create commands for interactive definition of the calorimeter 81 fDetectorMessenger = new DetectorMessenger(this); 82 } 83 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 85 86 DetectorConstruction::~DetectorConstruction() 87 { 88 delete fDetectorMessenger; 89 } 90 91 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 92 93 void DetectorConstruction::DefineMaterials() 94 { 95 // This function illustrates the possible ways to define materials using 96 // G4 database on G4Elements 97 G4NistManager* manager = G4NistManager::Instance(); 98 manager->SetVerbose(0); 99 // 100 // define Elements 101 // 102 G4double z, a; 103 104 G4Element* H = manager->FindOrBuildElement(1); 105 G4Element* C = manager->FindOrBuildElement(6); 106 G4Element* N = manager->FindOrBuildElement(7); 107 G4Element* O = manager->FindOrBuildElement(8); 108 G4Element* Si = manager->FindOrBuildElement(14); 109 G4Element* Ge = manager->FindOrBuildElement(32); 110 G4Element* Sb = manager->FindOrBuildElement(51); 111 G4Element* I = manager->FindOrBuildElement(53); 112 G4Element* Cs = manager->FindOrBuildElement(55); 113 G4Element* Pb = manager->FindOrBuildElement(82); 114 G4Element* Bi = manager->FindOrBuildElement(83); 115 116 // 117 // define an Element from isotopes, by relative abundance 118 // 119 G4int iz, n; // iz=number of protons in an isotope; 120 // n=number of nucleons in an isotope; 121 G4int ncomponents; 122 G4double abundance; 123 124 G4Isotope* U5 = new G4Isotope("U235", iz = 92, n = 235, a = 235.01 * g / mole); 125 G4Isotope* U8 = new G4Isotope("U238", iz = 92, n = 238, a = 238.03 * g / mole); 126 127 G4Element* U = new G4Element("enriched Uranium", "U", ncomponents = 2); 128 U->AddIsotope(U5, abundance = 90. * perCent); 129 U->AddIsotope(U8, abundance = 10. * perCent); 130 131 // 132 // define simple materials 133 // 134 G4double density; 135 136 new G4Material("liquidH2", z = 1., a = 1.008 * g / mole, density = 70.8 * mg / cm3); 137 new G4Material("Aluminium", z = 13., a = 26.98 * g / mole, density = 2.700 * g / cm3); 138 new G4Material("Titanium", z = 22., a = 47.867 * g / mole, density = 4.54 * g / cm3); 139 new G4Material("Iron", z = 26., a = 55.85 * g / mole, density = 7.870 * g / cm3); 140 new G4Material("Copper", z = 29., a = 63.55 * g / mole, density = 8.960 * g / cm3); 141 new G4Material("Tungsten", z = 74., a = 183.85 * g / mole, density = 19.30 * g / cm3); 142 new G4Material("Gold", z = 79., a = 196.97 * g / mole, density = 19.32 * g / cm3); 143 new G4Material("Uranium", z = 92., a = 238.03 * g / mole, density = 18.95 * g / cm3); 144 145 // 146 // define a material from elements. case 1: chemical molecule 147 // 148 G4int natoms; 149 150 G4Material* H2O = new G4Material("Water", density = 1.000 * g / cm3, ncomponents = 2); 151 H2O->AddElement(H, natoms = 2); 152 H2O->AddElement(O, natoms = 1); 153 H2O->GetIonisation()->SetMeanExcitationEnergy(78.0 * eV); 154 H2O->SetChemicalFormula("H_2O"); 155 156 G4Material* CH = new G4Material("Polystyrene", density = 1.032 * g / cm3, ncomponents = 2); 157 CH->AddElement(C, natoms = 1); 158 CH->AddElement(H, natoms = 1); 159 160 G4Material* Sci = new G4Material("Scintillator", density = 1.032 * g / cm3, ncomponents = 2); 161 Sci->AddElement(C, natoms = 9); 162 Sci->AddElement(H, natoms = 10); 163 164 Sci->GetIonisation()->SetBirksConstant(0.126 * mm / MeV); 165 166 G4Material* Lct = new G4Material("Lucite", density = 1.185 * g / cm3, ncomponents = 3); 167 Lct->AddElement(C, 59.97 * perCent); 168 Lct->AddElement(H, 8.07 * perCent); 169 Lct->AddElement(O, 31.96 * perCent); 170 171 G4Material* Sili = new G4Material("Silicon", density = 2.330 * g / cm3, ncomponents = 1); 172 Sili->AddElement(Si, natoms = 1); 173 174 G4Material* SiO2 = new G4Material("quartz", density = 2.200 * g / cm3, ncomponents = 2); 175 SiO2->AddElement(Si, natoms = 1); 176 SiO2->AddElement(O, natoms = 2); 177 178 G4Material* G10 = new G4Material("NemaG10", density = 1.700 * g / cm3, ncomponents = 4); 179 G10->AddElement(Si, natoms = 1); 180 G10->AddElement(O, natoms = 2); 181 G10->AddElement(C, natoms = 3); 182 G10->AddElement(H, natoms = 3); 183 184 G4Material* CsI = new G4Material("CsI", density = 4.534 * g / cm3, ncomponents = 2); 185 CsI->AddElement(Cs, natoms = 1); 186 CsI->AddElement(I, natoms = 1); 187 CsI->GetIonisation()->SetMeanExcitationEnergy(553.1 * eV); 188 189 G4Material* BGO = new G4Material("BGO", density = 7.10 * g / cm3, ncomponents = 3); 190 BGO->AddElement(O, natoms = 12); 191 BGO->AddElement(Ge, natoms = 3); 192 BGO->AddElement(Bi, natoms = 4); 193 194 // SiNx 195 density = 3.1 * g / cm3; 196 G4Material* SiNx = new G4Material("SiNx", density, ncomponents = 3); 197 SiNx->AddElement(Si, 300); 198 SiNx->AddElement(N, 310); 199 SiNx->AddElement(H, 6); 200 201 // 202 // define gaseous materials using G4 NIST database 203 // 204 G4double fractionmass; 205 206 G4Material* Air = manager->FindOrBuildMaterial("G4_AIR"); 207 manager->ConstructNewGasMaterial("Air20", "G4_AIR", 293. * kelvin, 1. * atmosphere); 208 209 G4Material* lAr = manager->FindOrBuildMaterial("G4_lAr"); 210 G4Material* lArEm3 = new G4Material("liquidArgon", density = 1.390 * g / cm3, ncomponents = 1); 211 lArEm3->AddMaterial(lAr, fractionmass = 1.0); 212 213 // 214 // define a material from elements and others materials (mixture of mixtures) 215 // 216 217 G4Material* Lead = new G4Material("Lead", density = 11.35 * g / cm3, ncomponents = 1); 218 Lead->AddElement(Pb, fractionmass = 1.0); 219 220 G4Material* LeadSb = new G4Material("LeadSb", density = 11.35 * g / cm3, ncomponents = 2); 221 LeadSb->AddElement(Sb, fractionmass = 4. * perCent); 222 LeadSb->AddElement(Pb, fractionmass = 96. * perCent); 223 224 G4Material* Aerog = new G4Material("Aerogel", density = 0.200 * g / cm3, ncomponents = 3); 225 Aerog->AddMaterial(SiO2, fractionmass = 62.5 * perCent); 226 Aerog->AddMaterial(H2O, fractionmass = 37.4 * perCent); 227 Aerog->AddElement(C, fractionmass = 0.1 * perCent); 228 229 // 230 // examples of gas in non STP conditions 231 // 232 G4double temperature, pressure; 233 234 G4Material* CO2 = 235 new G4Material("CarbonicGas", density = 27. * mg / cm3, ncomponents = 2, kStateGas, 236 temperature = 325. * kelvin, pressure = 50. * atmosphere); 237 CO2->AddElement(C, natoms = 1); 238 CO2->AddElement(O, natoms = 2); 239 240 G4Material* steam = 241 new G4Material("WaterSteam", density = 1.0 * mg / cm3, ncomponents = 1, kStateGas, 242 temperature = 273 * kelvin, pressure = 1 * atmosphere); 243 steam->AddMaterial(H2O, fractionmass = 1.); 244 245 new G4Material("ArgonGas", z = 18, a = 39.948 * g / mole, density = 1.782 * mg / cm3, kStateGas, 246 273.15 * kelvin, 1 * atmosphere); 247 // 248 // examples of vacuum 249 // 250 251 density = universe_mean_density; // from PhysicalConstants.h 252 pressure = 3.e-18 * pascal; 253 temperature = 2.73 * kelvin; 254 new G4Material("Galactic", z = 1., a = 1.008 * g / mole, density, kStateGas, temperature, 255 pressure); 256 257 density = 1.e-5 * g / cm3; 258 pressure = 2.e-2 * bar; 259 temperature = STP_Temperature; // from PhysicalConstants.h 260 G4Material* beam = 261 new G4Material("Beam", density, ncomponents = 1, kStateGas, temperature, pressure); 262 beam->AddMaterial(Air, fractionmass = 1.); 263 264 // G4cout << *(G4Material::GetMaterialTable()) << G4endl; 265 } 266 267 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 268 269 void DetectorConstruction::ComputeCalorParameters() 270 { 271 // Compute derived parameters of the calorimeter 272 fLayerThickness = 0.; 273 for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAbs++) { 274 fLayerThickness += fAbsorThickness[iAbs]; 275 } 276 fCalorThickness = fNbOfLayers * fLayerThickness; 277 fWorldSizeX = 1.2 * fCalorThickness; 278 fWorldSizeYZ = 1.2 * fCalorSizeYZ; 279 } 280 281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 282 283 G4VPhysicalVolume* DetectorConstruction::Construct() 284 { 285 if (fPhysiWorld) { 286 return fPhysiWorld; 287 } 288 // complete the Calor parameters definition 289 ComputeCalorParameters(); 290 291 // 292 // World 293 // 294 fSolidWorld = new G4Box("World", // its name 295 fWorldSizeX / 2, fWorldSizeYZ / 2, fWorldSizeYZ / 2); // its size 296 297 fLogicWorld = new G4LogicalVolume(fSolidWorld, // its solid 298 fWorldMaterial, // its material 299 "World"); // its name 300 301 fPhysiWorld = new G4PVPlacement(0, // no rotation 302 G4ThreeVector(), // at (0,0,0) 303 fLogicWorld, // its fLogical volume 304 "World", // its name 305 0, // its mother volume 306 false, // no boolean operation 307 0); // copy number 308 // 309 // Calorimeter 310 // 311 312 fSolidCalor = new G4Box("Calorimeter", fCalorThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 313 314 fLogicCalor = new G4LogicalVolume(fSolidCalor, fWorldMaterial, "Calorimeter"); 315 316 fPhysiCalor = new G4PVPlacement(0, // no rotation 317 G4ThreeVector(), // at (0,0,0) 318 fLogicCalor, // its fLogical volume 319 "Calorimeter", // its name 320 fLogicWorld, // its mother volume 321 false, // no boolean operation 322 0); // copy number 323 324 // 325 // Layers 326 // 327 328 fSolidLayer = new G4Box("Layer", fLayerThickness / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 329 330 fLogicLayer = new G4LogicalVolume(fSolidLayer, fWorldMaterial, "Layer"); 331 if (fNbOfLayers > 1) { 332 fPhysiLayer = 333 new G4PVReplica("Layer", fLogicLayer, fLogicCalor, kXAxis, fNbOfLayers, fLayerThickness); 334 } 335 else { 336 fPhysiLayer = 337 new G4PVPlacement(0, G4ThreeVector(), fLogicLayer, "Layer", fLogicCalor, false, 0); 338 } 339 // 340 // Absorbers 341 // 342 343 G4double xfront = -0.5 * fLayerThickness; 344 for (G4int k = 1; k <= fNbOfAbsor; ++k) { 345 fSolidAbsor[k] = new G4Box("Absorber", // its name 346 fAbsorThickness[k] / 2, fCalorSizeYZ / 2, fCalorSizeYZ / 2); 347 348 fLogicAbsor[k] = new G4LogicalVolume(fSolidAbsor[k], // its solid 349 fAbsorMaterial[k], // its material 350 fAbsorMaterial[k]->GetName()); 351 352 G4double xcenter = xfront + 0.5 * fAbsorThickness[k]; 353 xfront += fAbsorThickness[k]; 354 fPhysiAbsor[k] = new G4PVPlacement(0, G4ThreeVector(xcenter, 0., 0.), fLogicAbsor[k], 355 fAbsorMaterial[k]->GetName(), fLogicLayer, false, 356 k); // copy number 357 } 358 359 PrintCalorParameters(); 360 361 // always return the fPhysical World 362 // 363 return fPhysiWorld; 364 } 365 366 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 367 368 void DetectorConstruction::PrintCalorParameters() 369 { 370 G4cout << "\n-------------------------------------------------------------" 371 << "\n ---> The calorimeter is " << fNbOfLayers << " layers of:"; 372 for (G4int i = 1; i <= fNbOfAbsor; ++i) { 373 G4cout << "\n \t" << std::setw(12) << fAbsorMaterial[i]->GetName() << ": " << std::setw(6) 374 << G4BestUnit(fAbsorThickness[i], "Length"); 375 } 376 G4cout << "\n-------------------------------------------------------------\n"; 377 378 G4cout << "\n" << fWorldMaterial << G4endl; 379 for (G4int j = 1; j <= fNbOfAbsor; ++j) { 380 G4cout << "\n" << fAbsorMaterial[j] << G4endl; 381 } 382 G4cout << "\n-------------------------------------------------------------\n"; 383 } 384 385 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 386 387 void DetectorConstruction::SetWorldMaterial(const G4String& material) 388 { 389 // search the material by its name 390 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material); 391 if (pttoMaterial) { 392 fWorldMaterial = pttoMaterial; 393 if (fLogicWorld) { 394 fLogicWorld->SetMaterial(fWorldMaterial); 395 fLogicLayer->SetMaterial(fWorldMaterial); 396 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 397 } 398 } 399 } 400 401 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 402 403 void DetectorConstruction::SetNbOfLayers(G4int ival) 404 { 405 // set the number of Layers 406 // 407 if (ival < 1) { 408 G4cout << "\n --->warning from SetfNbOfLayers: " << ival 409 << " must be at least 1. Command refused" << G4endl; 410 return; 411 } 412 fNbOfLayers = ival; 413 } 414 415 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 416 417 void DetectorConstruction::SetNbOfAbsor(G4int ival) 418 { 419 // set the number of Absorbers 420 // 421 if (ival < 1 || ival > (kMaxAbsor - 1)) { 422 G4cout << "\n ---> warning from SetfNbOfAbsor: " << ival << " must be at least 1 and and most " 423 << kMaxAbsor - 1 << ". Command refused" << G4endl; 424 return; 425 } 426 fNbOfAbsor = ival; 427 } 428 429 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 430 431 void DetectorConstruction::SetAbsorMaterial(G4int ival, const G4String& material) 432 { 433 // search the material by its name 434 // 435 if (ival > fNbOfAbsor || ival <= 0) { 436 G4cout << "\n --->warning from SetAbsorMaterial: absor number " << ival 437 << " out of range. Command refused" << G4endl; 438 return; 439 } 440 441 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(material); 442 if (pttoMaterial) { 443 fAbsorMaterial[ival] = pttoMaterial; 444 if (fLogicAbsor[ival]) { 445 fLogicAbsor[ival]->SetMaterial(pttoMaterial); 446 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 447 } 448 } 449 } 450 451 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 452 453 void DetectorConstruction::SetAbsorThickness(G4int ival, G4double val) 454 { 455 // change Absorber thickness 456 // 457 if (ival > fNbOfAbsor || ival <= 0) { 458 G4cout << "\n --->warning from SetAbsorThickness: absor number " << ival 459 << " out of range. Command refused" << G4endl; 460 return; 461 } 462 if (val <= DBL_MIN) { 463 G4cout << "\n --->warning from SetAbsorThickness: thickness " << val 464 << " out of range. Command refused" << G4endl; 465 return; 466 } 467 fAbsorThickness[ival] = val; 468 } 469 470 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 471 472 void DetectorConstruction::SetCalorSizeYZ(G4double val) 473 { 474 // change the transverse size 475 // 476 if (val <= DBL_MIN) { 477 G4cout << "\n --->warning from SetfCalorSizeYZ: thickness " << val 478 << " out of range. Command refused" << G4endl; 479 return; 480 } 481 fCalorSizeYZ = val; 482 } 483 484 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 485 486 #include "G4AutoDelete.hh" 487 #include "G4GlobalMagFieldMessenger.hh" 488 489 void DetectorConstruction::ConstructSDandField() 490 { 491 if (fFieldMessenger.Get() == nullptr) { 492 // Create global magnetic field messenger. 493 // Uniform magnetic field is then created automatically if 494 // the field value is not zero. 495 G4ThreeVector fieldValue = G4ThreeVector(); 496 G4GlobalMagFieldMessenger* msg = new G4GlobalMagFieldMessenger(fieldValue); 497 // msg->SetVerboseLevel(1); 498 G4AutoDelete::Register(msg); 499 fFieldMessenger.Put(msg); 500 } 501 } 502 503 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 504