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