Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 /// \file DetectorConstruction.cc 26 /// \file DetectorConstruction.cc 27 /// \brief Implementation of the DetectorConst 27 /// \brief Implementation of the DetectorConstruction class 28 // 28 // >> 29 // $Id: DetectorConstruction.cc 77210 2013-11-22 01:58:38Z adotti $ 29 // 30 // 30 //....oooOO0OOooo........oooOO0OOooo........oo << 31 ///////////////////////////////////////////////////////////////////////// 31 //....oooOO0OOooo........oooOO0OOooo........oo << 32 // >> 33 // DetectorConstruction >> 34 // >> 35 // Created: 20.06.2008 V.Ivanchenko >> 36 // >> 37 // Modified: >> 38 // >> 39 //////////////////////////////////////////////////////////////////////// >> 40 // 32 41 33 #include "DetectorConstruction.hh" 42 #include "DetectorConstruction.hh" 34 << 35 #include "DetectorMessenger.hh" 43 #include "DetectorMessenger.hh" 36 44 37 #include "G4Box.hh" << 45 #include "G4Tubs.hh" 38 #include "G4GeometryManager.hh" << 39 #include "G4LogicalVolume.hh" 46 #include "G4LogicalVolume.hh" 40 #include "G4LogicalVolumeStore.hh" << 41 #include "G4Material.hh" << 42 #include "G4NistManager.hh" << 43 #include "G4PVPlacement.hh" 47 #include "G4PVPlacement.hh" 44 #include "G4PVReplica.hh" << 48 45 #include "G4PhysicalConstants.hh" << 46 #include "G4PhysicalVolumeStore.hh" << 47 #include "G4RunManager.hh" 49 #include "G4RunManager.hh" >> 50 >> 51 #include "G4GeometryManager.hh" >> 52 #include "G4PhysicalVolumeStore.hh" >> 53 #include "G4LogicalVolumeStore.hh" 48 #include "G4SolidStore.hh" 54 #include "G4SolidStore.hh" 49 #include "G4SystemOfUnits.hh" << 55 >> 56 #include "G4VisAttributes.hh" >> 57 #include "G4Colour.hh" >> 58 50 #include "G4UnitsTable.hh" 59 #include "G4UnitsTable.hh" >> 60 #include "G4ios.hh" 51 61 52 #include <iomanip> << 62 #include "G4NistManager.hh" >> 63 >> 64 #include "G4PhysicalConstants.hh" >> 65 #include "G4SystemOfUnits.hh" 53 66 54 //....oooOO0OOooo........oooOO0OOooo........oo 67 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 55 68 56 DetectorConstruction::DetectorConstruction() 69 DetectorConstruction::DetectorConstruction() >> 70 : G4VUserDetectorConstruction(), >> 71 fTargetMaterial(0), fWorldMaterial(0), >> 72 fLogicTarget(0), fLogicWorld(0), >> 73 fDetectorMessenger(0) 57 { 74 { 58 for (G4int i = 0; i < kMaxAbsor; ++i) { << 75 fDetectorMessenger = new DetectorMessenger(this); 59 fAbsorMaterial[i] = nullptr; << 60 fAbsorThickness[i] = 0.0; << 61 fSolidAbsor[i] = nullptr; << 62 fLogicAbsor[i] = nullptr; << 63 fPhysiAbsor[i] = nullptr; << 64 } << 65 76 66 // default parameter values of the calorimet << 77 fRadius = 5.*cm; 67 fNbOfAbsor = 2; << 78 fLength = 10.*cm; 68 fAbsorThickness[1] = 36 * mm; << 69 fAbsorThickness[2] = 4 * mm; << 70 fNbOfLayers = 50; << 71 fCalorSizeYZ = 1.5 * m; << 72 ComputeCalorParameters(); << 73 << 74 // materials << 75 DefineMaterials(); << 76 SetWorldMaterial("Galactic"); << 77 SetAbsorMaterial(1, "Iron"); << 78 SetAbsorMaterial(2, "Scintillator"); << 79 79 80 // create commands for interactive definitio << 80 fTargetMaterial = G4NistManager::Instance()->FindOrBuildMaterial("G4_Al"); 81 fDetectorMessenger = new DetectorMessenger(t << 81 fWorldMaterial = >> 82 G4NistManager::Instance()->FindOrBuildMaterial("G4_Galactic"); 82 } 83 } 83 84 84 //....oooOO0OOooo........oooOO0OOooo........oo 85 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 85 86 86 DetectorConstruction::~DetectorConstruction() 87 DetectorConstruction::~DetectorConstruction() 87 { << 88 { 88 delete fDetectorMessenger; 89 delete fDetectorMessenger; 89 } 90 } 90 91 91 //....oooOO0OOooo........oooOO0OOooo........oo << 92 << 93 void DetectorConstruction::DefineMaterials() << 94 { << 95 // This function illustrates the possible wa << 96 // G4 database on G4Elements << 97 G4NistManager* manager = G4NistManager::Inst << 98 manager->SetVerbose(0); << 99 // << 100 // define Elements << 101 // << 102 G4Element* H = manager->FindOrBuildElement(1 << 103 G4Element* C = manager->FindOrBuildElement(6 << 104 G4Element* O = manager->FindOrBuildElement(8 << 105 // << 106 // define an Element from isotopes, by relat << 107 // << 108 G4int iz, n; // iz=number of protons in an << 109 // n=number of nucleons in an << 110 G4int ncomponents; << 111 G4double z, a; << 112 G4double abundance; << 113 << 114 G4Isotope* U5 = new G4Isotope("U235", iz = 9 << 115 G4Isotope* U8 = new G4Isotope("U238", iz = 9 << 116 << 117 G4Element* U = new G4Element("enriched Urani << 118 U->AddIsotope(U5, abundance = 90. * perCent) << 119 U->AddIsotope(U8, abundance = 10. * perCent) << 120 << 121 // << 122 // define simple materials << 123 // << 124 G4double density; << 125 << 126 new G4Material("liquidH2", z = 1., a = 1.008 << 127 new G4Material("Aluminium", z = 13., a = 26. << 128 new G4Material("liquidArgon", z = 18, a = 39 << 129 new G4Material("Titanium", z = 22., a = 47.8 << 130 new G4Material("Iron", z = 26., a = 55.85 * << 131 new G4Material("Copper", z = 29., a = 63.55 << 132 new G4Material("Tungsten", z = 74., a = 183. << 133 new G4Material("Gold", z = 79., a = 196.97 * << 134 new G4Material("Lead", z = 82., a = 207.20 * << 135 new G4Material("Uranium", z = 92., a = 238.0 << 136 << 137 // << 138 // define a material from elements. case 1 << 139 // << 140 G4int natoms; << 141 << 142 G4Material* H2O = new G4Material("Water", de << 143 H2O->AddElement(H, natoms = 2); << 144 H2O->AddElement(O, natoms = 1); << 145 H2O->GetIonisation()->SetMeanExcitationEnerg << 146 H2O->SetChemicalFormula("H_2O"); << 147 << 148 G4Material* CH = new G4Material("Polystyrene << 149 CH->AddElement(C, natoms = 1); << 150 CH->AddElement(H, natoms = 1); << 151 << 152 G4Material* Sci = new G4Material("Scintillat << 153 Sci->AddElement(C, natoms = 9); << 154 Sci->AddElement(H, natoms = 10); << 155 << 156 Sci->GetIonisation()->SetBirksConstant(0.126 << 157 << 158 // << 159 // examples of gas in non STP conditions << 160 // << 161 G4double temperature, pressure; << 162 << 163 G4Material* CO2 = << 164 new G4Material("CarbonicGas", density = 27 << 165 temperature = 325. * kelvin << 166 CO2->AddElement(C, natoms = 1); << 167 CO2->AddElement(O, natoms = 2); << 168 << 169 new G4Material("ArgonGas", z = 18, a = 39.94 << 170 273.15 * kelvin, 1 * atmosphe << 171 // << 172 // example of vacuum << 173 // << 174 density = universe_mean_density; // from Ph << 175 pressure = 3.e-18 * pascal; << 176 temperature = 2.73 * kelvin; << 177 new G4Material("Galactic", z = 1., a = 1.008 << 178 pressure); << 179 << 180 // G4cout << *(G4Material::GetMaterialTable << 181 } << 182 << 183 //....oooOO0OOooo........oooOO0OOooo........oo << 184 << 185 G4Material* DetectorConstruction::MaterialWith << 186 << 187 { << 188 // define a material from an isotope << 189 // << 190 G4int ncomponents; << 191 G4double abundance, massfraction; << 192 << 193 G4Isotope* isotope = new G4Isotope(symbol, Z << 194 << 195 G4Element* element = new G4Element(name, sym << 196 element->AddIsotope(isotope, abundance = 100 << 197 << 198 G4Material* material = new G4Material(name, << 199 material->AddElement(element, massfraction = << 200 << 201 return material; << 202 } << 203 << 204 //....oooOO0OOooo........oooOO0OOooo........oo << 205 << 206 void DetectorConstruction::ComputeCalorParamet << 207 { << 208 // Compute derived parameters of the calorim << 209 fLayerThickness = 0.; << 210 for (G4int iAbs = 1; iAbs <= fNbOfAbsor; iAb << 211 fLayerThickness += fAbsorThickness[iAbs]; << 212 } << 213 fCalorThickness = fNbOfLayers * fLayerThickn << 214 fWorldSizeX = 1.2 * fCalorThickness; << 215 fWorldSizeYZ = 1.2 * fCalorSizeYZ; << 216 } << 217 << 218 //....oooOO0OOooo........oooOO0OOooo........oo << 219 << 220 G4VPhysicalVolume* DetectorConstruction::Const 92 G4VPhysicalVolume* DetectorConstruction::Construct() 221 { 93 { 222 if (fPhysiWorld) { << 94 // Cleanup old geometry 223 return fPhysiWorld; << 224 } << 225 // complete the Calor parameters definition << 226 ComputeCalorParameters(); << 227 95 228 // << 96 G4GeometryManager::GetInstance()->OpenGeometry(); 229 // World << 97 G4PhysicalVolumeStore::GetInstance()->Clean(); 230 // << 98 G4LogicalVolumeStore::GetInstance()->Clean(); 231 fSolidWorld = new G4Box("World", // its nam << 99 G4SolidStore::GetInstance()->Clean(); 232 fWorldSizeX / 2, fWo << 100 >> 101 // Sizes >> 102 G4double worldR = fRadius + cm; >> 103 G4double worldZ = fLength + cm; 233 104 234 fLogicWorld = new G4LogicalVolume(fSolidWorl << 235 fWorldMate << 236 "World"); << 237 << 238 fPhysiWorld = new G4PVPlacement(0, // no ro << 239 G4ThreeVecto << 240 fLogicWorld, << 241 "World", // << 242 0, // its m << 243 false, // n << 244 0); // copy << 245 // << 246 // Calorimeter << 247 // 105 // 248 << 106 // World 249 fSolidCalor = new G4Box("Calorimeter", fCalo << 250 << 251 fLogicCalor = new G4LogicalVolume(fSolidCalo << 252 << 253 fPhysiCalor = new G4PVPlacement(0, // no ro << 254 G4ThreeVecto << 255 fLogicCalor, << 256 "Calorimeter << 257 fLogicWorld, << 258 false, // n << 259 0); // copy << 260 << 261 // << 262 // Layers << 263 // 107 // >> 108 G4Tubs* solidW = new G4Tubs("World", 0., worldR, 0.5*worldZ, 0., twopi); >> 109 fLogicWorld = new G4LogicalVolume(solidW, fWorldMaterial,"World"); >> 110 G4VPhysicalVolume* world = new G4PVPlacement(0, G4ThreeVector(), >> 111 fLogicWorld, "World", >> 112 0, false, 0); 264 113 265 fSolidLayer = new G4Box("Layer", fLayerThick << 266 << 267 fLogicLayer = new G4LogicalVolume(fSolidLaye << 268 if (fNbOfLayers > 1) { << 269 fPhysiLayer = << 270 new G4PVReplica("Layer", fLogicLayer, fL << 271 } << 272 else { << 273 fPhysiLayer = << 274 new G4PVPlacement(0, G4ThreeVector(), fL << 275 } << 276 // 114 // 277 // Absorbers << 115 // Target volume 278 // 116 // >> 117 G4Tubs* solidA = new G4Tubs("Target", 0., fRadius, 0.5*fLength, 0.,twopi); >> 118 fLogicTarget = new G4LogicalVolume( solidA, fTargetMaterial, "Target"); >> 119 new G4PVPlacement(0, G4ThreeVector(), fLogicTarget, "Target", >> 120 fLogicWorld, false, 0); 279 121 280 G4double xfront = -0.5 * fLayerThickness; << 122 G4cout << "### Target consist of " 281 for (G4int k = 1; k <= fNbOfAbsor; ++k) { << 123 << fTargetMaterial->GetName() 282 fSolidAbsor[k] = new G4Box("Absorber", // << 124 << " disks with R(mm)= " << fRadius/mm 283 fAbsorThickness << 125 << " fLength(mm)= " << fLength/mm 284 << 126 << " ###" << G4endl; 285 fLogicAbsor[k] = new G4LogicalVolume(fSoli << 286 fAbso << 287 fAbso << 288 << 289 G4double xcenter = xfront + 0.5 * fAbsorTh << 290 xfront += fAbsorThickness[k]; << 291 fPhysiAbsor[k] = new G4PVPlacement(0, G4Th << 292 fAbsorM << 293 k); // << 294 } << 295 127 296 PrintCalorParameters(); << 128 // colors 297 << 129 fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible()); 298 // always return the fPhysical World << 299 // << 300 return fPhysiWorld; << 301 } << 302 << 303 //....oooOO0OOooo........oooOO0OOooo........oo << 304 << 305 void DetectorConstruction::PrintCalorParameter << 306 { << 307 G4int prec = 4, wid = prec + 2; << 308 G4int dfprec = G4cout.precision(prec); << 309 130 310 G4double totLength(0.), totRadl(0.), totNucl << 131 G4VisAttributes* regCcolor = new G4VisAttributes(G4Colour(0., 0.3, 0.7)); >> 132 fLogicTarget->SetVisAttributes(regCcolor); 311 133 312 G4cout << "\n------------------------------- << 134 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 313 << "\n ---> The calorimeter is " << f << 314 for (G4int i = 1; i <= fNbOfAbsor; ++i) { << 315 G4Material* material = fAbsorMaterial[i]; << 316 G4double radl = material->GetRadlen(); << 317 G4double nuclearl = material->GetNuclearIn << 318 G4double sumThickness = fNbOfLayers * fAbs << 319 G4double nbRadl = sumThickness / radl; << 320 G4double nbNuclearl = sumThickness / nucle << 321 totLength += sumThickness; << 322 totRadl += nbRadl; << 323 totNuclear += nbNuclearl; << 324 G4cout << "\n " << std::setw(12) << fAbs << 325 << G4BestUnit(fAbsorThickness[i], " << 326 << G4BestUnit(sumThickness, "Length << 327 << " = " << std::setw(wid) << nbNuc << 328 } << 329 G4cout << "\n\n total << 330 << G4BestUnit(totLength, "Length") << << 331 << " = " << std::setw(wid) << totNucl << 332 << 333 G4cout << " transverse s << 334 << G4BestUnit(fCalorSizeYZ, "Length") << 335 G4cout << "--------------------------------- << 336 << 337 G4cout << "\n" << fWorldMaterial << G4endl; << 338 for (G4int j = 1; j <= fNbOfAbsor; ++j) { << 339 G4cout << "\n" << fAbsorMaterial[j] << G4e << 340 } << 341 G4cout << "\n------------------------------- << 342 135 343 // restore default format << 136 return world; 344 G4cout.precision(dfprec); << 345 } 137 } 346 138 347 //....oooOO0OOooo........oooOO0OOooo........oo 139 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 348 140 349 void DetectorConstruction::SetWorldMaterial(co << 141 void DetectorConstruction::SetTargetMaterial(const G4String& mat) 350 { 142 { 351 // search the material by its name 143 // search the material by its name 352 G4Material* pttoMaterial = G4NistManager::In << 144 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(mat); 353 if (pttoMaterial) { << 354 fWorldMaterial = pttoMaterial; << 355 if (fLogicWorld) { << 356 fLogicWorld->SetMaterial(fWorldMaterial) << 357 fLogicLayer->SetMaterial(fWorldMaterial) << 358 G4RunManager::GetRunManager()->PhysicsHa << 359 } << 360 } << 361 } << 362 << 363 //....oooOO0OOooo........oooOO0OOooo........oo << 364 << 365 void DetectorConstruction::SetNbOfLayers(G4int << 366 { << 367 // set the number of Layers << 368 // << 369 if (ival < 1) { << 370 G4cout << "\n --->warning from SetfNbOfLay << 371 << " must be at least 1. Command re << 372 return; << 373 } << 374 fNbOfLayers = ival; << 375 } << 376 << 377 //....oooOO0OOooo........oooOO0OOooo........oo << 378 145 379 void DetectorConstruction::SetNbOfAbsor(G4int << 146 if (material && material != fTargetMaterial) { 380 { << 147 fTargetMaterial = material; 381 // set the number of Absorbers << 148 if(fLogicTarget) fLogicTarget->SetMaterial(fTargetMaterial); 382 // << 149 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 383 if (ival < 1 || ival > (kMaxAbsor - 1)) { << 384 G4cout << "\n ---> warning from SetfNbOfAb << 385 << kMaxAbsor - 1 << ". Command refu << 386 return; << 387 } 150 } 388 fNbOfAbsor = ival; << 389 } 151 } 390 152 391 //....oooOO0OOooo........oooOO0OOooo........oo 153 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 392 154 393 void DetectorConstruction::SetAbsorMaterial(G4 << 155 void DetectorConstruction::SetWorldMaterial(const G4String& mat) 394 { 156 { 395 // search the material by its name 157 // search the material by its name 396 // << 158 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(mat); 397 if (ival > fNbOfAbsor || ival <= 0) { << 398 G4cout << "\n --->warning from SetAbsorMat << 399 << " out of range. Command refused" << 400 return; << 401 } << 402 159 403 G4Material* pttoMaterial = G4NistManager::In << 160 if (material && material != fWorldMaterial) { 404 if (pttoMaterial) { << 161 fWorldMaterial = material; 405 fAbsorMaterial[ival] = pttoMaterial; << 162 if(fLogicWorld) fLogicWorld->SetMaterial(fWorldMaterial); 406 if (fLogicAbsor[ival]) { << 163 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 407 fLogicAbsor[ival]->SetMaterial(pttoMater << 408 G4RunManager::GetRunManager()->PhysicsHa << 409 } << 410 } 164 } 411 } 165 } 412 166 413 //....oooOO0OOooo........oooOO0OOooo........oo << 167 void DetectorConstruction::SetTargetRadius(G4double val) 414 << 415 void DetectorConstruction::SetAbsorThickness(G << 416 { 168 { 417 // change Absorber thickness << 169 if(val > 0.0 && val != fRadius) { 418 // << 170 fRadius = val; 419 if (ival > fNbOfAbsor || ival <= 0) { << 171 G4RunManager::GetRunManager()->ReinitializeGeometry(); 420 G4cout << "\n --->warning from SetAbsorThi << 172 } 421 << " out of range. Command refused" << 422 return; << 423 } << 424 if (val <= DBL_MIN) { << 425 G4cout << "\n --->warning from SetAbsorThi << 426 << " out of range. Command refused" << 427 return; << 428 } << 429 fAbsorThickness[ival] = val; << 430 } 173 } 431 174 432 //....oooOO0OOooo........oooOO0OOooo........oo 175 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 433 176 434 void DetectorConstruction::SetCalorSizeYZ(G4do << 177 void DetectorConstruction::SetTargetLength(G4double val) 435 { 178 { 436 // change the transverse size << 179 if(val > 0.0 && val != fLength) { 437 // << 180 fLength = val; 438 if (val <= DBL_MIN) { << 181 G4RunManager::GetRunManager()->ReinitializeGeometry(); 439 G4cout << "\n --->warning from SetfCalorSi << 182 } 440 << " out of range. Command refused" << 441 return; << 442 } << 443 fCalorSizeYZ = val; << 444 } << 445 << 446 //....oooOO0OOooo........oooOO0OOooo........oo << 447 << 448 #include "G4AutoDelete.hh" << 449 #include "G4GlobalMagFieldMessenger.hh" << 450 << 451 void DetectorConstruction::ConstructSDandField << 452 { << 453 if (fFieldMessenger.Get() == nullptr) { << 454 // Create global magnetic field messenger. << 455 // Uniform magnetic field is then created << 456 // the field value is not zero. << 457 G4ThreeVector fieldValue = G4ThreeVector() << 458 G4GlobalMagFieldMessenger* msg = new G4Glo << 459 // msg->SetVerboseLevel(1); << 460 G4AutoDelete::Register(msg); << 461 fFieldMessenger.Put(msg); << 462 } << 463 } 183 } 464 184 465 //....oooOO0OOooo........oooOO0OOooo........oo 185 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 466 186