Geant4  10.03
B5DetectorConstruction.cc
Go to the documentation of this file.
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 // $Id: B5DetectorConstruction.cc 101036 2016-11-04 09:00:23Z gcosmo $
27 //
30 
32 #include "B5MagneticField.hh"
34 #include "B5HodoscopeSD.hh"
35 #include "B5DriftChamberSD.hh"
36 #include "B5EmCalorimeterSD.hh"
37 #include "B5HadCalorimeterSD.hh"
38 
39 #include "G4FieldManager.hh"
41 #include "G4Mag_UsualEqRhs.hh"
42 #include "G4AutoDelete.hh"
43 
44 #include "G4Material.hh"
45 #include "G4Element.hh"
46 #include "G4MaterialTable.hh"
47 #include "G4NistManager.hh"
48 
49 #include "G4VSolid.hh"
50 #include "G4Box.hh"
51 #include "G4Tubs.hh"
52 #include "G4LogicalVolume.hh"
53 #include "G4VPhysicalVolume.hh"
54 #include "G4PVPlacement.hh"
55 #include "G4PVParameterised.hh"
56 #include "G4PVReplica.hh"
57 #include "G4UserLimits.hh"
58 
59 #include "G4SDManager.hh"
60 #include "G4VSensitiveDetector.hh"
61 #include "G4RunManager.hh"
62 #include "G4GenericMessenger.hh"
63 
64 #include "G4VisAttributes.hh"
65 #include "G4Colour.hh"
66 
67 #include "G4ios.hh"
68 #include "G4SystemOfUnits.hh"
69 
70 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
71 
74 
75 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
76 
79  fMessenger(nullptr),
80  fHodoscope1Logical(nullptr), fHodoscope2Logical(nullptr),
81  fWirePlane1Logical(nullptr), fWirePlane2Logical(nullptr),
82  fCellLogical(nullptr), fHadCalScintiLogical(nullptr),
83  fMagneticLogical(nullptr),
84  fVisAttributes(),
85  fArmAngle(30.*deg), fArmRotation(nullptr), fSecondArmPhys(nullptr)
86 
87 {
89  fArmRotation->rotateY(fArmAngle);
90 
91  // define commands for this class
93 }
94 
95 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
96 
98 {
99  delete fArmRotation;
100  delete fMessenger;
101 
102  for (auto visAttributes: fVisAttributes) {
103  delete visAttributes;
104  }
105 }
106 
107 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
108 
110 {
111  // Construct materials
113  auto air = G4Material::GetMaterial("G4_AIR");
114  //auto argonGas = G4Material::GetMaterial("B5_Ar");
115  auto argonGas = G4Material::GetMaterial("G4_Ar");
116  auto scintillator = G4Material::GetMaterial("G4_PLASTIC_SC_VINYLTOLUENE");
117  auto csI = G4Material::GetMaterial("G4_CESIUM_IODIDE");
118  auto lead = G4Material::GetMaterial("G4_Pb");
119 
120  // Option to switch on/off checking of volumes overlaps
121  //
122  G4bool checkOverlaps = true;
123 
124  // geometries --------------------------------------------------------------
125  // experimental hall (world volume)
126  auto worldSolid
127  = new G4Box("worldBox",10.*m,3.*m,10.*m);
128  auto worldLogical
129  = new G4LogicalVolume(worldSolid,air,"worldLogical");
130  auto worldPhysical
131  = new G4PVPlacement(0,G4ThreeVector(),worldLogical,"worldPhysical",0,
132  false,0,checkOverlaps);
133 
134  // Tube with Local Magnetic field
135 
136  auto magneticSolid
137  = new G4Tubs("magneticTubs",0.,1.*m,1.*m,0.,360.*deg);
138 
140  = new G4LogicalVolume(magneticSolid, air, "magneticLogical");
141 
142  // placement of Tube
143 
144  G4RotationMatrix* fieldRot = new G4RotationMatrix();
145  fieldRot->rotateX(90.*deg);
147  "magneticPhysical",worldLogical,
148  false,0,checkOverlaps);
149 
150  // set step limit in tube with magnetic field
151  G4UserLimits* userLimits = new G4UserLimits(1*m);
152  fMagneticLogical->SetUserLimits(userLimits);
153 
154  // first arm
155  auto firstArmSolid
156  = new G4Box("firstArmBox",1.5*m,1.*m,3.*m);
157  auto firstArmLogical
158  = new G4LogicalVolume(firstArmSolid,air,"firstArmLogical");
159  new G4PVPlacement(0,G4ThreeVector(0.,0.,-5.*m),firstArmLogical,
160  "firstArmPhysical",worldLogical,
161  false,0,checkOverlaps);
162 
163  // second arm
164  auto secondArmSolid
165  = new G4Box("secondArmBox",2.*m,2.*m,3.5*m);
166  auto secondArmLogical
167  = new G4LogicalVolume(secondArmSolid,air,"secondArmLogical");
168  auto x = -5.*m * std::sin(fArmAngle);
169  auto z = 5.*m * std::cos(fArmAngle);
171  = new G4PVPlacement(fArmRotation,G4ThreeVector(x,0.,z),secondArmLogical,
172  "fSecondArmPhys",worldLogical,
173  false,0,checkOverlaps);
174 
175  // hodoscopes in first arm
176  auto hodoscope1Solid
177  = new G4Box("hodoscope1Box",5.*cm,20.*cm,0.5*cm);
179  = new G4LogicalVolume(hodoscope1Solid,scintillator,"hodoscope1Logical");
180 
181  for (auto i=0;i<kNofHodoscopes1;i++) {
182  G4double x1 = (i-kNofHodoscopes1/2)*10.*cm;
184  "hodoscope1Physical",firstArmLogical,
185  false,i,checkOverlaps);
186  }
187 
188  // drift chambers in first arm
189  auto chamber1Solid
190  = new G4Box("chamber1Box",1.*m,30.*cm,1.*cm);
191  auto chamber1Logical
192  = new G4LogicalVolume(chamber1Solid,argonGas,"chamber1Logical");
193 
194  for (auto i=0;i<kNofChambers;i++) {
195  G4double z1 = (i-kNofChambers/2)*0.5*m;
196  new G4PVPlacement(0,G4ThreeVector(0.,0.,z1),chamber1Logical,
197  "chamber1Physical",firstArmLogical,
198  false,i,checkOverlaps);
199  }
200 
201  // "virtual" wire plane
202  auto wirePlane1Solid
203  = new G4Box("wirePlane1Box",1.*m,30.*cm,0.1*mm);
205  = new G4LogicalVolume(wirePlane1Solid,argonGas,"wirePlane1Logical");
207  "wirePlane1Physical",chamber1Logical,
208  false,0,checkOverlaps);
209 
210  // hodoscopes in second arm
211  auto hodoscope2Solid
212  = new G4Box("hodoscope2Box",5.*cm,20.*cm,0.5*cm);
214  = new G4LogicalVolume(hodoscope2Solid,scintillator,"hodoscope2Logical");
215 
216  for (auto i=0;i<kNofHodoscopes2;i++) {
217  G4double x2 = (i-kNofHodoscopes2/2)*10.*cm;
219  "hodoscope2Physical",secondArmLogical,
220  false,i,checkOverlaps);
221  }
222 
223  // drift chambers in second arm
224  auto chamber2Solid
225  = new G4Box("chamber2Box",1.5*m,30.*cm,1.*cm);
226  auto chamber2Logical
227  = new G4LogicalVolume(chamber2Solid,argonGas,"chamber2Logical");
228 
229  for (auto i=0;i<kNofChambers;i++) {
230  G4double z2 = (i-kNofChambers/2)*0.5*m - 1.5*m;
231  new G4PVPlacement(0,G4ThreeVector(0.,0.,z2),chamber2Logical,
232  "chamber2Physical",secondArmLogical,
233  false,i,checkOverlaps);
234  }
235 
236  // "virtual" wire plane
237  auto wirePlane2Solid
238  = new G4Box("wirePlane2Box",1.5*m,30.*cm,0.1*mm);
240  = new G4LogicalVolume(wirePlane2Solid,argonGas,"wirePlane2Logical");
242  "wirePlane2Physical",chamber2Logical,
243  false,0,checkOverlaps);
244 
245  // CsI calorimeter
246  auto emCalorimeterSolid
247  = new G4Box("EMcalorimeterBox",1.5*m,30.*cm,15.*cm);
248  auto emCalorimeterLogical
249  = new G4LogicalVolume(emCalorimeterSolid,csI,"EMcalorimeterLogical");
250  new G4PVPlacement(0,G4ThreeVector(0.,0.,2.*m),emCalorimeterLogical,
251  "EMcalorimeterPhysical",secondArmLogical,
252  false,0,checkOverlaps);
253 
254  // EMcalorimeter cells
255  auto cellSolid
256  = new G4Box("cellBox",7.5*cm,7.5*cm,15.*cm);
258  = new G4LogicalVolume(cellSolid,csI,"cellLogical");
260  new G4PVParameterised("cellPhysical",fCellLogical,emCalorimeterLogical,
261  kXAxis,kNofEmCells,cellParam);
262 
263  // hadron calorimeter
264  auto hadCalorimeterSolid
265  = new G4Box("HadCalorimeterBox",1.5*m,30.*cm,50.*cm);
266  auto hadCalorimeterLogical
267  = new G4LogicalVolume(hadCalorimeterSolid,lead,"HadCalorimeterLogical");
268  new G4PVPlacement(0,G4ThreeVector(0.,0.,3.*m),hadCalorimeterLogical,
269  "HadCalorimeterPhysical",secondArmLogical,
270  false,0,checkOverlaps);
271 
272  // hadron calorimeter column
273  auto HadCalColumnSolid
274  = new G4Box("HadCalColumnBox",15.*cm,30.*cm,50.*cm);
275  auto HadCalColumnLogical
276  = new G4LogicalVolume(HadCalColumnSolid,lead,"HadCalColumnLogical");
277  new G4PVReplica("HadCalColumnPhysical",HadCalColumnLogical,
278  hadCalorimeterLogical,kXAxis,kNofHadColumns,30.*cm);
279 
280  // hadron calorimeter cell
281  auto HadCalCellSolid
282  = new G4Box("HadCalCellBox",15.*cm,15.*cm,50.*cm);
283  auto HadCalCellLogical
284  = new G4LogicalVolume(HadCalCellSolid,lead,"HadCalCellLogical");
285  new G4PVReplica("HadCalCellPhysical",HadCalCellLogical,
286  HadCalColumnLogical,kYAxis,kNofHadRows,30.*cm);
287 
288  // hadron calorimeter layers
289  auto HadCalLayerSolid
290  = new G4Box("HadCalLayerBox",15.*cm,15.*cm,2.5*cm);
291  auto HadCalLayerLogical
292  = new G4LogicalVolume(HadCalLayerSolid,lead,"HadCalLayerLogical");
293  new G4PVReplica("HadCalLayerPhysical",HadCalLayerLogical,
294  HadCalCellLogical,kZAxis,kNofHadCells,5.*cm);
295 
296  // scintillator plates
297  auto HadCalScintiSolid
298  = new G4Box("HadCalScintiBox",15.*cm,15.*cm,0.5*cm);
300  = new G4LogicalVolume(HadCalScintiSolid,scintillator,
301  "HadCalScintiLogical");
303  "HadCalScintiPhysical",HadCalLayerLogical,
304  false,0,checkOverlaps);
305 
306  // visualization attributes ------------------------------------------------
307 
308  auto visAttributes = new G4VisAttributes(G4Colour(1.0,1.0,1.0));
309  visAttributes->SetVisibility(false);
310  worldLogical->SetVisAttributes(visAttributes);
311  fVisAttributes.push_back(visAttributes);
312 
313  visAttributes = new G4VisAttributes(G4Colour(0.9,0.9,0.9)); // LightGray
314  fMagneticLogical->SetVisAttributes(visAttributes);
315  fVisAttributes.push_back(visAttributes);
316 
317  visAttributes = new G4VisAttributes(G4Colour(1.0,1.0,1.0));
318  visAttributes->SetVisibility(false);
319  firstArmLogical->SetVisAttributes(visAttributes);
320  secondArmLogical->SetVisAttributes(visAttributes);
321  fVisAttributes.push_back(visAttributes);
322 
323  visAttributes = new G4VisAttributes(G4Colour(0.8888,0.0,0.0));
324  fHodoscope1Logical->SetVisAttributes(visAttributes);
325  fHodoscope2Logical->SetVisAttributes(visAttributes);
326  fVisAttributes.push_back(visAttributes);
327 
328  visAttributes = new G4VisAttributes(G4Colour(0.0,1.0,0.0));
329  chamber1Logical->SetVisAttributes(visAttributes);
330  chamber2Logical->SetVisAttributes(visAttributes);
331  fVisAttributes.push_back(visAttributes);
332 
333  visAttributes = new G4VisAttributes(G4Colour(0.0,0.8888,0.0));
334  visAttributes->SetVisibility(false);
335  fWirePlane1Logical->SetVisAttributes(visAttributes);
336  fWirePlane2Logical->SetVisAttributes(visAttributes);
337  fVisAttributes.push_back(visAttributes);
338 
339  visAttributes = new G4VisAttributes(G4Colour(0.8888,0.8888,0.0));
340  visAttributes->SetVisibility(false);
341  emCalorimeterLogical->SetVisAttributes(visAttributes);
342  fVisAttributes.push_back(visAttributes);
343 
344  visAttributes = new G4VisAttributes(G4Colour(0.9,0.9,0.0));
345  fCellLogical->SetVisAttributes(visAttributes);
346  fVisAttributes.push_back(visAttributes);
347 
348  visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 0.9));
349  hadCalorimeterLogical->SetVisAttributes(visAttributes);
350  fVisAttributes.push_back(visAttributes);
351 
352  visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 0.9));
353  visAttributes->SetVisibility(false);
354  HadCalColumnLogical->SetVisAttributes(visAttributes);
355  HadCalCellLogical->SetVisAttributes(visAttributes);
356  HadCalLayerLogical->SetVisAttributes(visAttributes);
357  fHadCalScintiLogical->SetVisAttributes(visAttributes);
358  fVisAttributes.push_back(visAttributes);
359 
360  // return the world physical volume ----------------------------------------
361 
362  return worldPhysical;
363 }
364 
365 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
366 
368 {
369  // sensitive detectors -----------------------------------------------------
370  auto sdManager = G4SDManager::GetSDMpointer();
371  G4String SDname;
372 
373  auto hodoscope1 = new B5HodoscopeSD(SDname="/hodoscope1");
374  sdManager->AddNewDetector(hodoscope1);
376 
377  auto hodoscope2 = new B5HodoscopeSD(SDname="/hodoscope2");
378  sdManager->AddNewDetector(hodoscope2);
380 
381  auto chamber1 = new B5DriftChamberSD(SDname="/chamber1");
382  sdManager->AddNewDetector(chamber1);
384 
385  auto chamber2 = new B5DriftChamberSD(SDname="/chamber2");
386  sdManager->AddNewDetector(chamber2);
388 
389  auto emCalorimeter = new B5EmCalorimeterSD(SDname="/EMcalorimeter");
390  sdManager->AddNewDetector(emCalorimeter);
391  fCellLogical->SetSensitiveDetector(emCalorimeter);
392 
393  auto hadCalorimeter = new B5HadCalorimeterSD(SDname="/HadCalorimeter");
394  sdManager->AddNewDetector(hadCalorimeter);
396 
397  // magnetic field ----------------------------------------------------------
399  fFieldMgr = new G4FieldManager();
402  G4bool forceToAllDaughters = true;
403  fMagneticLogical->SetFieldManager(fFieldMgr, forceToAllDaughters);
404 
405  // Register the field and its manager for deleting
408 }
409 
410 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
411 
413 {
414  auto nistManager = G4NistManager::Instance();
415 
416  // Air
417  nistManager->FindOrBuildMaterial("G4_AIR");
418 
419  // Argon gas
420  nistManager->FindOrBuildMaterial("G4_Ar");
421  // With a density different from the one defined in NIST
422  // G4double density = 1.782e-03*g/cm3;
423  // nistManager->BuildMaterialWithNewDensity("B5_Ar","G4_Ar",density);
424  // !! cases segmentation fault
425 
426  // Scintillator
427  // (PolyVinylToluene, C_9H_10)
428  nistManager->FindOrBuildMaterial("G4_PLASTIC_SC_VINYLTOLUENE");
429 
430  // CsI
431  nistManager->FindOrBuildMaterial("G4_CESIUM_IODIDE");
432 
433  // Lead
434  nistManager->FindOrBuildMaterial("G4_Pb");
435 
436  // Vacuum "Galactic"
437  // nistManager->FindOrBuildMaterial("G4_Galactic");
438 
439  // Vacuum "Air with low density"
440  // auto air = G4Material::GetMaterial("G4_AIR");
441  // G4double density = 1.0e-5*air->GetDensity();
442  // nistManager
443  // ->BuildMaterialWithNewDensity("Air_lowDensity", "G4_AIR", density);
444 
445  G4cout << G4endl << "The materials defined are : " << G4endl << G4endl;
446  G4cout << *(G4Material::GetMaterialTable()) << G4endl;
447 }
448 
449 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
450 
452 {
453  if (!fSecondArmPhys) {
454  G4cerr << "Detector has not yet been constructed." << G4endl;
455  return;
456  }
457 
458  fArmAngle = val;
459  *fArmRotation = G4RotationMatrix(); // make it unit vector
460  fArmRotation->rotateY(fArmAngle);
461  auto x = -5.*m * std::sin(fArmAngle);
462  auto z = 5.*m * std::cos(fArmAngle);
464 
465  // tell G4RunManager that we change the geometry
467 }
468 
469 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
470 
472 {
473  // Define /B5/detector command directory using generic messenger class
474  fMessenger = new G4GenericMessenger(this,
475  "/B5/detector/",
476  "Detector control");
477 
478  // armAngle command
479  auto& armAngleCmd
480  = fMessenger->DeclareMethodWithUnit("armAngle","deg",
482  "Set rotation angle of the second arm.");
483  armAngleCmd.SetParameterName("angle", true);
484  armAngleCmd.SetRange("angle>=0. && angle<180.");
485  armAngleCmd.SetDefaultValue("30.");
486 }
487 
488 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void GeometryHasBeenModified(G4bool prop=true)
Definition of the B5HadCalorimeterSD class.
G4GenericMessenger * fMessenger
Definition of the B5CellParameterisation class.
Definition of the B5DetectorConstruction class.
static constexpr double mm
Definition: G4SIunits.hh:115
Definition of the B5DriftChamberSD class.
CLHEP::Hep3Vector G4ThreeVector
G4LogicalVolume * fWirePlane2Logical
CLHEP::HepRotation G4RotationMatrix
G4bool SetDetectorField(G4Field *detectorField)
This class is generic messenger.
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:602
Definition: G4Box.hh:64
G4LogicalVolume * fHodoscope1Logical
void SetUserLimits(G4UserLimits *pULimits)
Definition: G4Tubs.hh:85
static G4MaterialTable * GetMaterialTable()
Definition: G4Material.cc:587
Drift chamber sensitive detector.
constexpr G4int kNofChambers
Definition: B5Constants.hh:38
Definition of the B5EmCalorimeterSD class.
G4LogicalVolume * fMagneticLogical
Command & DeclareMethodWithUnit(const G4String &name, const G4String &defaultUnit, const G4AnyMethod &fun, const G4String &doc="")
G4VPhysicalVolume * fSecondArmPhys
constexpr G4int kNofHadCells
Definition: B5Constants.hh:44
#define G4ThreadLocal
Definition: tls.hh:89
static G4NistManager * Instance()
void SetFieldManager(G4FieldManager *pFieldMgr, G4bool forceToAllDaughters)
Command & SetDefaultValue(const G4String &)
void Register(T *inst)
Definition: G4AutoDelete.hh:65
virtual G4VPhysicalVolume * Construct()
G4GLOB_DLL std::ostream G4cout
static constexpr double m
Definition: G4SIunits.hh:129
constexpr G4int kNofHadRows
Definition: B5Constants.hh:43
bool G4bool
Definition: G4Types.hh:79
G4LogicalVolume * fHadCalScintiLogical
EM Calorimeter cell parameterisation.
static constexpr double cm
Definition: G4SIunits.hh:119
static G4ThreadLocal B5MagneticField * fMagneticField
Magnetic field.
void SetTranslation(const G4ThreeVector &v)
constexpr G4int kNofHadColumns
Definition: B5Constants.hh:42
G4RotationMatrix * fArmRotation
static G4ThreadLocal G4FieldManager * fFieldMgr
Command & SetRange(const G4String &range)
constexpr G4int kNofHodoscopes2
Definition: B5Constants.hh:37
G4LogicalVolume * fWirePlane1Logical
static G4RunManager * GetRunManager()
Definition: G4RunManager.cc:79
Definition of the B5MagneticField class.
Definition of the B5HodoscopeSD class.
G4LogicalVolume * fHodoscope2Logical
static G4SDManager * GetSDMpointer()
Definition: G4SDManager.cc:40
Hodoscope sensitive detector.
Command & SetParameterName(const G4String &, G4bool, G4bool=false)
#define G4endl
Definition: G4ios.hh:61
double G4double
Definition: G4Types.hh:76
void CreateChordFinder(G4MagneticField *detectorMagField)
static constexpr double deg
Definition: G4SIunits.hh:152
constexpr G4int kNofEmCells
Definition: B5Constants.hh:41
constexpr G4int kNofHodoscopes1
Definition: B5Constants.hh:36
EM calorimeter sensitive detector.
void SetVisAttributes(const G4VisAttributes *pVA)
void SetSensitiveDetector(G4VSensitiveDetector *pSDetector)
Hadron calorimeter sensitive detector.
G4GLOB_DLL std::ostream G4cerr
std::vector< G4VisAttributes * > fVisAttributes