File indexing completed on 2025-07-12 07:56:05
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;
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 if (thetas[i - 1] == thetas[i]) {
0099 bendLengths.push_back(0);
0100 } else
0101 {
0102 double bendAngle = thetas[i] - thetas[i - 1];
0103 double bendLength = abs(rOuters1[i] * tan(bendAngle / 2));
0104 bendLengths.push_back(bendLength + bendRadius);
0105 }
0106 }
0107
0108
0109 for (uint pipeN = 0; pipeN < xCenters.size(); pipeN++) {
0110
0111 double length = lengths[pipeN];
0112 double theta = thetas[pipeN];
0113 double xCenter = xCenters[pipeN];
0114 double zCenter = zCenters[pipeN];
0115 double rOuter1 = rOuters1[pipeN];
0116 double rOuter2 = rOuters2[pipeN];
0117
0118
0119 if (pipeN != 0) {
0120 length -= bendLengths[pipeN - 1];
0121 xCenter -= bendLengths[pipeN - 1] / 2 * sin(theta);
0122 zCenter -= bendLengths[pipeN - 1] / 2 * cos(theta);
0123 }
0124 if (pipeN != xCenters.size() - 1) {
0125 length -= bendLengths[pipeN];
0126 xCenter += bendLengths[pipeN] / 2 * sin(theta);
0127 zCenter += bendLengths[pipeN] / 2 * cos(theta);
0128 }
0129
0130 ConeSegment s_tube(length / 2.0, rOuter2 - thickness, rOuter2, rOuter1 - thickness, rOuter1);
0131 ConeSegment s_vacuum(length / 2.0, 0, rOuter2 - thickness, 0, rOuter1 - thickness);
0132
0133 Volume v_tube("v_tube_" + names[pipeN], s_tube, m_Al);
0134 Volume v_vacuum("v_vacuum_" + names[pipeN], s_vacuum, m_Vacuum);
0135
0136 v_tube.setVisAttributes(description.visAttributes(vis_name));
0137
0138 assembly.placeVolume(v_tube, Transform3D(RotationY(theta), Position(xCenter, 0, zCenter)));
0139 auto placed_vacuum = assembly.placeVolume(
0140 v_vacuum, Transform3D(RotationY(theta), Position(xCenter, 0, zCenter)));
0141
0142 DetElement vacuum_element(sdet, names[pipeN] + "_vacuum", ids[pipeN]);
0143 vacuum_element.setPlacement(placed_vacuum);
0144
0145
0146 if (pipeN != xCenters.size() - 1 && bendLengths[pipeN] != 0) {
0147
0148
0149 double bendAngle = thetas[pipeN + 1] - thetas[pipeN];
0150
0151
0152 Torus s_bend_solid(rOuter2 + bendRadius, rOuter2 - thickness, rOuter2, 0.0, abs(bendAngle));
0153
0154
0155 Torus s_bend_vac(rOuter2 + bendRadius, 0, rOuter2 - thickness, 0, abs(bendAngle));
0156
0157
0158 Volume v_bend_soild("v_bend_solid_" + names[pipeN], s_bend_solid, m_Al);
0159 Volume v_bend_vac("v_bend_vac_" + names[pipeN], s_bend_vac, m_Vacuum);
0160
0161
0162 double bendCenterX = xCenter + rOuter2 * cos(theta) - (length / 2) * sin(theta);
0163 double bendCenterZ = zCenter - rOuter2 * sin(theta) - (length / 2) * cos(theta);
0164 double rotation = pi - theta;
0165 if (bendAngle > 0) {
0166 bendCenterX = xCenter - rOuter2 * cos(theta) - (length / 2) * sin(theta);
0167 bendCenterZ = zCenter + rOuter2 * sin(theta) - (length / 2) * cos(theta);
0168 rotation = -bendAngle - theta;
0169 }
0170
0171
0172 assembly.placeVolume(v_bend_soild, Transform3D(RotationZYX(rotation, 0, pi / 2),
0173 Position(bendCenterX, 0, bendCenterZ)));
0174 assembly.placeVolume(v_bend_vac, Transform3D(RotationZYX(rotation, 0, pi / 2),
0175 Position(bendCenterX, 0, bendCenterZ)));
0176
0177
0178 v_bend_soild.setVisAttributes(description.visAttributes(vis_name));
0179 }
0180 }
0181
0182
0183 auto pv_assembly =
0184 description.pickMotherVolume(sdet).placeVolume(assembly, Position(0.0, 0.0, 0.0));
0185
0186 sdet.setPlacement(pv_assembly);
0187
0188 assembly->GetShape()->ComputeBBox();
0189
0190 return sdet;
0191 }
0192
0193 DECLARE_DETELEMENT(BeamPipeChain, create_detector)