File indexing completed on 2025-01-18 09:15:58
0001
0002
0003
0004 #include "DD4hep/DetFactoryHelper.h"
0005 #include "DD4hep/Printout.h"
0006 #include <XML/Helper.h>
0007
0008 using namespace std;
0009 using namespace dd4hep;
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 static double getRotatedZ(double z, double x, double angle);
0027 static double getRotatedX(double z, double x, double angle);
0028
0029 static Ref_t create_detector(Detector& det, xml_h e, SensitiveDetector ) {
0030
0031 xml_det_t x_det = e;
0032 string det_name = x_det.nameStr();
0033 DetElement sdet(det_name, x_det.id());
0034 Assembly assembly(det_name + "_assembly");
0035 Material m_Vac = det.material("Vacuum");
0036 string vis_name = x_det.visStr();
0037
0038 PlacedVolume pv_assembly;
0039
0040
0041
0042
0043
0044
0045
0046
0047 bool makeIP_B0pfVacuum = true;
0048 bool make_B2pf_EW_Vacuum = true;
0049
0050
0051 vector<double> radii_magnet;
0052 vector<double> lengths_magnet;
0053 vector<double> rotation_magnet;
0054 vector<double> x_elem_magnet;
0055 vector<double> y_elem_magnet;
0056 vector<double> z_elem_magnet;
0057
0058
0059 vector<double> x_beg;
0060 vector<double> z_beg;
0061 vector<double> x_end;
0062 vector<double> z_end;
0063
0064
0065 vector<double> angle_elem_gap;
0066 vector<double> z_gap;
0067 vector<double> x_gap;
0068 vector<double> length_gap;
0069
0070
0071 vector<double> inRadius;
0072 vector<double> outRadius;
0073 vector<double> nxLow;
0074 vector<double> nyLow;
0075 vector<double> nzLow;
0076 vector<double> nxHigh;
0077 vector<double> nyHigh;
0078 vector<double> nzHigh;
0079 vector<double> phi_initial;
0080 vector<double> phi_final;
0081
0082 for (xml_coll_t c(x_det, _U(element)); c; ++c) {
0083
0084 xml_dim_t pos = c.child(_U(placement));
0085 double pos_x = pos.x();
0086 double pos_y = pos.y();
0087 double pos_z = pos.z();
0088 double pos_theta = pos.attr<double>(_U(theta));
0089 xml_dim_t dims = c.child(_U(dimensions));
0090 double dim_z = dims.z();
0091 xml_dim_t apperture = c.child(_Unicode(apperture));
0092 double app_r = apperture.r();
0093
0094 radii_magnet.push_back(app_r);
0095 lengths_magnet.push_back(dim_z);
0096 rotation_magnet.push_back(pos_theta);
0097 x_elem_magnet.push_back(pos_x * dd4hep::cm);
0098 y_elem_magnet.push_back(pos_y * dd4hep::cm);
0099 z_elem_magnet.push_back(pos_z * dd4hep::cm);
0100 }
0101
0102 int numMagnets = radii_magnet.size();
0103 int numGaps =
0104 numMagnets -
0105 2;
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 radii_magnet[0] = 2.9;
0116 lengths_magnet[0] = 120.0;
0117 rotation_magnet[0] = -0.025;
0118 x_elem_magnet[0] = 640.0 * sin(-0.025);
0119 y_elem_magnet[0] = 0.0;
0120 z_elem_magnet[0] = 640.0 * cos(-0.025);
0121
0122
0123
0124
0125
0126 for (int i = 0; i < numMagnets; i++) {
0127
0128
0129
0130
0131 z_beg.push_back(getRotatedZ(-0.5 * lengths_magnet[i], 0.0, rotation_magnet[i]) +
0132 z_elem_magnet[i]);
0133 z_end.push_back(getRotatedZ(0.5 * lengths_magnet[i], 0.0, rotation_magnet[i]) +
0134 z_elem_magnet[i]);
0135 x_beg.push_back(getRotatedX(-0.5 * lengths_magnet[i], 0.0, rotation_magnet[i]) +
0136 x_elem_magnet[i]);
0137 x_end.push_back(getRotatedX(0.5 * lengths_magnet[i], 0.0, rotation_magnet[i]) +
0138 x_elem_magnet[i]);
0139 }
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150 double endOfCentralBeamPipe_z =
0151 445.580 * dd4hep::cm;
0152 double diameterReduce = 11.0 * dd4hep::cm;
0153 double vacuumDiameterEntrance =
0154 25.792 * dd4hep::cm - diameterReduce;
0155 double vacuumDiameterExit =
0156 17.4 * dd4hep::cm;
0157 double crossingAngle = -0.025;
0158 double endOfCentralBeamPipe_x = endOfCentralBeamPipe_z * crossingAngle;
0159
0160
0161
0162
0163
0164 for (int i = 1; i < numMagnets; i++) {
0165
0166 angle_elem_gap.push_back((x_beg[i] - x_end[i - 1]) / (z_beg[i] - z_end[i - 1]));
0167 length_gap.push_back(sqrt(pow(z_beg[i] - z_end[i - 1], 2) + pow(x_beg[i] - x_end[i - 1], 2)));
0168 z_gap.push_back(z_end[i - 1] + 0.5 * length_gap[i - 1] * cos(angle_elem_gap[i - 1]));
0169 x_gap.push_back(x_end[i - 1] + 0.5 * length_gap[i - 1] * sin(angle_elem_gap[i - 1]));
0170 }
0171
0172
0173
0174
0175
0176 for (int gapIdx = 0; gapIdx < numGaps; gapIdx++) {
0177
0178 inRadius.push_back(0.0);
0179 outRadius.push_back(radii_magnet[gapIdx]);
0180 phi_initial.push_back(0.0);
0181 phi_final.push_back(2 * M_PI);
0182 nxLow.push_back(-(length_gap[gapIdx] / 2.0) *
0183 sin(rotation_magnet[gapIdx] - angle_elem_gap[gapIdx]));
0184 nyLow.push_back(0.0);
0185 nzLow.push_back(-(length_gap[gapIdx] / 2.0) *
0186 cos(rotation_magnet[gapIdx] - angle_elem_gap[gapIdx]));
0187 nxHigh.push_back((length_gap[gapIdx] / 2.0) *
0188 sin(rotation_magnet[gapIdx + 1] - angle_elem_gap[gapIdx]));
0189 nyHigh.push_back(0.0);
0190 nzHigh.push_back((length_gap[gapIdx] / 2.0) *
0191 cos(rotation_magnet[gapIdx + 1] - angle_elem_gap[gapIdx]));
0192 }
0193
0194
0195
0196
0197
0198 for (int pieceIdx = 0; pieceIdx < numMagnets; pieceIdx++) {
0199
0200 std::string piece_name = Form("MagnetVacuum%d", pieceIdx);
0201
0202 Tube magnetPiece(piece_name, 0.0, radii_magnet[pieceIdx], lengths_magnet[pieceIdx] / 2);
0203 Volume vpiece(piece_name, magnetPiece, m_Vac);
0204 sdet.setAttributes(det, vpiece, x_det.regionStr(), x_det.limitsStr(), vis_name);
0205
0206 assembly.placeVolume(vpiece,
0207 Transform3D(RotationY(rotation_magnet[pieceIdx]),
0208 Position(x_elem_magnet[pieceIdx], y_elem_magnet[pieceIdx],
0209 z_elem_magnet[pieceIdx])));
0210 }
0211
0212
0213
0214
0215
0216 for (int pieceIdx = numMagnets; pieceIdx < numGaps + numMagnets; pieceIdx++) {
0217
0218 int correctIdx = pieceIdx - numMagnets;
0219
0220 std::string piece_name = Form("GapVacuum%d", correctIdx);
0221
0222 CutTube gapPiece(piece_name, inRadius[correctIdx], outRadius[correctIdx],
0223 length_gap[correctIdx] / 2, phi_initial[correctIdx], phi_final[correctIdx],
0224 nxLow[correctIdx], nyLow[correctIdx], nzLow[correctIdx], nxHigh[correctIdx],
0225 nyHigh[correctIdx], nzHigh[correctIdx]);
0226
0227 Volume vpiece(piece_name, gapPiece, m_Vac);
0228 sdet.setAttributes(det, vpiece, x_det.regionStr(), x_det.limitsStr(), vis_name);
0229
0230 assembly.placeVolume(vpiece, Transform3D(RotationY(angle_elem_gap[correctIdx]),
0231 Position(x_gap[correctIdx], 0.0, z_gap[correctIdx])));
0232 }
0233
0234
0235
0236
0237
0238 if (makeIP_B0pfVacuum) {
0239
0240 double specialGapLength = sqrt(pow(z_beg[0] - endOfCentralBeamPipe_z, 2) +
0241 pow(x_beg[0] - endOfCentralBeamPipe_x, 2)) -
0242 0.1;
0243 double specialGap_z = 0.5 * specialGapLength * cos(crossingAngle) + endOfCentralBeamPipe_z;
0244 double specialGap_x = 0.5 * specialGapLength * sin(crossingAngle) + endOfCentralBeamPipe_x;
0245
0246 std::string piece_name = Form("GapVacuum%d", numGaps + numMagnets);
0247
0248 Cone specialGap(piece_name, specialGapLength / 2, 0.0, vacuumDiameterEntrance / 2, 0.0,
0249 vacuumDiameterExit / 2);
0250
0251 Volume specialGap_v(piece_name, specialGap, m_Vac);
0252 sdet.setAttributes(det, specialGap_v, x_det.regionStr(), x_det.limitsStr(), vis_name);
0253
0254 assembly.placeVolume(specialGap_v, Transform3D(RotationY(crossingAngle),
0255 Position(specialGap_x, 0.0, specialGap_z)));
0256 }
0257
0258
0259
0260
0261
0262
0263 if (make_B2pf_EW_Vacuum) {
0264
0265 int pieceIdx = numMagnets - 1;
0266 std::string piece_name = Form("GapVacuum%d", numGaps + numMagnets + 1);
0267 double endGapLength = (10000.0 - z_end[pieceIdx]) / cos(rotation_magnet[pieceIdx]);
0268 endGapLength =
0269 endGapLength -
0270 4 * radii_magnet[pieceIdx] *
0271 tan(-rotation_magnet[pieceIdx]);
0272 double endGap_z = 0.5 * endGapLength * cos(rotation_magnet[pieceIdx]) + z_end[pieceIdx];
0273 double endGap_x = 0.5 * endGapLength * sin(rotation_magnet[pieceIdx]) + x_end[pieceIdx];
0274
0275 Tube vacuum_endWorld(piece_name, 0.0, 4 * radii_magnet[pieceIdx],
0276 endGapLength / 2);
0277 Volume vpiece(piece_name, vacuum_endWorld, m_Vac);
0278 sdet.setAttributes(det, vpiece, x_det.regionStr(), x_det.limitsStr(),
0279 "InvisibleNoDaughters");
0280
0281 assembly.placeVolume(vpiece, Transform3D(RotationY(rotation_magnet[pieceIdx]),
0282 Position(endGap_x, 0.0, endGap_z)));
0283 }
0284
0285
0286 pv_assembly = det.pickMotherVolume(sdet).placeVolume(assembly);
0287 pv_assembly.addPhysVolID("system", x_det.id()).addPhysVolID("barrel", 1);
0288 sdet.setPlacement(pv_assembly);
0289 assembly->GetShape()->ComputeBBox();
0290
0291 return sdet;
0292 }
0293
0294 double getRotatedZ(double z, double x, double angle) { return z * cos(angle) - x * sin(angle); }
0295
0296 double getRotatedX(double z, double x, double angle) { return z * sin(angle) + x * cos(angle); }
0297
0298 DECLARE_DETELEMENT(magnetElementInnerVacuum, create_detector)