File indexing completed on 2025-01-18 09:14:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "DD4hep/DetFactoryHelper.h"
0015 #include "XML/Layering.h"
0016 #include <limits>
0017
0018 using namespace dd4hep;
0019
0020 static void placeStaves(DetElement& parent,
0021 DetElement& stave,
0022 double rmin,
0023 int numsides,
0024 double total_thickness,
0025 Volume envelopeVolume,
0026 double innerAngle,
0027 Volume sectVolume)
0028 {
0029 double innerRotation = innerAngle;
0030 double offsetRotation = -innerRotation / 2;
0031 double sectCenterRadius = rmin + total_thickness / 2;
0032 double rotX = M_PI / 2;
0033 double rotY = -offsetRotation;
0034 double posX = -sectCenterRadius * std::sin(rotY);
0035 double posY = sectCenterRadius * std::cos(rotY);
0036
0037 for (int module = 1; module <= numsides; ++module) {
0038 DetElement det = module>1 ? stave.clone(_toString(module,"stave%d")) : stave;
0039 PlacedVolume pv = envelopeVolume.placeVolume(sectVolume,Transform3D(RotationZYX(0,rotY,rotX),
0040 Translation3D(-posX,-posY,0)));
0041
0042 pv.addPhysVolID("module",module);
0043 det.setPlacement(pv);
0044 parent.add(det);
0045 rotY -= innerRotation;
0046 posX = -sectCenterRadius * std::sin(rotY);
0047 posY = sectCenterRadius * std::cos(rotY);
0048 }
0049 }
0050
0051 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0052 xml_det_t x_det = e;
0053 Layering layering(x_det);
0054
0055 xml_dim_t dim = x_det.dimensions();
0056 std::string det_name = x_det.nameStr();
0057 Material air = description.air();
0058 double totalThickness = layering.totalThickness();
0059 int numSides = dim.numsides();
0060 double detZ = dim.z();
0061 double rmin = dim.rmin();
0062 double rmax = dim.rmax();
0063 DetElement sdet(det_name,x_det.id());
0064 DetElement stave("stave1",x_det.id());
0065 Volume motherVol = description.pickMotherVolume(sdet);
0066 PolyhedraRegular polyhedron(numSides,0.,rmin,detZ+10);
0067 Tube tube(0.,rmin+totalThickness,detZ/2,0,2*M_PI);
0068 SubtractionSolid sub(tube,polyhedron);
0069 Volume envelopeVol(det_name+"_envelope",sub,air);
0070
0071
0072 double externalAngle = 2*M_PI/numSides;
0073 double halfExternalAngle = externalAngle/2;
0074 double tan_external = std::tan(externalAngle);
0075 double tan_half = std::tan(halfExternalAngle);
0076
0077 double half_polyFace = rmin * tan_half;
0078
0079 double innerFaceLen = std::sqrt(rmax*rmax - rmin*rmin)+half_polyFace;
0080
0081 double staveThickness = totalThickness;
0082
0083
0084
0085 Assembly staveOuterVol(det_name+"_stave");
0086
0087
0088
0089
0090
0091
0092 double layer_pos_z = -(staveThickness / 2);
0093 double layer_pos_x = 0;
0094
0095 double layer_dim_x = innerFaceLen/2;
0096 int layer_num = 1;
0097
0098 double layerR = rmin;
0099
0100
0101 envelopeVol.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr());
0102
0103 for(xml_coll_t c(x_det,_U(layer)); c; ++c) {
0104 xml_comp_t x_layer = c;
0105 int repeat = x_layer.repeat();
0106 const Layer* lay = layering.layer(layer_num-1);
0107
0108 for (int j = 0; j < repeat; j++) {
0109 std::string layer_name = det_name+_toString(layer_num,"_layer%d");
0110 double layer_thickness = lay->thickness();
0111 DetElement layer(stave,_toString(layer_num,"layer%d"),x_det.id());
0112
0113
0114 layer_pos_z += layer_thickness / 2;
0115
0116 Volume layer_vol(layer_name, Box(layer_dim_x,detZ/2,layer_thickness/2), air);
0117
0118
0119 double slice_pos_z = -(layer_thickness / 2);
0120 int slice_number = 1;
0121 for(xml_coll_t k(x_layer,_U(slice)); k; ++k) {
0122 xml_comp_t x_slice = k;
0123 std::string slice_name = layer_name + _toString(slice_number,"_slice%d");
0124 double slice_thickness = x_slice.thickness();
0125 Material slice_material = description.material(x_slice.materialStr());
0126 DetElement slice(layer,_toString(slice_number,"slice%d"),x_det.id());
0127
0128 slice_pos_z += slice_thickness / 2;
0129
0130 Volume slice_vol(slice_name,Box(layer_dim_x,detZ/2,slice_thickness/2),slice_material);
0131
0132 if ( x_slice.isSensitive() ) {
0133 sens.setType("calorimeter");
0134 slice_vol.setSensitiveDetector(sens);
0135 }
0136
0137 slice_vol.setAttributes(description,x_slice.regionStr(),x_slice.limitsStr(),x_slice.visStr());
0138
0139 PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol,Position(0,0,slice_pos_z));
0140 slice_phv.addPhysVolID("slice",slice_number);
0141
0142 slice.setPlacement(slice_phv);
0143
0144 slice_pos_z += slice_thickness / 2;
0145
0146 ++slice_number;
0147 }
0148
0149 layer_vol.setAttributes(description,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr());
0150
0151
0152 PlacedVolume layer_phv = staveOuterVol.placeVolume(layer_vol,Position((layer_dim_x+layer_pos_x-half_polyFace),0,layer_pos_z));
0153 layer_phv.addPhysVolID("layer",layer_num);
0154 layer.setPlacement(layer_phv);
0155
0156 layerR += layer_thickness;
0157
0158 layer_pos_x = (layerR-rmin)/tan_external;
0159 layer_dim_x = (std::sqrt(rmax*rmax - layerR*layerR)+half_polyFace - layer_pos_x)/2.0;
0160 std::cout << "Rmin: " << rmin << " Rmax: " << rmax
0161 << " half_polyFace: " << half_polyFace
0162 << " Layer " << layer_num << " layerR: " << layerR << " layer_dim_x:" << layer_dim_x
0163 << std::endl;
0164
0165 layer_pos_z += layer_thickness / 2;
0166
0167 ++layer_num;
0168 }
0169 }
0170
0171
0172
0173
0174
0175
0176 placeStaves(sdet,stave,rmin,numSides,totalThickness,envelopeVol,externalAngle,staveOuterVol);
0177
0178 double z_offset = dim.hasAttr(_U(z_offset)) ? dim.z_offset() : 0.0;
0179 Transform3D transform(RotationZ(M_PI-(M_PI/numSides)),Translation3D(0,0,z_offset));
0180 PlacedVolume env_phv = motherVol.placeVolume(envelopeVol,transform);
0181 env_phv.addPhysVolID("system", sdet.id());
0182 env_phv.addPhysVolID("barrel", 0);
0183 sdet.setPlacement(env_phv);
0184
0185
0186 return sdet;
0187 }
0188
0189 DECLARE_DETELEMENT(SectorBarrelCalorimeter,create_detector)