File indexing completed on 2025-10-25 07:59:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "DD4hep/DetFactoryHelper.h"
0013 #include "DD4hep/Printout.h"
0014 #include "TMath.h"
0015 #include <XML/Helper.h>
0016
0017 using namespace std;
0018 using namespace dd4hep;
0019
0020 static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector ) {
0021
0022 using namespace ROOT::Math;
0023 xml_det_t x_det = e;
0024 string det_name = x_det.nameStr();
0025 DetElement sdet(det_name, x_det.id());
0026 Assembly assembly(det_name + "_assembly");
0027 Material m_Al = description.material("Aluminum");
0028 Material m_Vacuum = description.material("Vacuum");
0029 string vis_name = dd4hep::getAttrOrDefault<std::string>(x_det, _Unicode(vis), "BeamPipeVis");
0030 double thickness = getAttrOrDefault<double>(x_det, _Unicode(wall_thickness), 0);
0031 double bendRadius = 0.00001 * mm;
0032
0033 vector<string> names;
0034 vector<int> ids;
0035 vector<double> xCenters;
0036 vector<double> zCenters;
0037 vector<double> lengths;
0038 vector<double> thetas;
0039 vector<double> rOuters1;
0040 vector<double> rOuters2;
0041 vector<double> bendLengths;
0042
0043
0044 for (xml_coll_t pipe_coll(x_det, _Unicode(pipe)); pipe_coll; pipe_coll++) {
0045
0046 xml_comp_t pipe(pipe_coll);
0047
0048 names.push_back(getAttrOrDefault<string>(pipe, _Unicode(name), ""));
0049 ids.push_back(getAttrOrDefault<int>(pipe, _Unicode(id), 0));
0050
0051
0052 xCenters.push_back(getAttrOrDefault<double>(pipe, _Unicode(xcenter), 0));
0053 zCenters.push_back(getAttrOrDefault<double>(pipe, _Unicode(zcenter), 0));
0054 lengths.push_back(getAttrOrDefault<double>(pipe, _Unicode(length), 0));
0055 thetas.push_back(getAttrOrDefault<double>(pipe, _Unicode(theta), 0));
0056 rOuters1.push_back(getAttrOrDefault<double>(pipe, _Unicode(rout1), 0));
0057 rOuters2.push_back(getAttrOrDefault<double>(pipe, _Unicode(rout2), 0));
0058 }
0059
0060
0061 for (uint pipeN = 0; pipeN < names.size(); pipeN++) {
0062
0063 if (lengths[pipeN] > 0) {
0064 continue;
0065 }
0066 if (pipeN == 0) {
0067 continue;
0068 }
0069 if ((pipeN + 1) == names.size()) {
0070 continue;
0071 }
0072
0073 double previousPipeEndX =
0074 xCenters[pipeN - 1] - lengths[pipeN - 1] / 2. * sin(thetas[pipeN - 1]);
0075 double previousPipeEndZ =
0076 zCenters[pipeN - 1] - lengths[pipeN - 1] / 2. * cos(thetas[pipeN - 1]);
0077 double nextPipeStartX = xCenters[pipeN + 1] + lengths[pipeN + 1] / 2. * sin(thetas[pipeN + 1]);
0078 double nextPipeStartZ = zCenters[pipeN + 1] + lengths[pipeN + 1] / 2. * cos(thetas[pipeN + 1]);
0079
0080 double x = (previousPipeEndX + nextPipeStartX) / 2.;
0081 double z = (previousPipeEndZ + nextPipeStartZ) / 2.;
0082 double deltaX = previousPipeEndX - nextPipeStartX;
0083 double deltaZ = previousPipeEndZ - nextPipeStartZ;
0084 double l = sqrt(deltaX * deltaX + deltaZ * deltaZ);
0085 double theta = atan2(deltaX, deltaZ);
0086
0087 xCenters[pipeN] = x;
0088 zCenters[pipeN] = z;
0089 lengths[pipeN] = l;
0090 thetas[pipeN] = theta;
0091 rOuters1[pipeN] = rOuters2[pipeN - 1];
0092 rOuters2[pipeN] = rOuters1[pipeN + 1];
0093 }
0094
0095
0096 for (uint i = 1; i < thetas.size(); i++) {
0097
0098
0099 double bendAngle = thetas[i] - thetas[i - 1];
0100 if (std::abs(bendAngle) < 0.01 * mrad) {
0101 bendLengths.push_back(0);
0102 } else
0103 {
0104 double bendLength = abs(rOuters1[i] * tan(bendAngle / 2));
0105 bendLengths.push_back(bendLength + bendRadius);
0106 }
0107 }
0108
0109
0110 for (uint pipeN = 0; pipeN < xCenters.size(); pipeN++) {
0111
0112 double length = lengths[pipeN];
0113 double theta = thetas[pipeN];
0114 double xCenter = xCenters[pipeN];
0115 double zCenter = zCenters[pipeN];
0116 double rOuter1 = rOuters1[pipeN];
0117 double rOuter2 = rOuters2[pipeN];
0118
0119
0120 if (pipeN != 0) {
0121 length -= bendLengths[pipeN - 1];
0122 xCenter -= bendLengths[pipeN - 1] / 2 * sin(theta);
0123 zCenter -= bendLengths[pipeN - 1] / 2 * cos(theta);
0124 }
0125 if (pipeN != xCenters.size() - 1) {
0126 length -= bendLengths[pipeN];
0127 xCenter += bendLengths[pipeN] / 2 * sin(theta);
0128 zCenter += bendLengths[pipeN] / 2 * cos(theta);
0129 }
0130
0131 ConeSegment s_tube(length / 2.0, rOuter2 - thickness, rOuter2, rOuter1 - thickness, rOuter1);
0132 ConeSegment s_vacuum(length / 2.0, 0, rOuter2 - thickness, 0, rOuter1 - thickness);
0133
0134 Volume v_tube("v_tube_" + names[pipeN], s_tube, m_Al);
0135 Volume v_vacuum("v_vacuum_" + names[pipeN], s_vacuum, m_Vacuum);
0136
0137 v_tube.setVisAttributes(description.visAttributes(vis_name));
0138
0139 assembly.placeVolume(v_tube, Transform3D(RotationY(theta), Position(xCenter, 0, zCenter)));
0140 auto placed_vacuum = assembly.placeVolume(
0141 v_vacuum, Transform3D(RotationY(theta), Position(xCenter, 0, zCenter)));
0142
0143 DetElement vacuum_element(sdet, names[pipeN] + "_vacuum", ids[pipeN]);
0144 vacuum_element.setPlacement(placed_vacuum);
0145
0146
0147 if (pipeN != xCenters.size() - 1 && bendLengths[pipeN] != 0) {
0148
0149
0150 double bendAngle = thetas[pipeN + 1] - thetas[pipeN];
0151
0152
0153 Torus s_bend_solid(rOuter2 + bendRadius, rOuter2 - thickness, rOuter2, 0.0, abs(bendAngle));
0154
0155
0156 Torus s_bend_vac(rOuter2 + bendRadius, 0, rOuter2 - thickness, 0, abs(bendAngle));
0157
0158
0159 Volume v_bend_soild("v_bend_solid_" + names[pipeN], s_bend_solid, m_Al);
0160 Volume v_bend_vac("v_bend_vac_" + names[pipeN], s_bend_vac, m_Vacuum);
0161
0162
0163 double bendCenterX = xCenter + rOuter2 * cos(theta) - (length / 2) * sin(theta);
0164 double bendCenterZ = zCenter - rOuter2 * sin(theta) - (length / 2) * cos(theta);
0165 double rotation = pi - theta;
0166 if (bendAngle > 0) {
0167 bendCenterX = xCenter - rOuter2 * cos(theta) - (length / 2) * sin(theta);
0168 bendCenterZ = zCenter + rOuter2 * sin(theta) - (length / 2) * cos(theta);
0169 rotation = -bendAngle - theta;
0170 }
0171
0172
0173 assembly.placeVolume(v_bend_soild, Transform3D(RotationZYX(rotation, 0, pi / 2),
0174 Position(bendCenterX, 0, bendCenterZ)));
0175 assembly.placeVolume(v_bend_vac, Transform3D(RotationZYX(rotation, 0, pi / 2),
0176 Position(bendCenterX, 0, bendCenterZ)));
0177
0178
0179 v_bend_soild.setVisAttributes(description.visAttributes(vis_name));
0180 }
0181 }
0182
0183
0184 auto pv_assembly =
0185 description.pickMotherVolume(sdet).placeVolume(assembly, Position(0.0, 0.0, 0.0));
0186
0187 sdet.setPlacement(pv_assembly);
0188
0189 assembly->GetShape()->ComputeBBox();
0190
0191 return sdet;
0192 }
0193
0194 DECLARE_DETELEMENT(BeamPipeChain, create_detector)