CrystalEndcapECAL_geo.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // Crystal Endcap EM Calorimeter Detector implementation
3 //--------------------------------------------------------------------------
4 //
5 // Authors : W.Armstrong
6 //
7 //==========================================================================
8 // J.KIM 2020-04-01
9 // Added box assembly of volumes
10 //==========================================================================
11 #include "DD4hep/DetFactoryHelper.h"
12 #include "XML/Layering.h"
13 #include <math.h>
14 
15 using namespace std;
16 using namespace dd4hep;
17 using namespace dd4hep::detail;
18 
37 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
38  xml_det_t x_det = e;
39  xml_dim_t dim = x_det.dimensions();
40  int det_id = x_det.id();
41  string det_name = x_det.nameStr();
42  Material PbWO4 = description.material("PbWO4");
43  double rmin = dim.rmin();
44  double rmax = dim.rmax();
45  double zmin = dim.zmin();
46  double zmax = dim.zmax();
47  double thickness = zmax - zmin;
48  double z_pos = zmin + thickness / 2.0;
49 
50  Assembly assembly(det_name);
51  DetElement endcap_DE(det_name,det_id);
52 
53  // Create a tube to represent the calorimeter
54  Tube tube(rmin, rmax, thickness / 2.0);
55  Volume Vol("tube_volume", tube, PbWO4);
56  //auto PV = assembly.placeVolume(Vol, Position(0.0, 0.0, 0.0));
57  //PV.addPhysVolID("layer", 0);
58  //sens.setType("calorimeter");
59  //Vol.setSensitiveDetector(sens);
60 
61  // Tube is filled with box-shaped crystals forming a grid.
62  Assembly box_assembly("box_assembly");
63  PlacedVolume pv_box;
64 
65  // Box-shaped crystal dimension
66  double box_x_width = 2*cm;
67  double box_y_width = 2*cm;
68  double box_z_length = 20*cm;
69  // Gap between box-shaped crystals
70  double offset_x = 1*mm;
71  double offset_y = 1*mm;
72  double offset_diagonal = box_x_width*sqrt(2)/2.0 + 0.1*cm;
73  // Limits
74  double limit_inner = rmin + offset_diagonal;
75  double limit_outer = rmax - offset_diagonal;
76  // Number of crystals in a grid
77  int nx = floor(rmax/box_x_width);
78  int ny = floor(rmax/box_y_width);
79  // X or Y spacing increasement
80  double x_spacing = box_x_width + offset_x;
81  double y_spacing = box_y_width + offset_y;
82  // initial positions in X or Y.
83  double pos_x = 0*cm;
84  double pos_y = 0*cm;
85 
86  // Create Box and Volume
87  Box box(box_x_width/2.0, box_y_width/2.0, box_z_length/2.0);
88  Volume vol("box_volume", box, PbWO4);
89 
91  // Divide tube into 4 sections; top left, top right, bottom left, and bottom right
93  // Top left
95  int i_module = 0;
96  for(int iy=0; iy<ny-1; iy++){
97  for(int ix=0; ix<nx; ix++){
98  double x_start = box_x_width/2.0 + offset_x/2.0;
99 
100  if(ix==0)
101  {
102  pos_x = x_start;
103  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
104  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
105  i_module++;
106  }
107  else{
108  continue;
109  }
110  }
111  else
112  {
113  // Move to +X
114  pos_x += x_spacing;
115  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner)
116  {
117  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
118  i_module++;
119  }
120  else{
121  continue;
122  }
123  }
124  pv_box.addPhysVolID("sector",1).addPhysVolID("module",i_module);
125  sens.setType("calorimeter");
126  vol.setSensitiveDetector(sens);
127  }
128  // Move to +Y
129  pos_y += y_spacing;
130  }
131 
133  // Top right
135  // Initialize position in Y
136  pos_y = 0.0;
137  i_module=0;
138  for(int iy=0; iy<ny-1; iy++){
139  for(int ix=0; ix<nx; ix++){
140  double x_start = box_x_width/2.0 + offset_x/2.0;
141 
142  if(ix==0)
143  {
144  pos_x = - x_start;
145  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
146  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
147  i_module++;
148  }
149  else{
150  continue;
151  }
152  }
153  else
154  {
155  // Move to -X
156  pos_x -= x_spacing;
157  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
158  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
159  i_module++;
160  }
161  else{
162  continue;
163  }
164  }
165  pv_box.addPhysVolID("sector",2).addPhysVolID("module",i_module);
166  sens.setType("calorimeter");
167  vol.setSensitiveDetector(sens);
168  }
169  // Move to +Y
170  pos_y += y_spacing;
171  }
172 
174  // Bottom left
176  // It's below the first row of the section of Top left
177  // That's why ny goes up to ny -2 (the first row of Bottom left starts one row less)
178  pos_y = -y_spacing;
179  i_module=0;
180  for(int iy=0; iy<ny-2; iy++){
181  for(int ix=0; ix<nx; ix++){
182  double x_start = box_x_width/2.0 + offset_x/2.0;
183 
184  if(ix==0)
185  {
186  pos_x = x_start;
187  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
188  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
189  i_module++;
190  }
191  else{
192  continue;
193  }
194  }
195  else
196  {
197  // Move to +X
198  pos_x += x_spacing;
199  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
200  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
201  i_module++;
202  }
203  else{
204  continue;
205  }
206  }
207  pv_box.addPhysVolID("sector",3).addPhysVolID("module",i_module);
208  sens.setType("calorimeter");
209  vol.setSensitiveDetector(sens);
210  }
211  // Move to -Y
212  pos_y -= y_spacing;
213  }
214 
216  // Bottom right
218  // Again it's below the first row of the section of Top left
219  // That's why ny goes up to ny -2 (the first row of Bottom left starts one row less)
220  pos_y = -y_spacing;
221  i_module=0;
222  for(int iy=0; iy<ny-2; iy++){
223  for(int ix=0; ix<nx; ix++)
224  {
225  double x_start = box_x_width/2.0 + offset_x/2.0;
226 
227  if(ix==0)
228  {
229  pos_x = - x_start;
230  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
231  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
232  i_module++;
233  }
234  else{
235  continue;
236  }
237  }
238  else
239  {
240  // Move to -X
241  pos_x -= x_spacing;
242  if(sqrt((pos_x*pos_x) + (pos_y*pos_y)) < limit_outer && sqrt((pos_x*pos_x) + (pos_y*pos_y)) > limit_inner){
243  pv_box = assembly.placeVolume(vol, Position(pos_x,pos_y,0.0));
244  i_module++;
245  }
246  else{
247  continue;
248  }
249  }
250  pv_box.addPhysVolID("sector",4).addPhysVolID("module",i_module);
251  sens.setType("calorimeter");
252  vol.setSensitiveDetector(sens);
253  }
254  // Move to -Y
255  pos_y -= y_spacing;
256  }
259 
260  Volume motherVol = description.pickMotherVolume(endcap_DE);
261  auto pv = motherVol.placeVolume(assembly, Position(0.0, 0.0, z_pos));
262  pv.addPhysVolID("system", det_id);
263  endcap_DE.setPlacement(pv);
264  return endcap_DE;
265 }
267 DECLARE_DETELEMENT(CrystalEndcapECAL,create_detector)
static Ref_t create_detector(Detector &description, xml_h e, SensitiveDetector sens)
Detector
Definition: DDG4.py:69
Namespace for the AIDA detector description toolkit.