ThresholdGasCherenkov_geo.cpp
Go to the documentation of this file.
1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/Printout.h"
3 #include <XML/Helper.h>
4 #include "TMath.h"
5 #include "DDRec/Surface.h"
6 
7 #include "DD4hep/OpticalSurfaces.h"
8 #include "DDRec/DetectorData.h"
9 
10 using namespace std;
11 using namespace dd4hep;
12 using namespace dd4hep::rec;
13 
14 using namespace dd4hep;
15 
29 static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens) {
30  xml::DetElement detElem = handle;
31  xml_det_t x_det = handle;
32 
33  std::string detName = detElem.nameStr();
34  int detID = detElem.id();
35 
36  DetElement det(detName, detID);
37  xml::Component dims = detElem.dimensions();
38  double rInner = dims.rmin();
39  double rOuter1 = dims.rmax1();
40  double rOuter2 = dims.rmax2();
41  double zMin = dims.zmin();
42  double zMax = dims.zmax();
43 
44  std::map<int,Position> mirror_positions;
45  std::map<int,std::array<double,3>> mirror_rotations;
46 
47  for(xml_coll_t i(x_det,Unicode("mirror")); i; ++i){
48  xml_comp_t x_mir = i;
49  //std::cout << "mirror " << x_mir.id() << "\n";
50  xml_dim_t mir_pos = x_mir.child(_U(placement));
51  xml_dim_t mir_rot = x_mir.child(_U(rotation));
52  mirror_positions[x_mir.id()] = Position(mir_pos.x(), mir_pos.y(), mir_pos.z());
53  mirror_rotations[x_mir.id()] = {mir_rot.x(), mir_rot.y(), mir_rot.z()};
54  }
55 
56  xml_dim_t pos = x_det.child(_U(placement));
57  double pos_x = pos.x();
58  double pos_y = pos.y();
59  double pos_z = pos.z();
60 
61  Material air = desc.air();
62  Material PyrexGlass = desc.material("PyrexGlass");
63  Material N2cherenkov = desc.material("N2cherenkov");
64  Material Copper = desc.material("Copper");
65 
66  double LGC_inner_radius1 = 71.0*cm;
67  double LGC_inner_radius2 = 85.0*cm;
68  double LGC_outer_radius1 = 265.0*cm;
69  double LGC_main_length = 105.0*cm;
70  double LGC_snout_length = 107.0*cm;
71  double LGC_snout_inner_radius1 = 58.0*cm;
72  double LGC_snout_inner_radius2 = LGC_inner_radius1;
73  double LGC_snout_outer_radius1 = 127.0*cm;
74  double LGC_snout_outer_radius2 = 144.0*cm;
75  double LGC_entrance_window_thickness = 0.05*mm; // something tells this might be 5 mil, not mm
76  double LGC_exit_window_thickness = 0.1*mm; // same here
77  double LGC_mirror1_radius = 277.51*cm;
78  double LGC_mirror2_radius = 157.99*cm;
79  double LGC_mirror1_length = 114.53*cm;
80  double LGC_mirror2_length = 59.260*cm;
81  double LGC_mirror1_width1 = 16.26*cm;
82  double LGC_mirror1_width2 = 36.03*cm;
83  double LGC_mirror2_width1 = 37.06*cm;
84  double LGC_mirror2_width2 = 45.95*cm;
85  double LGC_mirror1_thickness = 2.0*mm;
86  double LGC_mirror2_thickness = 2.0*mm;
87 
88  double LGC_sector_angle = M_PI * 15.0 / 180.0;
89  //double LGC_scattering_angle = 11.0 * M_PI / 180.0;
90 
91  double LGC_mirror1_tilt_angle = mirror_rotations[1][0];//25.0 * M_PI / 180.0;
92  double LGC_mirror2_tilt_angle = mirror_rotations[2][0];//2.0 * M_PI / 180.0;
93  double LGC_pmt_tilt_angle = mirror_rotations[3][0];//45.0 * M_PI / 180.0;
94 
95  double LGC_pmt_z_pos = mirror_positions[3].z();//-30.0*cm;
96  double LGC_pmt_y_pos = mirror_positions[3].y();//LGC_outer_radius1 - 20.0*cm;
97  double LGC_pmt_array_size = 20.0*cm;
98 
99  // the gas tank
100  ConeSegment tank_main(0.5 * LGC_main_length, LGC_inner_radius1, LGC_outer_radius1,
101  LGC_inner_radius2, LGC_outer_radius1);
102  // M_PI / 2.0 - LGC_sector_angle / 2.0,
103  //M_PI / 2.0 + LGC_sector_angle / 2.0);
104  ConeSegment tank_snout(0.5 * LGC_snout_length, LGC_snout_inner_radius1, LGC_snout_outer_radius1,
105  LGC_snout_inner_radius2, LGC_snout_outer_radius2);
106  //M_PI / 2.0 - LGC_sector_angle / 2.0,
107  //M_PI / 2.0 + LGC_sector_angle / 2.0);
108  UnionSolid sidis_tank(tank_main,tank_snout,Position(0,0,-0.5 * LGC_main_length -0.5 * LGC_snout_length));
109  Volume v_lgc_tank("v_lgc_tank_gas", sidis_tank, N2cherenkov);
110  v_lgc_tank.setVisAttributes(desc,dd4hep::getAttrOrDefault(x_det, _Unicode(vis), "BlueVis"));
111 
112  // Everything that goes in the tank will be copies of the sector assembly volume
113  Assembly v_sector("cherenkov_sector_1");
114  DetElement de_sector("de_sector"+std::to_string(1),1);
115 
116  // mirrors
117  Sphere mirror1_shell(LGC_mirror1_radius, LGC_mirror1_radius + LGC_mirror1_thickness,
118  0.0, M_PI / 2);
119  Trd1 mirror1_cutout(LGC_mirror1_width1 / 2.0, LGC_mirror1_width2 / 2.0,
120  LGC_mirror1_length / 2.0, LGC_mirror1_length / 2.0);
121  IntersectionSolid mirror1_shape(mirror1_cutout, mirror1_shell,
122  RotationX(M_PI/2.0)*Transform3D(Position(0, 0, -LGC_mirror1_radius)));
123  Sphere mirror2_shell(LGC_mirror2_radius, LGC_mirror2_radius + LGC_mirror2_thickness,
124  0.0, M_PI / 2);
125  Trd1 mirror2_cutout(LGC_mirror2_width1 / 2.0, LGC_mirror2_width2 / 2.0,
126  LGC_mirror2_length / 2.0, LGC_mirror2_length / 2.0);
127  IntersectionSolid mirror2_shape(mirror2_cutout, mirror2_shell,
128  RotationX(M_PI/2.0)*Transform3D(Position(0, 0, -LGC_mirror2_radius)));
129 
130  double z_mirror1 = mirror_positions[1].z();
131  double z_mirror2 = mirror_positions[2].z();
132  double y_mirror1 = mirror_positions[1].y();
133  double y_mirror2 = mirror_positions[2].y();
134 
135  Volume v_mirror1_shape("v_mirror1_shape", mirror1_shape, PyrexGlass);
136  PlacedVolume pv_mirror1_shape = v_sector.placeVolume(
137  v_mirror1_shape, Transform3D(Position(0, y_mirror1, z_mirror1)) *
138  RotationX(-M_PI / 2.0 + LGC_mirror1_tilt_angle));
139 
140  DetElement de_mirror1_shape(det,"de_mirror1_shape"+std::to_string(1),1);
141  pv_mirror1_shape.addPhysVolID("mirror", 1);
142  de_mirror1_shape.setPlacement(pv_mirror1_shape);
143  sens.setType("photoncounter");
144  v_mirror1_shape.setSensitiveDetector(sens);
145 
146  Volume v_mirror2_shape("v_mirror2_shape", mirror2_shape, PyrexGlass);
147  PlacedVolume pv_mirror2_shape = v_sector.placeVolume(
148  v_mirror2_shape, Transform3D(Position(0, y_mirror2, z_mirror2)) *
149  RotationX(-M_PI / 2.0 + LGC_mirror2_tilt_angle));
150 
151  DetElement de_mirror2_shape(det,"de_mirror2_shape"+std::to_string(2),2);
152  pv_mirror2_shape.addPhysVolID("mirror", 2);
153  de_mirror2_shape.setPlacement(pv_mirror2_shape);
154  sens.setType("photoncounter");
155  v_mirror2_shape.setSensitiveDetector(sens);
156 
157  // ---------------
158  // Winston Cone
159  double LGC_winston_cone_thickness = 4*mm;
160  double LGC_winston_tube_inner_radius = 11.28*cm;
161  double LGC_winston_tube_length = 30.0*cm;
162  double LGC_winston_cone_length = 30.0*cm;
163  double LGC_winston_cone_inner_radius1 = 7.8*cm;
164  double LGC_winston_cone_inner_radius2 = 21.0*cm;
165  double LGC_winston_cone_inset_length = 7.90909*cm;
166  DetElement de_winston_cone(det,"de_winston_cone1",1);
167  Tube winston_tube(LGC_winston_tube_inner_radius,
168  LGC_winston_tube_inner_radius + LGC_winston_cone_thickness,
169  LGC_winston_tube_length / 2.0);
170  //Cone winston_cone(LGC_winston_cone_length / 2.0, LGC_winston_cone_inner_radius1,
171  // LGC_winston_cone_inner_radius1 + LGC_winston_cone_thickness,
172  // LGC_winston_cone_inner_radius2,
173  // LGC_winston_cone_inner_radius2 + LGC_winston_cone_thickness );
174  //UnionSolid winston_cone_solid(winston_tube,winston_cone,Position(0,0,LGC_winston_tube_length / 2.0 - LGC_winston_cone_inset_length));
175  Paraboloid winston_cone1(LGC_winston_cone_inner_radius1 + LGC_winston_cone_thickness,
176  LGC_winston_cone_inner_radius2 + LGC_winston_cone_thickness,
177  LGC_winston_cone_length / 2.0 );
178  Paraboloid winston_cone2(LGC_winston_cone_inner_radius1,
179  LGC_winston_cone_inner_radius2,
180  LGC_winston_cone_length / 2.0 );
181 
182  SubtractionSolid winston_cone(winston_cone1, winston_cone2);
183 
184  Volume v_winston_cone_solid("v_winston_cone_solid", winston_cone, PyrexGlass);
185  PlacedVolume pv_winston_cone_solid = v_sector.placeVolume(
186  v_winston_cone_solid, Transform3D(Position(0, LGC_pmt_y_pos, LGC_pmt_z_pos)) *
187  RotationX(LGC_pmt_tilt_angle) *
188  Transform3D(Position(0, 0, LGC_winston_tube_length / 2.0 + 5.0 * mm)));
189 
190  //std::cout << " LGC_pmt_y_pos/cm " << LGC_pmt_y_pos/cm << "\n";
191  //std::cout << " LGC_pmt_z_pos/cm " << LGC_pmt_z_pos/cm << "\n";
192  //mirrorPV.addPhysVolID("layer", 2).addPhysVolID("module", 1);
193  //mirror_DE.setPlacement(mirrorPV);
194  //sens.setType("photoncounter");
195  //mirrorVol.setSensitiveDetector(sens);
196 
198 
201  DetElement de_pmt_array(det, "PMT_DE", 1);
202  Box pmt_array(LGC_pmt_array_size / 2.0, LGC_pmt_array_size / 2.0, 5 * mm / 2.0);
203  Volume v_pmt_array("v_pmt_array", pmt_array, N2cherenkov);
204  PlacedVolume pv_pmt_array =
205  v_sector.placeVolume(v_pmt_array, Transform3D(Position(0, LGC_pmt_y_pos, LGC_pmt_z_pos)) *
206  RotationX(LGC_pmt_tilt_angle));
207 
208  pv_pmt_array.addPhysVolID("mirror", 3);
209  de_pmt_array.setPlacement(pv_pmt_array);
210  sens.setType("photoncounter");
211  v_pmt_array.setSensitiveDetector(sens);
212 
213  // copper layer inside to stop photons
214  Box pmt_array_backing(LGC_pmt_array_size/2.0, LGC_pmt_array_size/2.0, 1*mm/2.0);
215  Volume v_pmt_array_backing("v_pmt_array_backing", pmt_array_backing, Copper);
216  PlacedVolume pv_pmt_array_backing = v_pmt_array.placeVolume(v_pmt_array_backing, Position(0,0,0));
217 
218  // Optical Surfaces
219 
220  OpticalSurfaceManager surfMgr = desc.surfaceManager();
221  OpticalSurface mirrorSurf = surfMgr.opticalSurface("MirrorOpticalSurface");
222  OpticalSurface pmtSurf = surfMgr.opticalSurface("PMTOpticalSurface");
223  //BorderSurface mirrorBorder_Surf = BorderSurface(desc, det, "RICHmirror", mirrorSurf, mirrorPV, envPV);
224  SkinSurface mirrorBorder_Surf(desc,de_mirror1_shape,"LGCmirror", mirrorSurf, v_mirror1_shape);
225  SkinSurface winstonBorder_Surf(desc,de_winston_cone,"LGCWinstonCone", mirrorSurf, v_winston_cone_solid);
226  SkinSurface pmtBorder_Surf(desc,de_pmt_array,"LGCPMTsurface", pmtSurf, v_pmt_array);
227  //BorderSurface bubbleSurf = BorderSurface(description, sdet, "TankBubble", airSurf, bubblePlace, tankPlace);
228  mirrorBorder_Surf.isValid();
229  winstonBorder_Surf.isValid();
230  pmtBorder_Surf.isValid();
231  //tankSurf.isValid();
232 
233 
234  // all sectors
235  for (int i_sector = 1; i_sector <= 30; i_sector++) {
236  //std::cout << i_sector << " sector\n";
237  PlacedVolume pv =
238  v_lgc_tank.placeVolume(v_sector, Transform3D(RotationZ((i_sector - 1) * LGC_sector_angle)));
239  pv.addPhysVolID("sector", i_sector);
240  auto amod = (i_sector == 1 ? de_sector : de_sector.clone("de_sector" + std::to_string(i_sector), i_sector));
241  amod.setPlacement(pv);
242  det.add(amod);
243  }
244 
245 
247 
248 
249  Volume motherVol = desc.pickMotherVolume(det);
250  PlacedVolume envPV = motherVol.placeVolume(v_lgc_tank, Position(pos_x, pos_y, pos_z));
251  envPV.addPhysVolID("system", detID);
252  det.setPlacement(envPV);
253 
254  return det;
255 }
257 // clang-format off
258 DECLARE_DETELEMENT(ThresholdGasCherenkov, createDetector)
259 
static Ref_t createDetector(Detector &desc, xml::Handle_t handle, SensitiveDetector sens)
Detector
Definition: DDG4.py:69
Namespace for the AIDA detector description toolkit.