File indexing completed on 2025-01-30 09:18:07
0001
0002
0003
0004
0005
0006 #include "DD4hep/DetFactoryHelper.h"
0007 #include "DD4hep/OpticalSurfaces.h"
0008 #include "DD4hep/Printout.h"
0009 #include "DDRec/DetectorData.h"
0010 #include <XML/Helper.h>
0011
0012 using namespace dd4hep;
0013 using namespace dd4hep::rec;
0014
0015
0016 static Ref_t createDetector(Detector& desc, xml::Handle_t handle, SensitiveDetector sens)
0017 {
0018 xml::DetElement detElem = handle;
0019 std::string detName = detElem.nameStr();
0020 int detID = detElem.id();
0021 xml::Component dims = detElem.dimensions();
0022 OpticalSurfaceManager surfMgr = desc.surfaceManager();
0023 DetElement det(detName, detID);
0024
0025
0026
0027 double vesselLength = dims.attr<double>(_Unicode(length));
0028 double vesselZmin = dims.attr<double>(_Unicode(zmin));
0029 double vesselRmin0 = dims.attr<double>(_Unicode(rmin0));
0030 double vesselRmin1 = dims.attr<double>(_Unicode(rmin1));
0031 double vesselRmax0 = dims.attr<double>(_Unicode(rmax0));
0032 double vesselRmax1 = dims.attr<double>(_Unicode(rmax1));
0033 double wallThickness = dims.attr<double>(_Unicode(wall_thickness));
0034 double windowThickness = dims.attr<double>(_Unicode(window_thickness));
0035 auto vesselMat = desc.material(detElem.attr<std::string>(_Unicode(material)));
0036 auto gasvolMat = desc.material(detElem.attr<std::string>(_Unicode(gas)));
0037 auto vesselVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_vessel)));
0038 auto gasvolVis = desc.visAttributes(detElem.attr<std::string>(_Unicode(vis_gas)));
0039
0040 auto radiatorElem = detElem.child(_Unicode(radiator));
0041 double radiatorRmin = radiatorElem.attr<double>(_Unicode(rmin));
0042 double radiatorRmax = radiatorElem.attr<double>(_Unicode(rmax));
0043 double radiatorFrontplane = radiatorElem.attr<double>(_Unicode(frontplane));
0044
0045 auto aerogelElem = radiatorElem.child(_Unicode(aerogel));
0046 auto aerogelMat = desc.material(aerogelElem.attr<std::string>(_Unicode(material)));
0047 auto aerogelVis = desc.visAttributes(aerogelElem.attr<std::string>(_Unicode(vis)));
0048 double aerogelThickness = aerogelElem.attr<double>(_Unicode(thickness));
0049
0050 auto filterElem = radiatorElem.child(_Unicode(filter));
0051 auto filterMat = desc.material(filterElem.attr<std::string>(_Unicode(material)));
0052 auto filterVis = desc.visAttributes(filterElem.attr<std::string>(_Unicode(vis)));
0053 double filterThickness = filterElem.attr<double>(_Unicode(thickness));
0054
0055 auto sensorElem = detElem.child(_Unicode(sensors)).child(_Unicode(module));
0056 auto sensorMat = desc.material(sensorElem.attr<std::string>(_Unicode(material)));
0057 auto sensorVis = desc.visAttributes(sensorElem.attr<std::string>(_Unicode(vis)));
0058 auto sensorSurf = surfMgr.opticalSurface(sensorElem.attr<std::string>(_Unicode(surface)));
0059 double sensorSide = sensorElem.attr<double>(_Unicode(side));
0060 double sensorGap = sensorElem.attr<double>(_Unicode(gap));
0061 double sensorThickness = sensorElem.attr<double>(_Unicode(thickness));
0062
0063 auto sensorPlaneElem = detElem.child(_Unicode(sensors)).child(_Unicode(plane));
0064 double sensorPlaneDist = sensorPlaneElem.attr<double>(_Unicode(sensordist));
0065 double sensorPlaneRmin = sensorPlaneElem.attr<double>(_Unicode(rmin));
0066 double sensorPlaneRmax = sensorPlaneElem.attr<double>(_Unicode(rmax));
0067
0068
0069
0070
0071
0072
0073
0074
0075 double boreDelta = vesselRmin1 - vesselRmin0;
0076 Cone vesselSolid(
0077 vesselLength / 2.0,
0078 vesselRmin1,
0079 vesselRmax1,
0080 vesselRmin0,
0081 vesselRmax0
0082 );
0083 Cone gasvolSolid(
0084 vesselLength / 2.0 - windowThickness,
0085 vesselRmin1 + wallThickness,
0086 vesselRmax1 - wallThickness,
0087 vesselRmin0 + wallThickness,
0088 vesselRmax0 - wallThickness
0089 );
0090
0091
0092 Volume vesselVol(detName, vesselSolid, vesselMat);
0093 Volume gasvolVol(detName+"_gas", gasvolSolid, gasvolMat);
0094 vesselVol.setVisAttributes(vesselVis);
0095 gasvolVol.setVisAttributes(gasvolVis);
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 auto originFront = Position(0., 0., vesselLength / 2.0);
0106
0107
0108 sens.setType("tracker");
0109
0110
0111
0112
0113 double airGap = 0.01 * mm;
0114
0115
0116 Cone aerogelSolid(
0117 aerogelThickness / 2,
0118 radiatorRmin + boreDelta * aerogelThickness / vesselLength,
0119 radiatorRmax,
0120 radiatorRmin,
0121 radiatorRmax
0122 );
0123 Cone filterSolid(
0124 filterThickness / 2,
0125 radiatorRmin + boreDelta * (aerogelThickness + airGap + filterThickness) / vesselLength,
0126 radiatorRmax,
0127 radiatorRmin + boreDelta * (aerogelThickness + airGap) / vesselLength,
0128 radiatorRmax
0129 );
0130 Volume aerogelVol(detName + "_aerogel", aerogelSolid, aerogelMat);
0131 Volume filterVol(detName + "_filter", filterSolid, filterMat);
0132 aerogelVol.setVisAttributes(aerogelVis);
0133 filterVol.setVisAttributes(filterVis);
0134
0135
0136
0137 auto radiatorPos = Position(0., 0., radiatorFrontplane - 0.5 * aerogelThickness) + originFront;
0138 auto aerogelPV = gasvolVol.placeVolume(
0139 aerogelVol,
0140 Transform3D(Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z()))
0141 );
0142 DetElement aerogelDE(det, "aerogel_de", 0);
0143 aerogelDE.setPlacement(aerogelPV);
0144
0145
0146 auto filterPV = gasvolVol.placeVolume(
0147 filterVol,
0148 Transform3D(
0149 Translation3D(0., 0., -airGap)
0150 *
0151 Translation3D(radiatorPos.x(), radiatorPos.y(), radiatorPos.z())
0152 *
0153 Translation3D(0., 0., -(aerogelThickness + filterThickness) / 2.)
0154 )
0155 );
0156 DetElement filterDE(det, "filter_de", 0);
0157 filterDE.setPlacement(filterPV);
0158
0159
0160
0161
0162 Box sensorSolid(sensorSide / 2., sensorSide / 2., sensorThickness / 2.);
0163 Volume sensorVol(detName + "_sensor", sensorSolid, sensorMat);
0164 sensorVol.setVisAttributes(sensorVis);
0165
0166
0167 sensorVol.setSensitiveDetector(sens);
0168
0169
0170
0171 double sensorZpos = radiatorFrontplane - aerogelThickness - sensorPlaneDist - 0.5 * sensorThickness;
0172 auto sensorPlanePos = Position(0., 0., sensorZpos) + originFront;
0173
0174 int imod = 0;
0175 double tBoxMax = vesselRmax1;
0176
0177
0178
0179
0180
0181
0182
0183 double sx, sy;
0184 for (double usx = 0; usx <= tBoxMax; usx += sensorSide + sensorGap) {
0185 for (int sgnx = 1; sgnx >= (usx > 0 ? -1 : 1); sgnx -= 2) {
0186 for (double usy = 0; usy <= tBoxMax; usy += sensorSide + sensorGap) {
0187 for (int sgny = 1; sgny >= (usy > 0 ? -1 : 1); sgny -= 2) {
0188
0189
0190 sx = sgnx * usx;
0191 sy = sgny * usy;
0192
0193
0194 if (std::hypot(sx, sy) < sensorPlaneRmin || std::hypot(sx, sy) > sensorPlaneRmax)
0195 continue;
0196
0197
0198 auto sensorPV = gasvolVol.placeVolume(
0199 sensorVol,
0200 Transform3D(
0201 Translation3D(sensorPlanePos.x(), sensorPlanePos.y(), sensorPlanePos.z())
0202 *
0203 Translation3D(sx, sy, 0.)
0204 )
0205 );
0206
0207
0208
0209
0210
0211 sensorPV.addPhysVolID("module", imod);
0212 DetElement sensorDE(det, Form("sensor_de_%d", imod), imod);
0213 sensorDE.setPlacement(sensorPV);
0214 SkinSurface sensorSkin(desc, sensorDE, "sensor_optical_surface", sensorSurf, sensorVol);
0215 sensorSkin.isValid();
0216
0217
0218 imod++;
0219 }
0220 }
0221 }
0222 }
0223
0224
0225
0226 if (detElem.child("sensors").hasChild(_Unicode(services))) {
0227 xml_comp_t x_service = detElem.child("sensors").child(_Unicode(services));
0228 Assembly service_vol("services");
0229 service_vol.setVisAttributes(desc, x_service.visStr());
0230
0231
0232 double total_thickness = 0;
0233 for (xml_coll_t ci(x_service, _Unicode(component)); ci; ++ci) {
0234 total_thickness += xml_comp_t(ci).thickness();
0235 }
0236
0237 int ncomponents = 0;
0238 double thickness_sum = -total_thickness / 2.0;
0239 for (xml_coll_t ci(x_service, _Unicode(component)); ci; ++ci, ncomponents++) {
0240 xml_comp_t x_comp = ci;
0241 double thickness = x_comp.thickness();
0242 Tube c_tube{sensorPlaneRmin, sensorPlaneRmax, thickness / 2};
0243 Volume c_vol{_toString(ncomponents, "component%d"), c_tube, desc.material(x_comp.materialStr())};
0244 c_vol.setVisAttributes(desc, x_comp.visStr());
0245 service_vol.placeVolume(c_vol, Position(0, 0, thickness_sum + thickness / 2.0));
0246 thickness_sum += thickness;
0247 }
0248 gasvolVol.placeVolume(service_vol,
0249 Transform3D(Translation3D(sensorPlanePos.x(), sensorPlanePos.y(),
0250 sensorPlanePos.z() - sensorThickness - total_thickness)));
0251 }
0252
0253
0254
0255
0256 PlacedVolume gasvolPV = vesselVol.placeVolume(gasvolVol, Position(0, 0, 0));
0257 DetElement gasvolDE(det, "gasvol_de", 0);
0258 gasvolDE.setPlacement(gasvolPV);
0259
0260
0261 Volume motherVol = desc.pickMotherVolume(det);
0262 PlacedVolume vesselPV = motherVol.placeVolume(vesselVol, Position(0, 0, vesselZmin) - originFront);
0263 vesselPV.addPhysVolID("system", detID);
0264 det.setPlacement(vesselPV);
0265
0266 return det;
0267 }
0268
0269
0270 DECLARE_DETELEMENT(PFRICH, createDetector)