1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/Printout.h"
3 #include <XML/Helper.h>
5 #include "DDRec/Surface.h"
7 #include "DD4hep/OpticalSurfaces.h"
8 #include "DDRec/DetectorData.h"
12 using namespace dd4hep::rec;
30 xml::DetElement detElem = handle;
31 xml_det_t x_det = handle;
33 std::string detName = detElem.nameStr();
34 int detID = detElem.id();
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();
44 std::map<int,Position> mirror_positions;
45 std::map<int,std::array<double,3>> mirror_rotations;
47 for(xml_coll_t i(x_det,Unicode(
"mirror")); i; ++i){
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()};
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();
61 Material air = desc.air();
62 Material PyrexGlass = desc.material(
"PyrexGlass");
63 Material N2cherenkov = desc.material(
"N2cherenkov");
64 Material Copper = desc.material(
"Copper");
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;
76 double LGC_exit_window_thickness = 0.1*mm;
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;
88 double LGC_sector_angle = M_PI * 15.0 / 180.0;
91 double LGC_mirror1_tilt_angle = mirror_rotations[1][0];
92 double LGC_mirror2_tilt_angle = mirror_rotations[2][0];
93 double LGC_pmt_tilt_angle = mirror_rotations[3][0];
95 double LGC_pmt_z_pos = mirror_positions[3].z();
96 double LGC_pmt_y_pos = mirror_positions[3].y();
97 double LGC_pmt_array_size = 20.0*cm;
100 ConeSegment tank_main(0.5 * LGC_main_length, LGC_inner_radius1, LGC_outer_radius1,
101 LGC_inner_radius2, LGC_outer_radius1);
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);
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"));
113 Assembly v_sector(
"cherenkov_sector_1");
114 DetElement de_sector(
"de_sector"+std::to_string(1),1);
117 Sphere mirror1_shell(LGC_mirror1_radius, LGC_mirror1_radius + LGC_mirror1_thickness,
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,
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)));
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();
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));
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);
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));
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);
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);
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 );
182 SubtractionSolid winston_cone(winston_cone1, winston_cone2);
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)));
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));
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);
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));
220 OpticalSurfaceManager surfMgr = desc.surfaceManager();
221 OpticalSurface mirrorSurf = surfMgr.opticalSurface(
"MirrorOpticalSurface");
222 OpticalSurface pmtSurf = surfMgr.opticalSurface(
"PMTOpticalSurface");
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);
228 mirrorBorder_Surf.isValid();
229 winstonBorder_Surf.isValid();
230 pmtBorder_Surf.isValid();
235 for (
int i_sector = 1; i_sector <= 30; i_sector++) {
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);
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);