File indexing completed on 2024-09-27 07:02:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include "DD4hep/DetFactoryHelper.h"
0018 #include "XML/Layering.h"
0019
0020 using namespace std;
0021 using namespace dd4hep;
0022 using namespace dd4hep::detail;
0023
0024 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0025 static double tolerance = 0e0;
0026 Layering layering (e);
0027 xml_det_t x_det = e;
0028 Material air = description.air();
0029 int det_id = x_det.id();
0030 string det_name = x_det.nameStr();
0031 xml_comp_t x_staves = x_det.staves();
0032 xml_comp_t x_dim = x_det.dimensions();
0033 int nsides = x_dim.numsides();
0034 double inner_r = x_dim.rmin();
0035 double dphi = (2*M_PI/nsides);
0036 double hphi = dphi/2;
0037 double support_thickness = 0.0;
0038 if(x_staves.hasChild("support")){
0039 support_thickness = getAttrOrDefault(x_staves.child(_U(support)), _U(thickness), 5.0 * cm);
0040 }
0041 double mod_z = layering.totalThickness() + support_thickness;
0042 double outer_r = inner_r + mod_z;
0043 double totThick = mod_z;
0044 double offset = x_det.attr<double>(_Unicode(offset));
0045 DetElement sdet (det_name,det_id);
0046 Volume motherVol = description.pickMotherVolume(sdet);
0047 PolyhedraRegular hedra (nsides,inner_r,inner_r+totThick+tolerance*2e0,x_dim.z());
0048 Volume envelope (det_name,hedra,air);
0049 PlacedVolume env_phv = motherVol.placeVolume(envelope,Transform3D(Translation3D(0,0,offset)*RotationZ(M_PI/nsides)));
0050
0051 env_phv.addPhysVolID("system",det_id);
0052 env_phv.addPhysVolID("barrel",0);
0053 sdet.setPlacement(env_phv);
0054
0055 DetElement stave_det("stave0",det_id);
0056 double dx = 0.0;
0057
0058
0059 double trd_x2 = (2 * std::tan(hphi) * outer_r - dx)/2 - tolerance;
0060 double trd_x1 = (2 * std::tan(hphi) * inner_r + dx)/2 - tolerance;
0061 double trd_y1 = x_dim.z()/2 - tolerance;
0062 double trd_y2 = trd_y1;
0063 double trd_z = mod_z/2 - tolerance;
0064
0065
0066 Trapezoid trd(trd_x1,
0067 trd_x2,
0068 trd_y1,
0069 trd_y2,
0070 trd_z);
0071
0072 Volume mod_vol("stave",trd,air);
0073 double l_pos_z = -(layering.totalThickness() / 2) - support_thickness/2.0;
0074
0075
0076 double trd_x1_support = (2 * std::tan(hphi) * outer_r - dx- support_thickness)/2 - tolerance;
0077
0078 Solid support_frame_s;
0079
0080 if(x_staves.hasChild("support")){
0081 xml_comp_t x_support = x_staves.child(_U(support));
0082
0083 bool is_inside_support = getAttrOrDefault<bool>(x_support, _Unicode(inside), true);
0084
0085 int n_beams = getAttrOrDefault<int>(x_support, _Unicode(n_beams), 3);
0086 double beam_thickness = support_thickness / 4.0;
0087 trd_x1_support = (2 * std::tan(hphi) * (outer_r - support_thickness + beam_thickness)) / 2 - tolerance;
0088 double grid_size = getAttrOrDefault(x_support, _Unicode(grid_size), 25.0 * cm);
0089 double beam_width = 2.0 * trd_x1_support / (n_beams + 1);
0090
0091 double cross_beam_thickness = support_thickness/4.0;
0092
0093 double trd_x2_support = trd_x2;
0094
0095 int n_cross_supports = std::floor((trd_y1-cross_beam_thickness)/grid_size);
0096
0097 Box beam_vert_s(beam_thickness / 2.0 - tolerance, trd_y1, support_thickness / 2.0 - tolerance);
0098 Box beam_hori_s(beam_width / 2.0 - tolerance, trd_y1, beam_thickness / 2.0 - tolerance);
0099 UnionSolid T_beam_s(beam_vert_s, beam_hori_s, Position(0, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
0100
0101
0102 Trapezoid trd_support(trd_x1_support,trd_x2_support,
0103 beam_thickness / 2.0 - tolerance, beam_thickness / 2.0 - tolerance,
0104 support_thickness / 2.0 - tolerance - cross_beam_thickness/2.0);
0105 UnionSolid support_array_start_s(T_beam_s,trd_support,Position(0,0,cross_beam_thickness/2.0));
0106 for (int isup = 0; isup < n_cross_supports; isup++) {
0107 support_array_start_s = UnionSolid(support_array_start_s, trd_support, Position(0, -1.0 * isup * grid_size, cross_beam_thickness/2.0));
0108 support_array_start_s = UnionSolid(support_array_start_s, trd_support, Position(0, 1.0 * isup * grid_size, cross_beam_thickness/2.0));
0109 }
0110 support_array_start_s =
0111 UnionSolid(support_array_start_s, beam_hori_s,
0112 Position(-1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
0113 support_array_start_s =
0114 UnionSolid(support_array_start_s, beam_hori_s,
0115 Position(1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, -support_thickness / 2.0 + beam_thickness / 2.0));
0116 support_array_start_s =
0117 UnionSolid(support_array_start_s, beam_vert_s, Position(-1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, 0));
0118 support_array_start_s =
0119 UnionSolid(support_array_start_s, beam_vert_s, Position(1.8 * 0.5*(trd_x1+trd_x2_support) / n_beams, 0, 0));
0120
0121 support_frame_s = support_array_start_s;
0122
0123 Material support_mat = description.material(x_support.materialStr());
0124 Volume support_vol("support_frame_v", support_frame_s, support_mat);
0125 support_vol.setVisAttributes(description,x_support.visStr());
0126
0127
0128
0129 auto pv = mod_vol.placeVolume(support_vol, Position(0.0, 0.0, -l_pos_z - support_thickness / 2.0));
0130 }
0131
0132
0133 sens.setType("calorimeter");
0134 {
0135
0136 double stave_z = trd_y1;
0137 double tan_hphi = std::tan(hphi);
0138 double l_dim_x = trd_x1;
0139
0140
0141 int l_num = 1;
0142 for(xml_coll_t li(x_det,_U(layer)); li; ++li) {
0143 xml_comp_t x_layer = li;
0144 int repeat = x_layer.repeat();
0145
0146 for (int j=0; j<repeat; j++) {
0147 string l_name = _toString(l_num,"layer%d");
0148 double l_thickness = layering.layer(l_num-1)->thickness();
0149
0150 Position l_pos(0,0,l_pos_z+l_thickness/2);
0151 Box l_box(l_dim_x-tolerance,stave_z-tolerance,l_thickness / 2-tolerance);
0152 Volume l_vol(l_name,l_box,air);
0153 DetElement layer(stave_det, l_name, det_id);
0154
0155
0156 int s_num = 1;
0157 double s_pos_z = -(l_thickness / 2);
0158 for(xml_coll_t si(x_layer,_U(slice)); si; ++si) {
0159 xml_comp_t x_slice = si;
0160 string s_name = _toString(s_num,"slice%d");
0161 double s_thick = x_slice.thickness();
0162 Box s_box(l_dim_x-tolerance,stave_z-tolerance,s_thick / 2-tolerance);
0163 Volume s_vol(s_name,s_box,description.material(x_slice.materialStr()));
0164 DetElement slice(layer,s_name,det_id);
0165
0166 if ( x_slice.isSensitive() ) {
0167 s_vol.setSensitiveDetector(sens);
0168 }
0169 slice.setAttributes(description,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
0170
0171
0172 PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2));
0173 slice_phv.addPhysVolID("slice", s_num);
0174 slice.setPlacement(slice_phv);
0175
0176 s_pos_z += s_thick;
0177
0178
0179 ++s_num;
0180 }
0181
0182
0183 layer.setAttributes(description,l_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
0184
0185 PlacedVolume layer_phv = mod_vol.placeVolume(l_vol,l_pos);
0186 layer_phv.addPhysVolID("layer", l_num);
0187 layer.setPlacement(layer_phv);
0188
0189 double xcut = l_thickness * tan_hphi;
0190 l_dim_x += xcut;
0191 l_pos_z += l_thickness;
0192 ++l_num;
0193 }
0194 }
0195 }
0196
0197
0198 if ( x_staves ) {
0199 mod_vol.setVisAttributes(description.visAttributes(x_staves.visStr()));
0200
0201 }
0202
0203 double phi = M_PI / nsides;
0204 double mod_x_off = dx / 2;
0205 double mod_y_off = inner_r + mod_z/2;
0206
0207
0208 for (int i = 0; i < nsides; i++, phi -= dphi) {
0209
0210 double m_pos_x = mod_x_off * std::cos(phi) - mod_y_off * std::sin(phi);
0211 double m_pos_y = mod_x_off * std::sin(phi) + mod_y_off * std::cos(phi);
0212 Transform3D tr(RotationZYX(0,phi,M_PI*0.5),Translation3D(-m_pos_x,-m_pos_y,0));
0213 PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
0214 pv.addPhysVolID("system",det_id);
0215 pv.addPhysVolID("barrel",0);
0216 pv.addPhysVolID("module",i+1);
0217 DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d"));
0218 sd.setPlacement(pv);
0219 sdet.add(sd);
0220 }
0221
0222
0223 envelope.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
0224 return sdet;
0225 }
0226
0227 DECLARE_DETELEMENT(athena_EcalBarrel,create_detector)
0228 DECLARE_DETELEMENT(athena_HcalBarrel,create_detector)