File indexing completed on 2025-11-25 09:25:09
0001
0002
0003
0004 #include "DD4hep/DetFactoryHelper.h"
0005 #include "DD4hep/OpticalSurfaces.h"
0006 #include "DD4hep/Printout.h"
0007 #include "DDRec/DetectorData.h"
0008 #include "DDRec/Surface.h"
0009
0010
0011
0012
0013
0014 using namespace std;
0015 using namespace dd4hep;
0016 using namespace dd4hep::rec;
0017
0018
0019 static void Make_Tagger(Detector& desc, xml_coll_t& mod, Assembly& env);
0020
0021 static Ref_t create_detector(Detector& desc, xml_h e, SensitiveDetector ) {
0022
0023 xml_det_t x_det = e;
0024 string detName = x_det.nameStr();
0025 int detID = x_det.id();
0026
0027 DetElement det(detName, detID);
0028
0029 string vis_name = dd4hep::getAttrOrDefault<std::string>(x_det, _Unicode(vis), "BackwardsBox");
0030
0031
0032 xml::Component dim = x_det.child(_Unicode(dimensions));
0033 double WidthL = dim.attr<double>(_Unicode(xL));
0034 double WidthR = dim.attr<double>(_Unicode(xR));
0035
0036 double Width = (WidthL + WidthR) / 2;
0037 double Height = dim.y();
0038 double Thickness = dim.z();
0039
0040
0041 Material Vacuum = desc.material("Vacuum");
0042 Material Steel = desc.material("StainlessSteelSAE304");
0043
0044
0045 xml::Component pos = x_det.child(_Unicode(focus));
0046 double off = pos.z();
0047
0048
0049 xml_dim_t rot = x_det.rotation();
0050
0051
0052 double wall = dd4hep::getAttrOrDefault<double>(x_det, _Unicode(wall), 1 * mm);
0053
0054
0055 xml::Component BB = x_det.child(_Unicode(bounding));
0056 double BB_MinX = BB.xmin();
0057 double BB_MinY = BB.ymin();
0058 double BB_MinZ = BB.zmin();
0059 double BB_MaxX = BB.xmax();
0060 double BB_MaxY = BB.ymax();
0061 double BB_MaxZ = BB.zmax();
0062
0063 double BB_X = abs(BB_MaxX - BB_MinX);
0064 double BB_Y = abs(BB_MaxY - BB_MinY);
0065 double BB_Z = abs(BB_MaxZ - BB_MinZ);
0066
0067 Box Far_Backwards_Box(BB_X, BB_Y, BB_Z);
0068
0069
0070 xml::Component EB = x_det.child(_Unicode(exitdim));
0071 double ED_X = EB.x();
0072 double ED_Y = EB.y();
0073 double ED_Z = off - EB.attr<double>(_Unicode(lumiZ));
0074 double Lumi_R = EB.attr<double>(_Unicode(lumiR));
0075
0076
0077 double exitTheta = EB.attr<double>(_Unicode(maxTheta));
0078
0079
0080 double xbox = 10 * m;
0081 double ybox = 10 * m;
0082 double zbox = 50 * m;
0083
0084 Box Cut_Box(xbox, ybox, zbox);
0085
0086
0087
0088 Box Extended_Beam_Box(Width + wall, Height + wall, Thickness);
0089
0090
0091
0092 Box Extended_Vacuum_Box(Width, Height, Thickness);
0093
0094 Solid Wall_Box = Extended_Beam_Box;
0095 Solid Vacuum_Box = Extended_Vacuum_Box;
0096
0097 Assembly DetAssembly("Tagger_vacuum_assembly");
0098
0099
0100
0101
0102 for (xml_coll_t mod(x_det, _Unicode(module)); mod; ++mod) {
0103
0104 int moduleID = dd4hep::getAttrOrDefault<int>(mod, _Unicode(id), 0);
0105 string moduleName = dd4hep::getAttrOrDefault<std::string>(mod, _Unicode(name), "Tagger0");
0106
0107 xml_dim_t mod_pos_global = mod.child(_U(position));
0108 xml_dim_t mod_rot_global = mod.child(_U(rotation));
0109 Position mod_pos(mod_pos_global.x(), mod_pos_global.y(), mod_pos_global.z());
0110 Position vac_pos(mod_pos_global.x() + wall / 2 * cos(mod_rot_global.theta()),
0111 mod_pos_global.y(),
0112 mod_pos_global.z() + wall / 2 * sin(mod_rot_global.theta()));
0113 RotationY mod_rot(mod_rot_global.theta() - rot.theta());
0114
0115
0116 xml_dim_t moddim = mod.child(_Unicode(dimensions));
0117 double vac_w = moddim.x() / 2;
0118 double vac_h = moddim.y() / 2;
0119 double vac_l = moddim.z() / 2;
0120
0121
0122 auto box_w = vac_w + wall;
0123 auto box_h = vac_h + wall;
0124
0125 Box TagWallBox(box_w, box_h, vac_l);
0126 Box TagVacBox(
0127 vac_w + wall / 2, vac_h,
0128 vac_l);
0129
0130 Wall_Box = UnionSolid(Wall_Box, TagWallBox, Transform3D(mod_rot, mod_pos));
0131 Vacuum_Box = UnionSolid(Vacuum_Box, TagVacBox, Transform3D(mod_rot, vac_pos));
0132
0133 Assembly TaggerAssembly("Tagger_module_assembly");
0134
0135 PlacedVolume pv_mod = DetAssembly.placeVolume(
0136 TaggerAssembly,
0137 Transform3D(mod_rot,
0138 mod_pos + Position(-vac_l * sin(mod_rot_global.theta() - rot.theta()), 0,
0139 -vac_l * cos(mod_rot_global.theta() - rot.theta()))));
0140 DetElement moddet(det, moduleName, moduleID);
0141 pv_mod.addPhysVolID("module", moduleID);
0142 moddet.setPlacement(pv_mod);
0143
0144 Make_Tagger(desc, mod, TaggerAssembly);
0145 }
0146
0147
0148
0149
0150
0151 Wall_Box = IntersectionSolid(Wall_Box, Cut_Box, Position(-xbox + Width + wall, 0, 0));
0152 Vacuum_Box = IntersectionSolid(Vacuum_Box, Cut_Box, Position(-xbox + Width, 0, 0));
0153
0154
0155
0156
0157 bool addLumi = dd4hep::getAttrOrDefault<bool>(x_det, _Unicode(lumi), true);
0158
0159 if (addLumi) {
0160
0161 Box Entry_Beam_Box(ED_X + wall, ED_Y + wall, ED_Z);
0162 Box Entry_Vacuum_Box(ED_X, ED_Y, ED_Z - wall);
0163 Tube Lumi_Exit(0, Lumi_R, ED_Z);
0164
0165
0166
0167
0168
0169
0170
0171
0172 Wall_Box = UnionSolid(Wall_Box, Entry_Beam_Box, Transform3D(RotationY(-rot.theta())));
0173 Vacuum_Box = UnionSolid(Vacuum_Box, Entry_Vacuum_Box, Transform3D(RotationY(-rot.theta())));
0174 Vacuum_Box = UnionSolid(Vacuum_Box, Lumi_Exit, Transform3D(RotationY(-rot.theta())));
0175 }
0176
0177
0178
0179
0180 double exitDist = BB_MinZ - off;
0181 double cutX = (ED_X - exitDist * tan(-rot.theta())) * cos(rot.theta());
0182 double cutZ =
0183 (ED_X - exitDist * tan(-rot.theta())) * sin(rot.theta()) + exitDist * cos(rot.theta());
0184 double cutXwall = (ED_X - wall - exitDist * tan(-rot.theta())) * cos(rot.theta());
0185 double cutZwall =
0186 (ED_X - wall - exitDist * tan(-rot.theta())) * sin(rot.theta()) + exitDist * cos(rot.theta());
0187
0188 Wall_Box = IntersectionSolid(Wall_Box, Cut_Box,
0189 Transform3D(RotationY(exitTheta), Position(xbox - cutX, 0, cutZ)));
0190 Vacuum_Box =
0191 IntersectionSolid(Vacuum_Box, Cut_Box,
0192 Transform3D(RotationY(exitTheta), Position(xbox - cutXwall, 0, cutZwall)));
0193
0194
0195
0196
0197 RotationY rotate2(-rot.theta());
0198 Position position(0, 0, (exitDist - BB_Z) / cos(rot.theta()));
0199
0200 IntersectionSolid Wall_Box_Sub(Wall_Box, Far_Backwards_Box, Transform3D(rotate2, position));
0201 IntersectionSolid Vacuum_Box_Sub(Vacuum_Box, Far_Backwards_Box, Transform3D(rotate2, position));
0202 SubtractionSolid Wall_Box_Out(Wall_Box_Sub, Vacuum_Box_Sub);
0203
0204 Volume vacVol("TaggerStation_Vacuum", Vacuum_Box_Sub, Vacuum);
0205 vacVol.setVisAttributes(desc.visAttributes("BackwardsVac"));
0206 vacVol.placeVolume(DetAssembly);
0207
0208 Volume wallVol("TaggerStation_Container", Wall_Box_Out, Steel);
0209 wallVol.setVisAttributes(desc.visAttributes(vis_name));
0210
0211 Assembly backAssembly(detName + "_assembly");
0212 backAssembly.placeVolume(wallVol);
0213 backAssembly.placeVolume(vacVol);
0214
0215
0216 Transform3D tr(RotationY(rot.theta()), Position(pos.x(), pos.y(), pos.z()));
0217 PlacedVolume detPV = desc.pickMotherVolume(det).placeVolume(backAssembly, tr);
0218 detPV.addPhysVolID("system", detID);
0219
0220 det.setPlacement(detPV);
0221
0222 return det;
0223 }
0224
0225 static void Make_Tagger(Detector& desc, xml_coll_t& mod, Assembly& env) {
0226
0227 xml_dim_t moddim = mod.child(_Unicode(dimensions));
0228 double tag_w = moddim.x() / 2;
0229 double tag_h = moddim.y() / 2;
0230
0231 double window_thickness = 0;
0232
0233
0234 for (xml_coll_t lay(mod, _Unicode(windowLayer)); lay; ++lay) {
0235
0236 string layerType = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(type), "window");
0237 string layerVis =
0238 dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(vis), "FFTrackerShieldingVis");
0239 double layerRot = dd4hep::getAttrOrDefault<double>(lay, _Unicode(angle), 0);
0240 double layerThickness =
0241 dd4hep::getAttrOrDefault<double>(lay, _Unicode(sensor_thickness), 1 * mm);
0242 string layerMaterial = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(material), "Copper");
0243
0244 window_thickness = layerThickness;
0245
0246 Material WindowMaterial = desc.material(layerMaterial);
0247
0248 RotationY rotate(layerRot);
0249
0250 Box Window_Box(tag_w, tag_h, layerThickness / 2);
0251 Volume layVol("WindowVolume", Window_Box, WindowMaterial);
0252 layVol.setVisAttributes(desc.visAttributes(layerVis));
0253
0254 env.placeVolume(layVol, Position(0, 0, layerThickness / 2));
0255
0256
0257 break;
0258 }
0259
0260
0261 for (xml_coll_t lay(mod, _Unicode(foilLayer)); lay; ++lay) {
0262
0263 string layerType = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(type), "foil");
0264 string layerVis =
0265 dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(vis), "FFTrackerShieldingVis");
0266 double layerRot = dd4hep::getAttrOrDefault<double>(lay, _Unicode(angle), 45 * deg);
0267 double layerThickness =
0268 dd4hep::getAttrOrDefault<double>(lay, _Unicode(sensor_thickness), 100 * um);
0269 string layerMaterial = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(material), "Copper");
0270
0271 Material FoilMaterial = desc.material(layerMaterial);
0272
0273 RotationY rotate(layerRot);
0274
0275 Box Foil_Box(tag_w / cos(layerRot) - 0.5 * layerThickness * tan(layerRot), tag_h,
0276 layerThickness / 2);
0277 Volume layVol("FoilVolume", Foil_Box, FoilMaterial);
0278 layVol.setVisAttributes(desc.visAttributes(layerVis));
0279
0280 env.placeVolume(layVol,
0281 Transform3D(rotate, Position(0, 0, window_thickness + tag_w * tan(layerRot))));
0282
0283
0284 break;
0285 }
0286 }
0287
0288 DECLARE_DETELEMENT(FarBackwardVacuum, create_detector)