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 medical/electronScattering2/src/ElectronBenchmarkDetector.cc 28 /// \brief Implementation of the ElectronBenchmarkDetector class 29 30 #include "ElectronBenchmarkDetector.hh" 31 32 #include "ElectronBenchmarkDetectorMessenger.hh" 33 34 #include "G4Colour.hh" 35 #include "G4GeometryManager.hh" 36 #include "G4LogicalVolume.hh" 37 #include "G4LogicalVolumeStore.hh" 38 #include "G4Material.hh" 39 #include "G4MultiFunctionalDetector.hh" 40 #include "G4NistManager.hh" 41 #include "G4PSCellFlux.hh" 42 #include "G4PSPopulation.hh" 43 #include "G4PVPlacement.hh" 44 #include "G4PVReplica.hh" 45 #include "G4PhysicalVolumeStore.hh" 46 #include "G4RunManager.hh" 47 #include "G4SDManager.hh" 48 #include "G4SDParticleFilter.hh" 49 #include "G4SolidStore.hh" 50 #include "G4SystemOfUnits.hh" 51 #include "G4Tubs.hh" 52 #include "G4UImanager.hh" 53 #include "G4VPrimitiveScorer.hh" 54 #include "G4VisAttributes.hh" 55 56 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 57 58 ElectronBenchmarkDetector::ElectronBenchmarkDetector() : G4VUserDetectorConstruction() 59 { 60 // Exit Window 61 fPosWindow0 = 0.000000 * cm; 62 fPosWindow1 = 0.004120 * cm; 63 64 // Scattering Foil 65 fPosPrimFoil = 2.650000 * cm; 66 fHalfThicknessPrimFoil = 0.0 * cm; 67 68 // Monitor Chamber 69 fPosMon0 = 5.000000 * cm; 70 fPosMon1 = 5.011270 * cm; 71 72 // Helium Bag 73 fPosBag0 = 6.497500 * cm; 74 fPosHelium0 = 6.500000 * cm; 75 fPosHelium1 = 116.500000 * cm; 76 fPosBag1 = 116.502500 * cm; 77 fThicknessRing = 1.4 * cm; 78 79 // Scoring Plane 80 fPosScorer = 118.200000 * cm; 81 fThicknessScorer = 0.001 * cm; 82 fWidthScorerRing = 0.1 * cm; 83 84 // Radii 85 fRadOverall = 23.3 * cm; 86 fRadRingInner = 20.0 * cm; 87 88 // Extra space remaining in world volume around apparatus 89 fPosDelta = 1. * cm; 90 fRadDelta = 0.1 * cm; 91 92 fMessenger = new ElectronBenchmarkDetectorMessenger(this); 93 DefineMaterials(); 94 } 95 96 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 97 98 ElectronBenchmarkDetector::~ElectronBenchmarkDetector() 99 { 100 delete fMessenger; 101 102 delete fWorldVisAtt; 103 delete fWindowVisAtt; 104 delete fPrimFoilVisAtt; 105 delete fMonVisAtt; 106 delete fBagVisAtt; 107 delete fHeliumVisAtt; 108 delete fRingVisAtt; 109 delete fScorerVisAtt; 110 } 111 112 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 113 114 G4VPhysicalVolume* ElectronBenchmarkDetector::Construct() 115 { 116 return CreateGeometry(); 117 } 118 119 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 120 121 void ElectronBenchmarkDetector::DefineMaterials() 122 { 123 // Use NIST database for elements and materials whereever possible. 124 G4NistManager* man = G4NistManager::Instance(); 125 man->SetVerbose(1); 126 127 // Take all elements and materials from NIST 128 man->FindOrBuildMaterial("G4_He"); 129 man->FindOrBuildMaterial("G4_Be"); 130 man->FindOrBuildMaterial("G4_Al"); 131 man->FindOrBuildMaterial("G4_Ti"); 132 man->FindOrBuildMaterial("G4_Ta"); 133 man->FindOrBuildMaterial("G4_AIR"); 134 man->FindOrBuildMaterial("G4_MYLAR"); 135 136 G4Element* C = man->FindOrBuildElement("C"); 137 G4Element* Cu = man->FindOrBuildElement("Cu"); 138 G4Element* Au = man->FindOrBuildElement("Au"); 139 G4Element* Ti = man->FindOrBuildElement("Ti"); 140 G4Element* Al = man->FindOrBuildElement("Al"); 141 G4Element* V = man->FindOrBuildElement("V"); 142 143 // Define materials not in NIST. 144 // While the NIST database does contain default materials for C, Cu and Au, 145 // those defaults have different densities than the ones used in the 146 // benchmark specification. 147 G4double density; 148 G4int ncomponents; 149 G4double fractionmass; 150 151 G4Material* G4_C = new G4Material("G4_C", density = 2.18 * g / cm3, ncomponents = 1); 152 G4_C->AddElement(C, fractionmass = 1.00); 153 154 G4Material* G4_Cu = new G4Material("G4_Cu", density = 8.92 * g / cm3, ncomponents = 1); 155 G4_Cu->AddElement(Cu, fractionmass = 1.00); 156 157 G4Material* G4_Au = new G4Material("G4_Au", density = 19.30 * g / cm3, ncomponents = 1); 158 G4_Au->AddElement(Au, fractionmass = 1.00); 159 160 G4Material* TiAlloy = new G4Material("TiAlloy", density = 4.42 * g / cm3, ncomponents = 3); 161 TiAlloy->AddElement(Ti, fractionmass = 0.90); 162 TiAlloy->AddElement(Al, fractionmass = 0.06); 163 TiAlloy->AddElement(V, fractionmass = 0.04); 164 165 // Print materials table 166 G4cout << *(G4Material::GetMaterialTable()) << G4endl; 167 } 168 169 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 170 171 G4VPhysicalVolume* ElectronBenchmarkDetector::CreateGeometry() 172 { 173 if (fPhysiWorld) return fPhysiWorld; 174 175 // Instantiate the world 176 fPhysiWorld = CreateWorld(); 177 fLogWorld = fPhysiWorld->GetLogicalVolume(); 178 179 // Instantiate the geometry 180 CreateExitWindow(fLogWorld); 181 CreatePrimaryFoil(fLogWorld); 182 CreateMonitor(fLogWorld); 183 CreateHeliumBag(fLogWorld); 184 185 // Create the scorers 186 CreateScorer(fLogWorld); 187 188 return fPhysiWorld; 189 } 190 191 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 192 193 G4VPhysicalVolume* ElectronBenchmarkDetector::CreateWorld() 194 { 195 G4double halfLengthWorld = fPosScorer / 2. + fPosDelta; 196 G4double radWorld = fRadOverall + fRadDelta; 197 G4VSolid* worldSolid = 198 new G4Tubs("WorldSolid", 0. * cm, radWorld, halfLengthWorld, 0. * deg, 360. * deg); 199 G4LogicalVolume* worldLog = 200 new G4LogicalVolume(worldSolid, G4Material::GetMaterial("G4_AIR"), "WorldLog"); 201 202 fWorldVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0)); 203 worldLog->SetVisAttributes(fWorldVisAtt); 204 205 G4VPhysicalVolume* worldPhys = 206 new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), worldLog, "World", 0, false, 0); 207 208 return worldPhys; 209 } 210 211 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 212 213 void ElectronBenchmarkDetector::CreateExitWindow(G4LogicalVolume* worldLog) 214 { 215 G4double halfLengthWorld = fPosScorer / 2.; 216 G4double halfThicknessWindow = fPosWindow1 / 2.; 217 G4VSolid* windowSolid = 218 new G4Tubs("windowSolid", 0. * cm, fRadOverall, halfThicknessWindow, 0. * deg, 360. * deg); 219 G4LogicalVolume* windowLog = 220 new G4LogicalVolume(windowSolid, G4Material::GetMaterial("TiAlloy"), "windowLog"); 221 222 fWindowVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 223 windowLog->SetVisAttributes(fWindowVisAtt); 224 225 new G4PVPlacement(0, G4ThreeVector(0., 0., halfThicknessWindow - halfLengthWorld), windowLog, 226 "ExitWindow", worldLog, false, 0); 227 } 228 229 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 230 231 void ElectronBenchmarkDetector::CreatePrimaryFoil(G4LogicalVolume* worldLog) 232 { 233 G4double halfLengthWorld = fPosScorer / 2.; 234 235 // For some energies, we have no Primary Foil. 236 if (fHalfThicknessPrimFoil == 0.) return; 237 238 fSolidPrimFoil = 239 new G4Tubs("PrimFoilSolid", 0. * cm, fRadOverall, fHalfThicknessPrimFoil, 0. * deg, 360. * deg); 240 fLogPrimFoil = new G4LogicalVolume(fSolidPrimFoil, fMaterialPrimFoil, "PrimFoilLog"); 241 242 fPrimFoilVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 243 fLogPrimFoil->SetVisAttributes(fPrimFoilVisAtt); 244 245 new G4PVPlacement(0, 246 G4ThreeVector(0., 0., fPosPrimFoil + fHalfThicknessPrimFoil - halfLengthWorld), 247 fLogPrimFoil, "ScatteringFoil", worldLog, false, 0); 248 } 249 250 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 251 252 void ElectronBenchmarkDetector::CreateMonitor(G4LogicalVolume* worldLog) 253 { 254 G4double halfLengthWorld = fPosScorer / 2.; 255 G4double halfThicknessMon = (fPosMon1 - fPosMon0) / 2.; 256 G4VSolid* monSolid = 257 new G4Tubs("monSolid", 0. * cm, fRadOverall, halfThicknessMon, 0. * deg, 360. * deg); 258 G4LogicalVolume* monLog = 259 new G4LogicalVolume(monSolid, G4Material::GetMaterial("G4_MYLAR"), "monLog"); 260 261 fMonVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 262 monLog->SetVisAttributes(fMonVisAtt); 263 264 new G4PVPlacement(0, G4ThreeVector(0., 0., fPosMon0 + halfThicknessMon - halfLengthWorld), monLog, 265 "MonitorChamber", worldLog, false, 0); 266 } 267 268 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 269 270 void ElectronBenchmarkDetector::CreateHeliumBag(G4LogicalVolume* worldLog) 271 { 272 G4double halfLengthWorld = fPosScorer / 2.; 273 274 // Construct cylinder of Mylar 275 G4double halfThicknessBag = (fPosBag1 - fPosBag0) / 2.; 276 G4VSolid* bagSolid = 277 new G4Tubs("bagSolid", 0. * cm, fRadOverall, halfThicknessBag, 0. * deg, 360. * deg); 278 G4LogicalVolume* bagLog = 279 new G4LogicalVolume(bagSolid, G4Material::GetMaterial("G4_MYLAR"), "bagLog"); 280 281 fBagVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 282 bagLog->SetVisAttributes(fBagVisAtt); 283 284 new G4PVPlacement(0, G4ThreeVector(0., 0., fPosBag0 + halfThicknessBag - halfLengthWorld), bagLog, 285 "HeliumBag", worldLog, false, 0); 286 287 // Insert cylinder of Helium into the Cylinder of Mylar 288 G4double halfThicknessHelium = (fPosHelium1 - fPosHelium0) / 2.; 289 G4VSolid* heliumSolid = 290 new G4Tubs("heliumSolid", 0. * cm, fRadOverall, halfThicknessHelium, 0. * deg, 360. * deg); 291 G4LogicalVolume* heliumLog = 292 new G4LogicalVolume(heliumSolid, G4Material::GetMaterial("G4_He"), "heliumLog"); 293 294 fHeliumVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 295 heliumLog->SetVisAttributes(fHeliumVisAtt); 296 297 new G4PVPlacement(0, G4ThreeVector(0., 0., 0.), heliumLog, "Helium", bagLog, false, 0); 298 299 // Insert two rings of Aluminum into the Cylinder of Helium 300 G4double halfThicknessRing = fThicknessRing / 2.; 301 G4VSolid* ringSolid = 302 new G4Tubs("ringSolid", fRadRingInner, fRadOverall, halfThicknessRing, 0. * deg, 360. * deg); 303 G4LogicalVolume* ring0Log = 304 new G4LogicalVolume(ringSolid, G4Material::GetMaterial("G4_Al"), "ring0Log"); 305 G4LogicalVolume* ring1Log = 306 new G4LogicalVolume(ringSolid, G4Material::GetMaterial("G4_Al"), "ring1Log"); 307 308 fRingVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 309 ring0Log->SetVisAttributes(fRingVisAtt); 310 ring1Log->SetVisAttributes(fRingVisAtt); 311 312 new G4PVPlacement(0, G4ThreeVector(0., 0., -halfThicknessHelium + halfThicknessRing), ring0Log, 313 "Ring0", heliumLog, false, 0); 314 315 new G4PVPlacement(0, G4ThreeVector(0., 0., halfThicknessHelium - halfThicknessRing), ring1Log, 316 "Ring1", heliumLog, false, 0); 317 } 318 319 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 320 321 void ElectronBenchmarkDetector::CreateScorer(G4LogicalVolume* worldLog) 322 { 323 G4double halfLengthWorld = fPosScorer / 2.; 324 G4double halfThicknessScorer = fThicknessScorer / 2.; 325 326 G4VSolid* scorerSolid = 327 new G4Tubs("scorerSolid", 0. * cm, fRadOverall, halfThicknessScorer, 0. * deg, 360. * deg); 328 G4LogicalVolume* scorerLog = 329 new G4LogicalVolume(scorerSolid, G4Material::GetMaterial("G4_AIR"), "scorerLog"); 330 331 fScorerVisAtt = new G4VisAttributes(G4Colour(0.5, 1.0, 0.5)); 332 scorerLog->SetVisAttributes(fScorerVisAtt); 333 new G4PVPlacement(0, G4ThreeVector(0., 0., halfLengthWorld - halfThicknessScorer), scorerLog, 334 "Scorer", worldLog, false, 0); 335 336 G4VSolid* scorerRingSolid = 337 new G4Tubs("scorerRingSolid", 0. * cm, fRadOverall, halfThicknessScorer, 0. * deg, 360. * deg); 338 fScorerRingLog = 339 new G4LogicalVolume(scorerRingSolid, G4Material::GetMaterial("G4_AIR"), "scorerRingLog"); 340 new G4PVReplica("ScorerRing", fScorerRingLog, scorerLog, kRho, 341 G4int(fRadOverall / fWidthScorerRing), fWidthScorerRing); 342 } 343 344 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 345 346 // Note that this method is called both at start of job and again after 347 // any command causes a change to detector geometry 348 void ElectronBenchmarkDetector::ConstructSDandField() 349 { 350 G4SDManager::GetSDMpointer()->SetVerboseLevel(1); 351 352 // G4Cache mechanism is necessary for multi-threaded operation 353 // as it allows us to store separate detector pointer per thread 354 G4MultiFunctionalDetector*& sensitiveDetector = fSensitiveDetectorCache.Get(); 355 356 if (!sensitiveDetector) { 357 sensitiveDetector = new G4MultiFunctionalDetector("MyDetector"); 358 359 G4VPrimitiveScorer* primitive; 360 361 G4SDParticleFilter* electronFilter = new G4SDParticleFilter("electronFilter", "e-"); 362 363 primitive = new G4PSCellFlux("cell flux"); 364 sensitiveDetector->RegisterPrimitive(primitive); 365 366 primitive = new G4PSCellFlux("e cell flux"); 367 primitive->SetFilter(electronFilter); 368 sensitiveDetector->RegisterPrimitive(primitive); 369 370 primitive = new G4PSPopulation("population"); 371 sensitiveDetector->RegisterPrimitive(primitive); 372 373 primitive = new G4PSPopulation("e population"); 374 primitive->SetFilter(electronFilter); 375 sensitiveDetector->RegisterPrimitive(primitive); 376 } 377 G4SDManager::GetSDMpointer()->AddNewDetector(sensitiveDetector); 378 fScorerRingLog->SetSensitiveDetector(sensitiveDetector); 379 } 380 381 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 382 383 void ElectronBenchmarkDetector::SetPrimFoilMaterial(const G4String& matname) 384 { 385 G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(matname); 386 387 if (material && material != fMaterialPrimFoil) { 388 fMaterialPrimFoil = material; 389 if (fLogPrimFoil) { 390 fLogPrimFoil->SetMaterial(fMaterialPrimFoil); 391 } 392 G4RunManager::GetRunManager()->PhysicsHasBeenModified(); 393 } 394 } 395 396 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 397 398 void ElectronBenchmarkDetector::SetPrimFoilThickness(G4double thicknessPrimFoil) 399 { 400 fHalfThicknessPrimFoil = thicknessPrimFoil / 2.; 401 } 402 403 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 404