File indexing completed on 2025-11-25 09:25:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "DD4hep/DetFactoryHelper.h"
0012 #include "DD4hep/Printout.h"
0013 #include <XML/Helper.h>
0014 #include <XML/Layering.h>
0015 #include "forwardEcalMap.h"
0016
0017 using namespace dd4hep;
0018
0019 double blocksize, blockgap, offsetX[2], offsetY[2], insert_dx[2];
0020
0021 double xBlock(int ns, int row, int col) {
0022 if (row >= 18 && row <= 20) {
0023 return (1 - 2 * ns) * (offsetX[ns] + insert_dx[ns] + (blocksize + blockgap) * (col + 0.5));
0024 } else {
0025 return (1 - 2 * ns) * (offsetX[ns] + (blocksize + blockgap) * (col + 0.5));
0026 }
0027 }
0028
0029 double yBlock(int ns, int row) {
0030 return offsetY[ns] + (blocksize + blockgap) * (mMaxRowBlock / 2.0 - row - 0.5);
0031 }
0032
0033 static Ref_t createDetector(Detector& desc, xml_h handle, SensitiveDetector sens) {
0034 blocksize = desc.constant<double>("EcalEndcapP_blockSize");
0035 blockgap = desc.constant<double>("EcalEndcapP_spaceBetweenBlock");
0036 double nsgap = desc.constant<double>("EcalEndcapP_xOffsetNorth") +
0037 desc.constant<double>("EcalEndcapP_xOffsetSouth");
0038 double rmin = 0.0;
0039 double rmax = desc.constant<double>("EcalEndcapP_rmax");
0040 double rmaxWithGap = desc.constant<double>("EcalEndcapP_rmaxWithGap");
0041 double zmax = desc.constant<double>("EcalEndcapP_zmax");
0042 double length = desc.constant<double>("EcalEndcapP_length");
0043 double zmin = desc.constant<double>("EcalEndcapP_zmin");
0044 offsetX[0] = desc.constant<double>("EcalEndcapP_xOffsetNorth");
0045 offsetX[1] = desc.constant<double>("EcalEndcapP_xOffsetSouth");
0046 offsetY[0] = desc.constant<double>("EcalEndcapP_yOffsetNorth");
0047 offsetY[1] = desc.constant<double>("EcalEndcapP_yOffsetSouth");
0048 insert_dx[0] = desc.constant<double>("EcalEndcapP_xOffsetBeamPipeNorth");
0049 insert_dx[1] = desc.constant<double>("EcalEndcapP_xOffsetBeamPipeSouth");
0050 double insert_dy = desc.constant<double>("EcalEndcapP_insert_dy");
0051 double insert_dz = desc.constant<double>("EcalEndcapP_insert_dz");
0052 double insert_thickness = desc.constant<double>("EcalEndcapP_insert_thickness");
0053 double insert_x = desc.constant<double>("EcalEndcapP_insert_center_x");
0054 int nx = desc.constant<int>("EcalEndcapP_nfiber_x");
0055 int ny = desc.constant<int>("EcalEndcapP_nfiber_y");
0056 double rFiber = desc.constant<double>("EcalEndcapP_rfiber");
0057 double rScfi = desc.constant<double>("EcalEndcapP_rscfi");
0058
0059 const double phi1[2] = {-M_PI / 2.0, M_PI / 2.0};
0060 const double phi2[2] = {M_PI / 2.0, 3.0 * M_PI / 2.0};
0061 const char* nsName[2] = {"N", "S"};
0062 const double pm[2] = {1.0, -1.0};
0063
0064
0065 xml_det_t detElem = handle;
0066 std::string detName = detElem.nameStr();
0067 int detID = detElem.id();
0068
0069 int Homogeneous_Scfi = 0;
0070 Homogeneous_Scfi = desc.constant<int>("EcalEndcapP_Homogeneous_ScFi");
0071 if (Homogeneous_Scfi <= 1)
0072 printout(INFO, "FEMC", "Making Homogeneous geometry model\n");
0073 else
0074 printout(INFO, "FEMC", "Making ScFi geometry model\n");
0075
0076
0077
0078 if (zmax != mBackPlateZ)
0079 printf("WARNING!!! forwardEcal_geo.cpp detect inconsistent Z pos %f(compact) %f(map)\n", zmax,
0080 mBackPlateZ);
0081
0082
0083 PlacedVolume pv;
0084 Material air = desc.material("Air");
0085 Material alumi = desc.material("Aluminum5083");
0086 Material Wpowder = desc.material("WPowderplusEpoxy");
0087 Material PMMA = desc.material("Plexiglass");
0088 Material ScFi = desc.material("Polystyrene");
0089
0090
0091 Tube envelope(rmin, rmaxWithGap, length / 2.0);
0092
0093
0094 Box insert((insert_dx[0] + insert_dx[1] - insert_thickness * 2 + nsgap) / 2.0,
0095 (insert_dy - insert_thickness * 2) / 2.0, length / 2.);
0096 SubtractionSolid envelope_with_inserthole(envelope, insert, Position(insert_x, 0.0, 0.0));
0097 Volume envelopeVol(detName, envelope_with_inserthole, air);
0098 envelopeVol.setAttributes(desc, detElem.regionStr(), detElem.limitsStr(), detElem.visStr());
0099
0100
0101
0102 double slice_z = -length / 2.0;
0103
0104 for (xml_coll_t sl(detElem, _U(slice)); sl; ++sl) {
0105 xml_comp_t x_slice = sl;
0106 double slice_thickness = x_slice.thickness();
0107
0108
0109 std::string slice_name = "fEcal" + x_slice.nameStr();
0110 Material slice_mat = desc.material(x_slice.materialStr());
0111 slice_z += slice_thickness / 2.;
0112 Tube slice(rmin, rmaxWithGap, slice_thickness / 2.);
0113
0114
0115 Box slice_insert((insert_dx[0] + insert_dx[1] + nsgap) / 2.0, insert_dy / 2.0,
0116 slice_thickness / 2.0);
0117 SubtractionSolid slice_with_inserthole(slice, slice_insert, Position(insert_x, 0.0, 0.0));
0118 Volume slice_vol(slice_name, slice_with_inserthole, air);
0119 slice_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0120 pv = envelopeVol.placeVolume(slice_vol,
0121 Transform3D(RotationZYX(0, 0, 0), Position(0., 0., slice_z)));
0122
0123
0124 for (int ns = 0; ns < 2; ns++) {
0125 Tube half(rmin, rmax, slice_thickness / 2.0, phi1[ns], phi2[ns]);
0126 std::string half_name = slice_name + "_" + nsName[ns];
0127
0128
0129 Box half_insert(insert_dx[ns] / 2.0, insert_dy / 2.0, slice_thickness / 2.0);
0130 SubtractionSolid half_with_inserthole(half, half_insert,
0131 Position(pm[ns] * insert_dx[ns] / 2.0, 0.0, 0.0));
0132
0133 Material mat = slice_mat;
0134 if (x_slice.isSensitive())
0135 mat = air;
0136 Volume half_vol(half_name, half_with_inserthole, mat);
0137 half_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0138 pv = slice_vol.placeVolume(
0139 half_vol, Transform3D(RotationZYX(0, 0, 0), Position(pm[ns] * nsgap / 2.0, 0.0, 0.0)));
0140 pv.addPhysVolID("northsouth", ns);
0141
0142
0143 double bsize = blocksize + blockgap;
0144 if (x_slice.isSensitive()) {
0145
0146
0147 if (Homogeneous_Scfi <= 1)
0148 mat = slice_mat;
0149 Box block(blocksize / 2.0, blocksize / 2.0, slice_thickness / 2.0);
0150 Volume block_vol("FEMCBlock", block, mat);
0151 block_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0152 if (Homogeneous_Scfi <= 1) {
0153 sens.setType("calorimeter");
0154 block_vol.setSensitiveDetector(sens);
0155 }
0156
0157 if (Homogeneous_Scfi == 2) {
0158
0159 Box trow(blocksize / 2.0, blocksize / 8.0, slice_thickness / 2.0);
0160 Volume trow_vol("FEMCTowerRow", trow, air);
0161 trow_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0162 for (int tr = 0; tr < 4; tr++) {
0163 pv = block_vol.placeVolume(
0164 trow_vol,
0165 Transform3D(RotationZYX(0, 0, 0), Position(0.0, (tr - 1.5) * blocksize / 4, 0)));
0166 pv.addPhysVolID("y", tr);
0167 }
0168
0169
0170 Box tower(blocksize / 8.0, blocksize / 8.0, slice_thickness / 2.0);
0171 Volume tower_vol("FEMCTower", tower, Wpowder);
0172 tower_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0173 for (int tc = 0; tc < 4; tc++) {
0174 pv = trow_vol.placeVolume(
0175 tower_vol,
0176 Transform3D(RotationZYX(0, 0, 0), Position((tc - 1.5) * blocksize / 4, 0, 0)));
0177 pv.addPhysVolID("x", tc);
0178 }
0179
0180
0181 double fiberDistanceX =
0182 blocksize / 4.0 / (nx + 0.5);
0183 Box frow(blocksize / 8.0 - fiberDistanceX / 2.0, blocksize / 8.0 / ny,
0184 slice_thickness / 2.0);
0185 Volume frow_vol("FEMCFiberRow", frow, Wpowder);
0186 frow_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0187 for (int iy = 0; iy < ny; iy++) {
0188 double xx = 0;
0189 if (iy % 2 == 1)
0190 xx += fiberDistanceX / 2.0;
0191 pv = tower_vol.placeVolume(
0192 frow_vol,
0193 Transform3D(RotationZYX(0, 0, 0),
0194 Position(xx, (iy - ny / 2.0 + 0.5) * blocksize / 4.0 / ny, 0)));
0195
0196 pv.addPhysVolID("fiber_y", iy);
0197 }
0198
0199
0200 Box fcol(fiberDistanceX / 2.0, blocksize / 8.0 / ny, slice_thickness / 2.0);
0201 Volume fcol_vol("FEMCFiberCol", fcol, Wpowder);
0202 fcol_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0203 for (int ix = 0; ix < nx; ix++) {
0204 double xx = (ix - nx / 2.0 + 0.5) * fiberDistanceX;
0205 pv = frow_vol.placeVolume(fcol_vol,
0206 Transform3D(RotationZYX(0, 0, 0), Position(xx, 0, 0)));
0207
0208 pv.addPhysVolID("fiber_x", ix);
0209 }
0210
0211
0212 Tube fiber(0, rFiber, slice_thickness / 2.0);
0213 Volume fiber_vol("FEMCFiber", fiber, PMMA);
0214 fiber_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0215 pv =
0216 fcol_vol.placeVolume(fiber_vol, Transform3D(RotationZYX(0, 0, 0), Position(0, 0, 0)));
0217
0218
0219 Tube scfi(0, rScfi, slice_thickness / 2.0);
0220 Volume scfi_vol("FEMCScFi", scfi, ScFi);
0221 scfi_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0222 pv =
0223 fiber_vol.placeVolume(scfi_vol, Transform3D(RotationZYX(0, 0, 0), Position(0, 0, 0)));
0224 sens.setType("calorimeter");
0225 scfi_vol.setSensitiveDetector(sens);
0226 }
0227
0228
0229
0230 int nRowBlock = mMaxRowBlock;
0231 for (int r = 0; r < nRowBlock; r++) {
0232
0233 int nColBlock = mNColBlock[ns][r];
0234 double dxrow = bsize * nColBlock;
0235 Box row(dxrow / 2.0, bsize / 2.0, slice_thickness / 2.0);
0236 std::string row_name = half_name + _toString(r, "_R%02d");
0237 Volume row_vol(row_name, row, air);
0238 row_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0239
0240
0241
0242 double xrow =
0243 (xBlock(ns, r, 0) + xBlock(ns, r, nColBlock - 1)) / 2.0 - pm[ns] * nsgap / 2.0;
0244 double yrow = yBlock(ns, r);
0245 pv = half_vol.placeVolume(row_vol,
0246 Transform3D(RotationZYX(0, 0, 0), Position(xrow, yrow, 0)));
0247 pv.addPhysVolID("blockrow", r);
0248
0249
0250 double xcol = -pm[ns] * (dxrow / 2.0 - bsize / 2.0);
0251 for (int c = 0; c < nColBlock; c++) {
0252 Box col(bsize / 2.0, bsize / 2.0, slice_thickness / 2.0);
0253 std::string col_name = row_name + _toString(c, "C%02d");
0254 Volume col_vol(col_name, col, air);
0255 col_vol.setAttributes(desc, x_slice.regionStr(), x_slice.limitsStr(), x_slice.visStr());
0256 pv = row_vol.placeVolume(col_vol,
0257 Transform3D(RotationZYX(0, 0, 0), Position(xcol, 0, 0)));
0258 pv.addPhysVolID("blockcol", c);
0259
0260 xcol += pm[ns] * bsize;
0261
0262
0263 pv = col_vol.placeVolume(block_vol,
0264 Transform3D(RotationZYX(0, 0, 0), Position(0, 0, 0)));
0265 }
0266 }
0267 }
0268 }
0269 slice_z += slice_thickness / 2.;
0270
0271 }
0272
0273
0274
0275 for (int ns = 0; ns < 2; ns++) {
0276 Box bpp(insert_dx[ns] / 2.0, insert_dy / 2.0, insert_dz / 2.0);
0277 std::string bpp_name = detName + "_BeamPipeProtector_" + nsName[ns];
0278 Box bpp_hole((insert_dx[ns] - insert_thickness) / 2.0, insert_dy / 2.0 - insert_thickness,
0279 insert_dz / 2.0);
0280 SubtractionSolid bpp_with_hole(bpp, bpp_hole,
0281 Position(-pm[ns] * insert_thickness / 2.0, 0.0, 0.0));
0282 Volume bpp_vol(bpp_name, bpp_with_hole, alumi);
0283 bpp_vol.setAttributes(desc, detElem.regionStr(), detElem.limitsStr(), detElem.visStr());
0284 pv = envelopeVol.placeVolume(
0285 bpp_vol, Transform3D(RotationZYX(0, 0, 0), Position(pm[ns] * (insert_dx[ns] + nsgap) / 2.0,
0286 0.0, (length - insert_dz) / 2.0)));
0287 }
0288
0289
0290 DetElement det(detName, detID);
0291 Volume motherVol = desc.pickMotherVolume(det);
0292 auto tr = Transform3D(Position(0.0, 0.0, zmin + length / 2.0));
0293 pv = motherVol.placeVolume(envelopeVol, tr);
0294 pv.addPhysVolID("system", detID);
0295 det.setPlacement(pv);
0296
0297
0298 return det;
0299 }
0300 DECLARE_DETELEMENT(epic_ForwardEcal, createDetector)