ACTARSim
ACTAR TPC Simulation Reference Guide
ActarSimSciDetectorConstruction.cc
Go to the documentation of this file.
1 // - AUTHOR: Hector Alvarez-Pol 04/2008
2 /******************************************************************
3  * Copyright (C) 2005-2016, Hector Alvarez-Pol *
4  * All rights reserved. *
5  * *
6  * License according to GNU LESSER GPL (see lgpl-3.0.txt). *
7  * For the list of contributors see CREDITS. *
8  ******************************************************************/
9 //////////////////////////////////////////////////////////////////
10 /// \class ActarSimSciDetectorConstruction
11 /// Scintillator detector description
12 /////////////////////////////////////////////////////////////////
13 
18 #include "ActarSimROOTAnalysis.hh"
19 #include "ActarSimSciSD.hh"
20 
21 #include "G4Material.hh"
22 #include "G4Box.hh"
23 #include "G4Trd.hh"
24 #include "G4Cons.hh"
25 #include "G4LogicalVolume.hh"
26 #include "G4PVPlacement.hh"
27 #include "G4RotationMatrix.hh"
28 #include "G4VisAttributes.hh"
29 #include "G4Colour.hh"
30 #include "G4RunManager.hh"
31 #include "G4Transform3D.hh"
32 
33 #include "G4PhysicalConstants.hh"
34 #include "G4SystemOfUnits.hh"
35 
36 #include "globals.hh"
37 
38 //////////////////////////////////////////////////////////////////
39 /// Constructor. Sets the material and the pointer to the Messenger
42  : sciBulkMaterial(0),detConstruction(det) {
43  SetSciBulkMaterial("CsI");
44 
45  //Options for Silicon and scintillator coverage:
46  // 6 bits to indicate which sci wall is present (1) or absent (0)
47  // order is:
48  // bit1 (lsb) beam output wall
49  // bit2 lower (gravity based) wall
50  // bit3 upper (gravity based) wall
51  // bit4 left (from beam point of view) wall
52  // bit5 right (from beam point of view) wall
53  // bit6 (msb) beam entrance wall
54  SetSideCoverage(1);
55 
56  SetXBoxSciHalfLength(100*cm);
57  SetYBoxSciHalfLength(100*cm);
58  SetZBoxSciHalfLength(100*cm);
59 
60  // create commands for interactive definition of the calorimeter
62 }
63 
64 //////////////////////////////////////////////////////////////////
65 /// Destructor.
67  delete sciMessenger;
68 }
69 
70 //////////////////////////////////////////////////////////////////
71 /// Wrap for the construction function
72 G4VPhysicalVolume* ActarSimSciDetectorConstruction::Construct(G4LogicalVolume* worldLog) {
73  return ConstructSci(worldLog);
74 }
75 
76 //////////////////////////////////////////////////////////////////
77 /// Constructs the scintillator detector elements
78 ///
79 /// - Introduce Silicon and CsI(Tl) detectors all around. Use MUST style:
80 /// Si: 300 microns thick, 100x100mm2, with 128 strides per side
81 /// (horizontal on one side and vertical in the opposite).
82 /// CsI(Tl): 25x25mm2, 30mm thick, so 16 per Silicon detector.
83 /// <pre>
84 /// < -- 50mm -- >
85 /// ------ -- | x
86 /// | | || | x wires shaping the field
87 /// | | || | x
88 /// |CsI | || | x
89 /// | | || | x
90 /// ------ -- | Gas x Gas
91 /// Si | x
92 /// | x
93 /// Al layer (~1 microm)
94 /// </pre>
95 G4VPhysicalVolume* ActarSimSciDetectorConstruction::ConstructSci(G4LogicalVolume* worldLog) {
96  //MUST-like scintillator detectors (half-sides)
97  //I left some "air" in between crystals. Half-length are 0,1 shorter.
98  G4double sciBulk_x = 12.0*mm; //half length=12.5mm
99  G4double sciBulk_y = 12.0*mm; //half length=12.5mm
100  G4double sciBulk_z = 15.0*mm; //half length=15.0mm
101 
102  G4double defectHalfLength = 0.5*mm;
103  G4double separationFromBox = 25*mm;
104 
105  //Position of the GasBox inside the Chamber
107  G4double zGasBoxPosition=gasDet->GetGasBoxCenterZ();
108 
109  // Printing the final settings...
110  G4cout << "##################################################################"
111  << G4endl
112  << "######### ActarSimSciDetectorConstruction::ConstructSci() #######"
113  << G4endl
114  << " Note that only a thin (1 micron) Al window is defined in front"
115  << G4endl
116  << " of the silicons. Here only the scintillator volume is described."
117  << G4endl
118  << " x dimension (half-side) of scintillator: " << sciBulk_x/mm << " mm"
119  << G4endl
120  << " y dimension (half-side) of scintillator: " << sciBulk_y/mm << " mm"
121  << G4endl
122  << " z dimension (half-side) of scintillator: " << sciBulk_z/mm << " mm"
123  << G4endl;
124  G4cout << "##################################################################"
125  << G4endl;
126 
127  G4LogicalVolume* sciLog(0);
128  G4VPhysicalVolume* sciPhys(0);
129 
130  // G4Trd* sciBox = //testing the direction after rotation...
131  // new G4Trd("sciBox", 5, 12, 5, 12, 30);
132  G4Box* sciBox =
133  new G4Box("sciBox", sciBulk_x, sciBulk_y, sciBulk_z);
134 
135  sciLog =
136  new G4LogicalVolume(sciBox, sciBulkMaterial, "sciLog");
137 
138  //As a function of the lateral coverage
139  // 6 bits to indicate which sci wall is present (1) or absent (0)
140  // order is:
141  // bit1 (lsb) beam output wall
142  // bit2 lower (gravity based) wall
143  // bit3 upper (gravity based) wall
144  // bit4 left (from beam point of view) wall
145  // bit5 right (from beam point of view) wall
146  // bit6 (msb) beam entrance wall
147 
148  //for the moment, let's assume square scintillator...
149  //if not, more sophisticated approach needed!
150  G4int numberOfRowsX = ((G4int) (2*xBoxSciHalfLength/(2*(sciBulk_x+defectHalfLength)))) - 1;
151  if( (numberOfRowsX+1)*sciBulk_x <= 2*xBoxSciHalfLength ) numberOfRowsX++;
152  G4int numberOfRowsY = ((G4int) (2*yBoxSciHalfLength/(2*(sciBulk_x+defectHalfLength)))) - 1;
153  if( (numberOfRowsY+1)*sciBulk_x <= 2*yBoxSciHalfLength ) numberOfRowsY++;
154  G4int numberOfRowsZ = ((G4int) (2*zBoxSciHalfLength/(2*(sciBulk_x+defectHalfLength)))) - 1;
155  if( (numberOfRowsZ+1)*sciBulk_x <= 2*zBoxSciHalfLength ) numberOfRowsZ++;
156 
157  //G4cout << numberOfRowsX << " " << numberOfRowsY << " " << numberOfRowsZ << G4endl;
158 
159  G4int iterationNumber = 0;
160 
161  //By a reason I do not know the correct rotation using Euler angles does not match with standards...
162  // I would call rotLeft to rotTop, and so on...
163  G4RotationMatrix* rotBack = //beam entrance
164  new G4RotationMatrix(0,pi,pi); //if y direction is up and x is right
165  //new G4RotationMatrix(0,pi,0); //if x direction is left and y down
166  G4RotationMatrix* rotBottom = //ZX planes (bottom)
167  new G4RotationMatrix(0,pi/2,0);
168  G4RotationMatrix* rotTop = //ZX planes (top)
169  new G4RotationMatrix(0,-pi/2,0);
170  G4RotationMatrix* rotLeft = //ZY planes
171  new G4RotationMatrix(pi/2,pi/2,-pi/2);
172  G4RotationMatrix* rotRight = //ZY planes
173  new G4RotationMatrix(-pi/2,pi/2,pi/2);
174 
175  // G4int checker = sideCoverage;
176  if(sideCoverage & 0x0001){ // bit1 (lsb) beam output wall
177  //iteration on Scintillator elements
178  /*
179  for(G4int rowX=0;rowX<numberOfRowsX;rowX++){ //maybe is rowX=1 the first??
180  for(G4int rowY=0;rowY<numberOfRowsY;rowY++){
181  iterationNumber++;
182  sciPhys =
183  new G4PVPlacement(0,G4ThreeVector(-xBoxSciHalfLength + ((rowX+1)*2-1)*(sciBulk_x+defectHalfLength),
184  -yBoxSciHalfLength + ((rowY+1)*2-1)*(sciBulk_x+defectHalfLength),
185  2*zBoxSciHalfLength + separationFromBox + sciBulk_z),
186  sciLog, "sciPhys", worldLog, false, iterationNumber);
187  }
188  }
189  */
190  for(G4int rowX=0;rowX<4;rowX++){ //maybe is rowX=1 the first??
191  for(G4int rowY=0;rowY<4;rowY++){
192  iterationNumber++;
193  sciPhys =
194  new G4PVPlacement(0,G4ThreeVector( (rowX-1.5)*2*(sciBulk_x+defectHalfLength),
195  (rowY-1.5)*2*(sciBulk_x+defectHalfLength),
196  2*zBoxSciHalfLength + separationFromBox + sciBulk_z - zGasBoxPosition),
197  sciLog, "sciPhys", worldLog, false, iterationNumber);
198  }
199  }
200  }
201 
202  //PLANES ZX
203  //a different rotation has to be introduced on each side...
204  if((sideCoverage >> 1) & 0x0001){ // bit2 lower [bottom] (gravity based) wall
205  for(G4int rowZ=0;rowZ<numberOfRowsZ;rowZ++){
206  for(G4int rowX=0;rowX<numberOfRowsX;rowX++){
207  iterationNumber++;
208  sciPhys =
209  new G4PVPlacement(rotBottom,G4ThreeVector(-xBoxSciHalfLength + ((rowX+1)*2-1)*(sciBulk_x+defectHalfLength),
210  -(yBoxSciHalfLength + separationFromBox + sciBulk_z),
211  ((rowZ+1)*2-1)*(sciBulk_x+defectHalfLength) - zGasBoxPosition),
212  sciLog, "sciPhys", worldLog, false, iterationNumber);
213  }
214  }
215  }
216  if((sideCoverage >> 2) & 0x0001){ // bit3 upper [top] (gravity based) wall
217  for(G4int rowZ=0;rowZ<numberOfRowsZ;rowZ++){
218  for(G4int rowX=0;rowX<numberOfRowsX;rowX++){
219  iterationNumber++;
220  sciPhys =
221  new G4PVPlacement(rotTop,G4ThreeVector(-xBoxSciHalfLength + ((rowX+1)*2-1)*(sciBulk_x+defectHalfLength),
222  yBoxSciHalfLength + separationFromBox + sciBulk_z,
223  ((rowZ+1)*2-1)*(sciBulk_x+defectHalfLength) - zGasBoxPosition),
224  sciLog, "sciPhys", worldLog, false, iterationNumber);
225  }
226  }
227  }
228 
229  //PLANES ZY
230  if((sideCoverage >> 3) & 0x0001){ // bit4 left (from beam point of view) wall
231  /*
232  for(G4int rowZ=0;rowZ<numberOfRowsZ;rowZ++){
233  for(G4int rowY=0;rowY<numberOfRowsY;rowY++){
234  iterationNumber++;
235  sciPhys =
236  new G4PVPlacement(rotLeft,G4ThreeVector(xBoxSciHalfLength + separationFromBox + sciBulk_z,
237  -yBoxSciHalfLength + ((rowY+1)*2-1)*(sciBulk_x+defectHalfLength),
238  ((rowZ+1)*2-1)*(sciBulk_x+defectHalfLength)),
239  sciLog, "sciPhys", worldLog, false, iterationNumber);
240  }
241  }
242  */
243  for(G4int rowZ=0;rowZ<6;rowZ++){
244  for(G4int rowY=0;rowY<4;rowY++){
245  iterationNumber++;
246  sciPhys =
247  new G4PVPlacement(rotLeft,G4ThreeVector(xBoxSciHalfLength + separationFromBox + sciBulk_z,
248  (rowY-1.5)*2*(sciBulk_x+defectHalfLength),
249  zBoxSciHalfLength+(rowZ-2.5)*2*(sciBulk_x+defectHalfLength) - zGasBoxPosition),
250  sciLog, "sciPhys", worldLog, false, iterationNumber);
251  }
252  }
253  }
254 
255  if((sideCoverage >> 4) & 0x0001){ // bit5 right (from beam point of view) wall
256  /*
257  for(G4int rowZ=0;rowZ<numberOfRowsZ;rowZ++){
258  for(G4int rowY=0;rowY<numberOfRowsY;rowY++){
259  iterationNumber++;
260  sciPhys =
261  new G4PVPlacement(rotRight,G4ThreeVector(-(xBoxSciHalfLength + separationFromBox + sciBulk_z),
262  -yBoxSciHalfLength + ((rowY+1)*2-1)*(sciBulk_x+defectHalfLength),
263  ((rowZ+1)*2-1)*(sciBulk_x+defectHalfLength)),
264  sciLog, "sciPhys", worldLog, false, iterationNumber);
265  }
266  }
267  */
268 
269  for(G4int rowZ=0;rowZ<2;rowZ++){
270  for(G4int rowY=0;rowY<2;rowY++){
271  iterationNumber++;
272  sciPhys =
273  new G4PVPlacement(rotRight,G4ThreeVector(-(xBoxSciHalfLength + separationFromBox + sciBulk_z),
274  (rowY-0.5)*2*(sciBulk_y+defectHalfLength),
275  zBoxSciHalfLength+(rowZ-0.5)*2*(sciBulk_x+defectHalfLength) - zGasBoxPosition),
276  sciLog, "sciPhys", worldLog, false, iterationNumber);
277 
278  }
279  }
280  }
281 
282  if((sideCoverage >> 5) & 0x0001){ // bit6 (msb) beam entrance wall
283  for(G4int rowX=0;rowX<numberOfRowsX;rowX++){
284  for(G4int rowY=0;rowY<numberOfRowsY;rowY++){
285  iterationNumber++;
286  sciPhys =
287  new G4PVPlacement(rotBack,G4ThreeVector(-xBoxSciHalfLength + ((rowX+1)*2-1)*(sciBulk_x+defectHalfLength),
288  -yBoxSciHalfLength + ((rowY+1)*2-1)*(sciBulk_x+defectHalfLength),
289  -separationFromBox - sciBulk_z - zGasBoxPosition),
290  sciLog, "sciPhys", worldLog, false, iterationNumber);
291  }
292  }
293  }
294 
295  //------------------------------------------------
296  // Sensitive detectors
297  //------------------------------------------------
298  sciLog->SetSensitiveDetector( detConstruction->GetSciSD() );
299 
300  //------------------------------------------------------------------
301  // Visualization attributes
302  //------------------------------------------------------------------
303  G4VisAttributes* sciVisAtt1 = new G4VisAttributes(G4Colour(0,1,1));
304  sciVisAtt1->SetVisibility(true);
305  sciLog->SetVisAttributes(sciVisAtt1);
306 
307  return sciPhys;
308 }
309 
310 //////////////////////////////////////////////////////////////////
311 /// Set the material the scintillator bulk is made of
313  G4Material* pttoMaterial = G4Material::GetMaterial(mat);
314  if (pttoMaterial) sciBulkMaterial = pttoMaterial;
315 }
316 
317 //////////////////////////////////////////////////////////////////
318 /// Updates Scintillator detector
321  G4RunManager::GetRunManager()->
322  DefineWorldVolume(detConstruction->GetWorldPhysicalVolume());
323 }
324 
325 //////////////////////////////////////////////////////////////////
326 /// Prints Scintillator detector parameters. TODO: To be filled
328  G4cout << "##################################################################"
329  << G4endl
330  << "#### ActarSimSciDetectorConstruction::PrintDetectorParameters() ####"
331  << G4endl;
332  G4cout << "##################################################################"
333  << G4endl;
334 }
G4VPhysicalVolume * Construct(G4LogicalVolume *)
Wrap for the construction function.
ActarSimSciDetectorMessenger * sciMessenger
Pointer to the Messenger.
G4VPhysicalVolume * ConstructSci(G4LogicalVolume *)
void SetSciBulkMaterial(G4String)
Set the material the scintillator bulk is made of.
G4Material * sciBulkMaterial
Pointer to the material the scintillator is made of.
G4double xBoxSciHalfLength
Scintillator box half length along X (X is horizontal)
ActarSimSciDetectorConstruction(ActarSimDetectorConstruction *)
Constructor. Sets the material and the pointer to the Messenger.
ActarSimGasDetectorConstruction * GetGasDetector()
G4double zBoxSciHalfLength
Scintillator box half length along Z (Z is along beam)
void UpdateGeometry()
Updates Scintillator detector.
void PrintDetectorParameters()
Prints Scintillator detector parameters. TODO: To be filled.
ActarSimDetectorConstruction * detConstruction
Pointer to the global detector.
G4double yBoxSciHalfLength
Scintillator box half length along Y (Y is vertical)