File indexing completed on 2025-01-18 09:14:57
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 mod_z = layering.totalThickness();
0038 double outer_r = inner_r + mod_z;
0039 double totThick = mod_z;
0040 DetElement sdet (det_name,det_id);
0041 Volume motherVol = description.pickMotherVolume(sdet);
0042 double z_offset = x_dim.hasAttr(_U(z_offset)) ? x_dim.z_offset() : 0.0;
0043 PolyhedraRegular hedra (nsides,inner_r,inner_r+totThick+tolerance*2e0,x_dim.z());
0044 Volume envelope (det_name,hedra,air);
0045 PlacedVolume env_phv = motherVol.placeVolume(envelope,Transform3D (RotationZ(M_PI / nsides), Translation3D(0, 0, z_offset)) );
0046
0047 env_phv.addPhysVolID("system",det_id);
0048 env_phv.addPhysVolID("barrel",0);
0049 sdet.setPlacement(env_phv);
0050
0051 DetElement stave_det("stave0",det_id);
0052 double dx = 0.0;
0053
0054
0055 double trd_x2 = (2 * std::tan(hphi) * outer_r - dx)/2 - tolerance;
0056 double trd_x1 = (2 * std::tan(hphi) * inner_r + dx)/2 - tolerance;
0057 double trd_y1 = x_dim.z()/2 - tolerance;
0058 double trd_y2 = trd_y1;
0059 double trd_z = mod_z/2 - tolerance;
0060
0061
0062 Trapezoid trd(trd_x1,
0063 trd_x2,
0064 trd_y1,
0065 trd_y2,
0066 trd_z);
0067
0068 Volume mod_vol("stave",trd,air);
0069
0070 sens.setType("calorimeter");
0071 {
0072
0073 double stave_z = trd_y1/2;
0074 double l_dim_x = trd_x1/2;
0075 double adj = (l_dim_x-trd_x2/2)/2;
0076 double hyp = std::sqrt(trd_z*trd_z/4 + adj*adj);
0077 double beta = std::acos(adj / hyp);
0078 double tan_beta = std::tan(beta);
0079 double l_pos_z = -(layering.totalThickness() / 2);
0080
0081
0082 int l_num = 1;
0083 for(xml_coll_t li(x_det,_U(layer)); li; ++li) {
0084 xml_comp_t x_layer = li;
0085 int repeat = x_layer.repeat();
0086
0087 for (int j=0; j<repeat; j++) {
0088 string l_name = _toString(l_num,"layer%d");
0089 double l_thickness = layering.layer(l_num-1)->thickness();
0090 double xcut = (l_thickness / tan_beta);
0091 l_dim_x -= xcut/2;
0092
0093 Position l_pos(0,0,l_pos_z+l_thickness/2);
0094 Box l_box(l_dim_x*2-tolerance,stave_z*2-tolerance,l_thickness-tolerance);
0095 Volume l_vol(l_name,l_box,air);
0096 DetElement layer(stave_det, l_name, det_id);
0097
0098
0099 int s_num = 1;
0100 double s_pos_z = -(l_thickness / 2);
0101 for(xml_coll_t si(x_layer,_U(slice)); si; ++si) {
0102 xml_comp_t x_slice = si;
0103 string s_name = _toString(s_num,"slice%d");
0104 double s_thick = x_slice.thickness();
0105 Box s_box(l_dim_x*2-tolerance,stave_z*2-tolerance,s_thick-tolerance);
0106 Volume s_vol(s_name,s_box,description.material(x_slice.materialStr()));
0107 DetElement slice(layer,s_name,det_id);
0108
0109 if ( x_slice.isSensitive() ) {
0110 s_vol.setSensitiveDetector(sens);
0111 }
0112 slice.setAttributes(description,s_vol,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
0113
0114
0115 PlacedVolume slice_phv = l_vol.placeVolume(s_vol,Position(0,0,s_pos_z+s_thick/2));
0116 slice_phv.addPhysVolID("slice", s_num);
0117 slice.setPlacement(slice_phv);
0118
0119 s_pos_z += s_thick;
0120
0121
0122 ++s_num;
0123 }
0124
0125
0126 layer.setAttributes(description,l_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
0127
0128 PlacedVolume layer_phv = mod_vol.placeVolume(l_vol,l_pos);
0129 layer_phv.addPhysVolID("layer", l_num);
0130 layer.setPlacement(layer_phv);
0131
0132 l_pos_z += l_thickness;
0133 ++l_num;
0134 }
0135 }
0136 }
0137
0138
0139 if ( x_staves ) {
0140 mod_vol.setVisAttributes(description.visAttributes(x_staves.visStr()));
0141 }
0142
0143 double phi = M_PI / nsides;
0144 double mod_x_off = dx / 2;
0145 double mod_y_off = inner_r + mod_z/2;
0146
0147
0148 for (int i = 0; i < nsides; i++, phi -= dphi) {
0149
0150 double m_pos_x = mod_x_off * std::cos(phi) - mod_y_off * std::sin(phi);
0151 double m_pos_y = mod_x_off * std::sin(phi) + mod_y_off * std::cos(phi);
0152 Transform3D tr(RotationZYX(0,phi,M_PI*0.5),Translation3D(-m_pos_x,-m_pos_y,0));
0153 PlacedVolume pv = envelope.placeVolume(mod_vol,tr);
0154 pv.addPhysVolID("system",det_id);
0155 pv.addPhysVolID("barrel",0);
0156 pv.addPhysVolID("module",i+1);
0157 DetElement sd = i==0 ? stave_det : stave_det.clone(_toString(i,"stave%d"));
0158 sd.setPlacement(pv);
0159 sdet.add(sd);
0160 }
0161
0162
0163 envelope.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
0164 return sdet;
0165 }
0166
0167 DECLARE_DETELEMENT(Lhe_EcalBarrel,create_detector)