File indexing completed on 2025-01-18 09:14:02
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 void placeStaves(DetElement& parent, DetElement& stave, double rmin, int numsides, double total_thickness,
0025 Volume envelopeVolume, double innerAngle, Volume sectVolume) {
0026 double innerRotation = innerAngle;
0027 double offsetRotation = -innerRotation / 2;
0028 double sectCenterRadius = rmin + total_thickness / 2;
0029 double rotX = M_PI / 2;
0030 double rotY = -offsetRotation;
0031 double posX = -sectCenterRadius * std::sin(rotY);
0032 double posY = sectCenterRadius * std::cos(rotY);
0033
0034 for (int module = 1; module <= numsides; ++module) {
0035 DetElement det = module > 1 ? stave.clone(_toString(module,"stave%d")) : stave;
0036 Transform3D trafo(RotationZYX(0, rotY, rotX), Translation3D(-posX, -posY, 0));
0037 PlacedVolume pv = envelopeVolume.placeVolume(sectVolume,trafo);
0038
0039 pv.addPhysVolID("module", module);
0040 det.setPlacement(pv);
0041 parent.add(det);
0042 rotY -= innerRotation;
0043 posX = -sectCenterRadius * std::sin(rotY);
0044 posY = sectCenterRadius * std::cos(rotY);
0045 }
0046 }
0047
0048 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector sens) {
0049 xml_det_t x_det = e;
0050 Layering layering(x_det);
0051 xml_comp_t staves = x_det.staves();
0052 xml_dim_t dim = x_det.dimensions();
0053 string det_name = x_det.nameStr();
0054 Material air = description.air();
0055 double totalThickness = layering.totalThickness();
0056 double gap = xml_dim_t(x_det).gap();
0057 int numSides = dim.numsides();
0058 double detZ = dim.z();
0059 double rmin = dim.rmin();
0060 DetElement sdet(det_name, x_det.id());
0061 DetElement stave("stave1", x_det.id());
0062 Volume motherVol = description.pickMotherVolume(sdet);
0063
0064 #if 0
0065 int totalRepeat = 0;
0066 int totalSlices = 0;
0067 for (xml_coll_t c(x_det, _U(layer)); c; ++c) {
0068 xml_comp_t x_layer = c;
0069 int repeat = x_layer.repeat();
0070 totalRepeat += repeat;
0071 totalSlices += x_layer.numChildren(_U(slice));
0072 }
0073 #endif
0074 PolyhedraRegular polyhedra(numSides, rmin, rmin + totalThickness, detZ);
0075 Volume envelopeVol(det_name, polyhedra, air);
0076
0077
0078 double innerAngle = 2 * M_PI / numSides;
0079 double halfInnerAngle = innerAngle / 2;
0080 double tan_inner = std::tan(halfInnerAngle) * 2;
0081 double innerFaceLen = rmin * tan_inner;
0082 double outerFaceLen = (rmin + totalThickness) * tan_inner;
0083 double staveThickness = totalThickness;
0084
0085 Trapezoid staveTrdOuter(innerFaceLen / 2, outerFaceLen / 2, detZ / 2, detZ / 2, staveThickness / 2);
0086 Volume staveOuterVol("stave_outer", staveTrdOuter, air);
0087
0088 Trapezoid staveTrdInner(innerFaceLen / 2 - gap, outerFaceLen / 2 - gap, detZ / 2, detZ / 2, staveThickness / 2);
0089 Volume staveInnerVol("stave_inner", staveTrdInner, air);
0090
0091 double layerOuterAngle = (M_PI - innerAngle) / 2;
0092 double layerInnerAngle = (M_PI / 2 - layerOuterAngle);
0093 double layer_pos_z = -(staveThickness / 2);
0094 double layer_dim_x = innerFaceLen / 2 - gap * 2;
0095 int layer_num = 1;
0096
0097
0098
0099
0100 for (xml_coll_t xc(x_det, _U(layer)); xc; ++xc) {
0101 xml_comp_t x_layer = xc;
0102 int repeat = x_layer.repeat();
0103 const Layer* lay = layering.layer(layer_num - 1);
0104
0105 for (int j = 0; j < repeat; j++) {
0106 string layer_name = _toString(layer_num, "layer%d");
0107 double layer_thickness = lay->thickness();
0108 DetElement layer(stave, layer_name, layer_num);
0109
0110
0111
0112 layer_pos_z += layer_thickness / 2;
0113
0114 Volume layer_vol(layer_name, Box(layer_dim_x, detZ / 2, layer_thickness / 2), air);
0115
0116
0117 double slice_pos_z = -(layer_thickness / 2);
0118 int slice_number = 1;
0119 for (xml_coll_t xk(x_layer, _U(slice)); xk; ++xk) {
0120 xml_comp_t x_slice = xk;
0121 string slice_name = _toString(slice_number, "slice%d");
0122 double slice_thickness = x_slice.thickness();
0123 Material slice_material = description.material(x_slice.materialStr());
0124 DetElement slice(layer, slice_name, slice_number);
0125
0126 slice_pos_z += slice_thickness / 2;
0127
0128 Volume slice_vol(slice_name, Box(layer_dim_x, detZ / 2, slice_thickness / 2), slice_material);
0129
0130 if (x_slice.isSensitive()) {
0131 sens.setType("calorimeter");
0132 slice_vol.setSensitiveDetector(sens);
0133 }
0134
0135 slice_vol.setAttributes(description, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0136
0137 PlacedVolume slice_phv = layer_vol.placeVolume(slice_vol, Position(0, 0, slice_pos_z));
0138 slice_phv.addPhysVolID("slice", slice_number);
0139
0140 slice.setPlacement(slice_phv);
0141
0142 slice_pos_z += slice_thickness / 2;
0143
0144 ++slice_number;
0145 }
0146
0147 layer_vol.setAttributes(description, x_layer.regionStr(), x_layer.limitsStr(), x_layer.visStr());
0148
0149
0150 PlacedVolume layer_phv = staveInnerVol.placeVolume(layer_vol, Position(0, 0, layer_pos_z));
0151 layer_phv.addPhysVolID("layer", layer_num);
0152 layer.setPlacement(layer_phv);
0153
0154
0155 layer_dim_x += layer_thickness * std::tan(layerInnerAngle);
0156
0157 layer_pos_z += layer_thickness / 2;
0158
0159 ++layer_num;
0160 }
0161 }
0162
0163
0164 staveOuterVol.placeVolume(staveInnerVol);
0165 if ( staves ) {
0166
0167 stave.setVisAttributes(description, staves.visStr(), staveInnerVol);
0168 stave.setVisAttributes(description, staves.visStr(), staveOuterVol);
0169 }
0170
0171 placeStaves(sdet, stave, rmin, numSides, totalThickness, envelopeVol, innerAngle, staveOuterVol);
0172
0173 envelopeVol.setAttributes(description, x_det.regionStr(), x_det.limitsStr(), x_det.visStr());
0174
0175 double z_offset = dim.hasAttr(_U(z_offset)) ? dim.z_offset() : 0.0;
0176 Transform3D transform(RotationZ(M_PI / numSides), Translation3D(0, 0, z_offset));
0177 PlacedVolume env_phv = motherVol.placeVolume(envelopeVol, transform);
0178 env_phv.addPhysVolID("system", sdet.id());
0179 env_phv.addPhysVolID("barrel", 0);
0180 sdet.setPlacement(env_phv);
0181
0182
0183
0184 return sdet;
0185 }
0186
0187 DECLARE_DETELEMENT(DD4hep_PolyhedraBarrelCalorimeter2, create_detector)