Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/medical/electronScattering2/src/ElectronBenchmarkDetector.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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