File indexing completed on 2026-04-10 07:46:29
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0013 #include "Acts/Geometry/CylinderLayer.hpp"
0014 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/DiscLayer.hpp"
0016 #include "Acts/Geometry/GlueVolumesDescriptor.hpp"
0017 #include "Acts/Geometry/ILayerArrayCreator.hpp"
0018 #include "Acts/Geometry/ITrackingVolumeArrayCreator.hpp"
0019 #include "Acts/Geometry/Layer.hpp"
0020 #include "Acts/Geometry/TrackingVolume.hpp"
0021 #include "Acts/Geometry/VolumeBounds.hpp"
0022 #include "Acts/Material/ISurfaceMaterial.hpp"
0023 #include "Acts/Surfaces/CylinderBounds.hpp"
0024 #include "Acts/Surfaces/CylinderSurface.hpp"
0025 #include "Acts/Surfaces/DiscSurface.hpp"
0026 #include "Acts/Surfaces/RadialBounds.hpp"
0027 #include "Acts/Surfaces/RegularSurface.hpp"
0028 #include "Acts/Surfaces/Surface.hpp"
0029 #include "Acts/Surfaces/SurfaceArray.hpp"
0030 #include "Acts/Surfaces/SurfaceBounds.hpp"
0031 #include "Acts/Utilities/BinUtility.hpp"
0032
0033 #include <algorithm>
0034 #include <cmath>
0035 #include <cstddef>
0036 #include <iosfwd>
0037 #include <memory>
0038 #include <numbers>
0039 #include <ostream>
0040 #include <utility>
0041
0042 namespace Acts {
0043
0044 CylinderVolumeHelper::CylinderVolumeHelper(
0045 const CylinderVolumeHelper::Config& cvhConfig,
0046 std::unique_ptr<const Logger> logger)
0047 : ITrackingVolumeHelper(), m_cfg(), m_logger(std::move(logger)) {
0048 setConfiguration(cvhConfig);
0049 }
0050
0051
0052 void CylinderVolumeHelper::setConfiguration(
0053 const CylinderVolumeHelper::Config& cvhConfig) {
0054
0055
0056 m_cfg = cvhConfig;
0057 }
0058
0059 void CylinderVolumeHelper::setLogger(std::unique_ptr<const Logger> newLogger) {
0060 m_logger = std::move(newLogger);
0061 }
0062
0063 std::shared_ptr<TrackingVolume> CylinderVolumeHelper::createTrackingVolume(
0064 const GeometryContext& gctx, const LayerVector& layers,
0065 std::shared_ptr<const IVolumeMaterial> volumeMaterial,
0066 std::shared_ptr<VolumeBounds> volumeBounds,
0067 MutableTrackingVolumeVector mtvVector, const Transform3& transform,
0068 const std::string& volumeName, BinningType bType) const {
0069
0070 MutableTrackingVolumePtr tVolume = nullptr;
0071
0072 std::unique_ptr<const LayerArray> layerArray = nullptr;
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 bool idTrf = transform.isApprox(Transform3::Identity());
0083
0084 auto cylinderBounds =
0085 std::dynamic_pointer_cast<CylinderVolumeBounds>(volumeBounds);
0086
0087 if (volumeBounds != nullptr && cylinderBounds == nullptr) {
0088 ACTS_WARNING(
0089 "[!] Problem: given bounds are not cylindrical - return nullptr");
0090 return tVolume;
0091 }
0092
0093 if (!layers.empty()) {
0094
0095 double rMinRaw = 0.;
0096 double rMaxRaw = 0.;
0097 double zMinRaw = 0.;
0098 double zMaxRaw = 0.;
0099
0100 AxisDirection bValue = AxisDirection::AxisR;
0101
0102
0103 if (!estimateAndCheckDimension(gctx, layers, cylinderBounds, transform,
0104 rMinRaw, rMaxRaw, zMinRaw, zMaxRaw, bValue,
0105 bType)) {
0106 ACTS_WARNING(
0107 "[!] Problem with given dimensions - return nullptr and "
0108 "delete provided objects");
0109 return tVolume;
0110 }
0111
0112 volumeBounds = cylinderBounds;
0113
0114 double zMin =
0115 (!idTrf ? transform.translation().z() : 0.) +
0116 (cylinderBounds != nullptr
0117 ? -cylinderBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0118 : 0.);
0119 double zMax = (!idTrf ? transform.translation().z() : 0.) +
0120 (cylinderBounds != nullptr
0121 ? cylinderBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0122 : 0.);
0123
0124 double rMin = cylinderBounds != nullptr
0125 ? cylinderBounds->get(CylinderVolumeBounds::eMinR)
0126 : rMinRaw;
0127 double rMax = cylinderBounds != nullptr
0128 ? cylinderBounds->get(CylinderVolumeBounds::eMaxR)
0129 : rMaxRaw;
0130
0131 ACTS_VERBOSE(
0132 "Filling the layers into an appropriate layer array - with "
0133 "binningValue = "
0134 << bValue);
0135
0136
0137 layerArray = (bValue == AxisDirection::AxisR)
0138 ? m_cfg.layerArrayCreator->layerArray(gctx, layers, rMin,
0139 rMax, bType, bValue)
0140 : m_cfg.layerArrayCreator->layerArray(gctx, layers, zMin,
0141 zMax, bType, bValue);
0142
0143 }
0144
0145 tVolume = std::make_shared<TrackingVolume>(
0146 transform, volumeBounds, volumeMaterial, std::move(layerArray), nullptr,
0147 mtvVector, volumeName);
0148
0149 ACTS_VERBOSE("Created cylindrical volume at z-position :"
0150 << tVolume->center(gctx).z());
0151 ACTS_VERBOSE(" created bounds : " << tVolume->volumeBounds());
0152
0153 return tVolume;
0154 }
0155
0156 std::shared_ptr<TrackingVolume> CylinderVolumeHelper::createTrackingVolume(
0157 const GeometryContext& gctx, const LayerVector& layers,
0158 MutableTrackingVolumeVector mtvVector,
0159 std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin,
0160 double rMax, double zMin, double zMax, const std::string& volumeName,
0161 BinningType bType) const {
0162
0163 ACTS_VERBOSE("Create cylindrical TrackingVolume '" << volumeName << "'.");
0164 ACTS_VERBOSE(" -> with given dimensions of (rMin/rMax/zMin/Max) = "
0165 << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
0166
0167
0168 if (zMin > zMax || rMin > rMax) {
0169 ACTS_WARNING("Inconsistent dimensions given :"
0170 << ((zMin > zMax) ? " zMin > zMax (" : " rMin > rMax (")
0171 << ((zMin > zMax) ? zMin : rMin) << " > "
0172 << ((zMin > zMax) ? zMax : rMax) << " ) - return 0");
0173 return nullptr;
0174 }
0175
0176
0177 double halflengthZ = 0.5 * (zMax - zMin);
0178 double zPosition = 0.5 * (zMin + zMax);
0179 zPosition = std::abs(zPosition) < 0.1 ? 0. : zPosition;
0180
0181
0182 auto cBounds =
0183 std::make_shared<CylinderVolumeBounds>(rMin, rMax, halflengthZ);
0184
0185
0186 const Transform3 transform = Transform3(Translation3(0., 0., zPosition));
0187
0188 return createTrackingVolume(gctx, layers, volumeMaterial, cBounds, mtvVector,
0189 transform, volumeName, bType);
0190 }
0191
0192 std::shared_ptr<TrackingVolume> CylinderVolumeHelper::createGapTrackingVolume(
0193 const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector,
0194 std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin,
0195 double rMax, double zMin, double zMax, unsigned int materialLayers,
0196 bool cylinder, const std::string& volumeName) const {
0197
0198 ACTS_VERBOSE("Create cylindrical gap TrackingVolume '"
0199 << volumeName << "' with (rMin/rMax/zMin/Max) = ");
0200 ACTS_VERBOSE("\t" << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
0201
0202
0203 double min = cylinder ? rMin : zMin;
0204 double max = cylinder ? rMax : zMax;
0205
0206
0207 std::vector<double> layerPositions;
0208 if (materialLayers > 1) {
0209 double step = (max - min) / (materialLayers - 1);
0210 for (unsigned int il = 0; il < materialLayers; ++il) {
0211 layerPositions.push_back(min + il * step);
0212 }
0213 } else {
0214 layerPositions.push_back(0.5 * (min + max));
0215 }
0216
0217
0218 return createGapTrackingVolume(gctx, mtvVector, volumeMaterial, rMin, rMax,
0219 zMin, zMax, layerPositions, cylinder,
0220 volumeName, arbitrary);
0221 }
0222
0223 std::shared_ptr<TrackingVolume> CylinderVolumeHelper::createGapTrackingVolume(
0224 const GeometryContext& gctx, MutableTrackingVolumeVector& mtvVector,
0225 std::shared_ptr<const IVolumeMaterial> volumeMaterial, double rMin,
0226 double rMax, double zMin, double zMax,
0227 const std::vector<double>& layerPositions, bool cylinder,
0228 const std::string& volumeName, BinningType bType) const {
0229
0230 ACTS_VERBOSE("Create cylindrical gap TrackingVolume '"
0231 << volumeName << "' with (rMin/rMax/zMin/Max) = ");
0232 ACTS_VERBOSE("\t" << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
0233
0234
0235 LayerVector layers;
0236 layers.reserve(layerPositions.size());
0237
0238 std::vector<double>::const_iterator layerPropIter = layerPositions.begin();
0239 std::vector<double>::const_iterator layerPropEnd = layerPositions.end();
0240 for (; layerPropIter != layerPropEnd; ++layerPropIter) {
0241
0242 if (cylinder) {
0243
0244 double zMinLayer = zMin;
0245 double zMaxLayer = zMax;
0246
0247 layers.push_back(createCylinderLayer(
0248 0.5 * (zMinLayer + zMaxLayer), (*layerPropIter),
0249 std::abs(0.5 * (zMaxLayer - zMinLayer)), m_cfg.passiveLayerThickness,
0250 m_cfg.passiveLayerPhiBins, m_cfg.passiveLayerRzBins));
0251
0252 } else {
0253
0254 double rMinLayer = rMin;
0255 double rMaxLayer = rMax;
0256
0257 layers.push_back(createDiscLayer(
0258 (*layerPropIter), rMinLayer, rMaxLayer, m_cfg.passiveLayerThickness,
0259 m_cfg.passiveLayerPhiBins, m_cfg.passiveLayerRzBins));
0260 }
0261 }
0262
0263 return createTrackingVolume(gctx, layers, mtvVector, volumeMaterial, rMin,
0264 rMax, zMin, zMax, volumeName, bType);
0265 }
0266
0267 std::shared_ptr<TrackingVolume>
0268 CylinderVolumeHelper::createContainerTrackingVolume(
0269 const GeometryContext& gctx, const TrackingVolumeVector& volumes) const {
0270
0271 if (volumes.size() <= std::size_t{1}) {
0272 ACTS_WARNING(
0273 "None (only one) TrackingVolume given to create container "
0274 "volume (min required: 2) - returning 0 ");
0275 return nullptr;
0276 }
0277
0278 std::string volumeName = "{ ";
0279 ACTS_VERBOSE("[start] Creating a container volume with " << volumes.size()
0280 << " sub volumes:");
0281
0282
0283 auto firstVolume = volumes.begin();
0284 auto lastVolume = volumes.end();
0285
0286 for (std::size_t ivol = 0; firstVolume != lastVolume; ++firstVolume, ++ivol) {
0287 if (*firstVolume == nullptr) {
0288 ACTS_ERROR("Volume " << ivol << " is nullptr, return nullptr");
0289 return nullptr;
0290 }
0291 ACTS_VERBOSE(" - volume (" << ivol
0292 << ") is : " << (*firstVolume)->volumeName());
0293 ACTS_VERBOSE(" at position : "
0294 << (*firstVolume)->center(gctx).x() << ", "
0295 << (*firstVolume)->center(gctx).y() << ", "
0296 << (*firstVolume)->center(gctx).z());
0297
0298 ACTS_VERBOSE(" with bounds : " << (*firstVolume)->volumeBounds());
0299
0300 volumeName += (*firstVolume)->volumeName();
0301 if (ivol + 1 < volumes.size()) {
0302 volumeName += " | ";
0303 }
0304 }
0305
0306 volumeName += " }";
0307
0308 firstVolume = volumes.begin();
0309 --lastVolume;
0310
0311 if (firstVolume == lastVolume) {
0312 ACTS_WARNING(
0313 "Only one TrackingVolume given to create Top level volume "
0314 "(min required: 2) - returning 0 ");
0315 return nullptr;
0316 }
0317
0318 const CylinderVolumeBounds* firstVolumeBounds =
0319 dynamic_cast<const CylinderVolumeBounds*>(
0320 &((*firstVolume)->volumeBounds()));
0321 const CylinderVolumeBounds* lastVolumeBounds =
0322 dynamic_cast<const CylinderVolumeBounds*>(
0323 &((*lastVolume)->volumeBounds()));
0324
0325 if ((firstVolumeBounds == nullptr) || (lastVolumeBounds == nullptr)) {
0326 ACTS_WARNING(
0327 "VolumeBounds given are not of type: CylinderVolumeBounds "
0328 "(required) - returning 0 ");
0329 return nullptr;
0330 }
0331
0332 bool rCase =
0333 std::abs(firstVolumeBounds->get(CylinderVolumeBounds::eMinR) -
0334 lastVolumeBounds->get(CylinderVolumeBounds::eMinR)) > 0.1;
0335
0336
0337 double zMin = 0.;
0338 double zMax = 0.;
0339 double rMin = 0.;
0340 double rGlueMin = 0.;
0341 double rMax = 0.;
0342 double zSep1 = 0.;
0343 double zSep2 = 0.;
0344 if (rCase) {
0345 zMin = (*firstVolume)->center(gctx).z() -
0346 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0347 zMax = (*firstVolume)->center(gctx).z() +
0348 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0349 zSep1 = zMin;
0350 zSep2 = zMax;
0351 rMin = firstVolumeBounds->get(CylinderVolumeBounds::eMinR);
0352 rGlueMin = firstVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0353 rMax = lastVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0354 } else {
0355 zMin = (*firstVolume)->center(gctx).z() -
0356 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0357 zMax = (*lastVolume)->center(gctx).z() +
0358 lastVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0359 zSep1 = (*firstVolume)->center(gctx).z() +
0360 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0361 zSep2 = zSep1;
0362 rMin = firstVolumeBounds->get(CylinderVolumeBounds::eMinR);
0363 rMax = firstVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0364 }
0365
0366 double zPos = 0.5 * (zMin + zMax);
0367
0368 const Transform3 topVolumeTransform = Transform3(Translation3(0., 0., zPos));
0369
0370 auto topVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0371 rMin, rMax, 0.5 * std::abs(zMax - zMin));
0372
0373
0374 ACTS_VERBOSE("Container volume bounds are " << (*topVolumeBounds));
0375
0376
0377 std::shared_ptr<const TrackingVolumeArray> volumeArray =
0378 (rCase) ? m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0379 gctx, volumes, AxisDirection::AxisR)
0380 : m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0381 gctx, volumes, AxisDirection::AxisZ);
0382 if (volumeArray == nullptr) {
0383 ACTS_WARNING(
0384 "Creation of TrackingVolume array did not succeed - returning 0 ");
0385 return nullptr;
0386 }
0387
0388 std::shared_ptr<TrackingVolume> topVolume = std::make_shared<TrackingVolume>(
0389 topVolumeTransform, topVolumeBounds, nullptr, nullptr, volumeArray,
0390 MutableTrackingVolumeVector{}, volumeName);
0391
0392
0393 if (!interGlueTrackingVolume(gctx, topVolume, rCase, rMin, rGlueMin, rMax,
0394 zSep1, zSep2)) {
0395 ACTS_WARNING(
0396 "Problem with inter-glueing of TrackingVolumes (needed) - "
0397 "returning 0 ");
0398 return nullptr;
0399 }
0400
0401 ACTS_VERBOSE(
0402 "[ end ] return newly created container : " << topVolume->volumeName());
0403
0404 return topVolume;
0405 }
0406
0407
0408
0409 bool CylinderVolumeHelper::estimateAndCheckDimension(
0410 const GeometryContext& gctx, const LayerVector& layers,
0411 std::shared_ptr<CylinderVolumeBounds>& cylinderVolumeBounds,
0412 const Transform3& transform, double& rMinClean, double& rMaxClean,
0413 double& zMinClean, double& zMaxClean, AxisDirection& bValue,
0414 BinningType ) const {
0415
0416
0417 ACTS_VERBOSE("Parsing the " << layers.size()
0418 << " layers to gather overall dimensions");
0419 if (cylinderVolumeBounds != nullptr) {
0420 ACTS_VERBOSE(
0421 "Cylinder volume bounds are given: (rmin/rmax/dz) = "
0422 << "(" << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) << "/"
0423 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) << "/"
0424 << cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0425 << ")");
0426 }
0427
0428
0429 double layerRmin = 10e10;
0430 double layerRmax = 0.;
0431 double layerZmin = 10e10;
0432 double layerZmax = -10e10;
0433 bool radial = false;
0434
0435 rMinClean = 10e10;
0436 rMaxClean = 0.;
0437 zMinClean = 10e10;
0438 zMaxClean = -10e10;
0439
0440
0441 for (auto& layerIter : layers) {
0442
0443 double currentRmin = 0.;
0444 double currentRmax = 0.;
0445 double currentZmin = 0.;
0446 double currentZmax = 0.;
0447
0448 const CylinderBounds* cylBounds = dynamic_cast<const CylinderBounds*>(
0449 &(layerIter->surfaceRepresentation()).bounds());
0450
0451 if (cylBounds != nullptr) {
0452 radial = true;
0453
0454 double currentR = cylBounds->get(CylinderBounds::eR);
0455 double centerZ = (layerIter->surfaceRepresentation()).center(gctx).z();
0456
0457 currentRmin = currentR - (0.5 * (layerIter)->layerThickness());
0458 currentRmax = currentR + (0.5 * (layerIter)->layerThickness());
0459 currentZmin = centerZ - cylBounds->get(CylinderBounds::eHalfLengthZ);
0460 currentZmax = centerZ + cylBounds->get(CylinderBounds::eHalfLengthZ);
0461 }
0462
0463 const RadialBounds* discBounds = dynamic_cast<const RadialBounds*>(
0464 &(layerIter->surfaceRepresentation()).bounds());
0465 if (discBounds != nullptr) {
0466
0467 double centerZ = (layerIter->surfaceRepresentation()).center(gctx).z();
0468 currentRmin = discBounds->rMin();
0469 currentRmax = discBounds->rMax();
0470 currentZmin = centerZ - (0.5 * (layerIter)->layerThickness());
0471 currentZmax = centerZ + (0.5 * (layerIter)->layerThickness());
0472 }
0473
0474 rMinClean = std::min(rMinClean, currentRmin);
0475 rMaxClean = std::max(rMaxClean, currentRmax);
0476 zMinClean = std::min(zMinClean, currentZmin);
0477 zMaxClean = std::max(zMaxClean, currentZmax);
0478
0479 layerRmin = std::min(layerRmin, currentRmin);
0480 layerRmax = std::max(layerRmax, currentRmax);
0481 layerZmin = std::min(layerZmin, currentZmin);
0482 layerZmax = std::max(layerZmax, currentZmax);
0483 }
0484
0485
0486 bValue = radial ? AxisDirection::AxisR : AxisDirection::AxisZ;
0487
0488 ACTS_VERBOSE(
0489 "Estimate/check CylinderVolumeBounds from/w.r.t. enclosed "
0490 "layers + envelope covers");
0491
0492 double zEstFromLayerEnv = 0.5 * (layerZmax + layerZmin);
0493 double halflengthFromLayer = 0.5 * std::abs(layerZmax - layerZmin);
0494
0495
0496
0497
0498 bool concentric = std::abs(zEstFromLayerEnv) < 0.031622777;
0499
0500 bool idTrf = transform.isApprox(Transform3::Identity());
0501
0502 Transform3 vtransform = Transform3::Identity();
0503
0504 if ((cylinderVolumeBounds == nullptr) && idTrf) {
0505
0506 cylinderVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0507 layerRmin, layerRmax, halflengthFromLayer);
0508
0509 vtransform = concentric ? Transform3(Translation3(0., 0., zEstFromLayerEnv))
0510 : Transform3::Identity();
0511 } else if ((cylinderVolumeBounds != nullptr) && idTrf && !concentric) {
0512 vtransform = Transform3(Translation3(0., 0., zEstFromLayerEnv));
0513 } else if (!idTrf && (cylinderVolumeBounds == nullptr)) {
0514
0515 cylinderVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0516 layerRmin, layerRmax, halflengthFromLayer);
0517 }
0518
0519 ACTS_VERBOSE(" -> dimensions from layers (rMin/rMax/zMin/zMax) = "
0520 << layerRmin << " / " << layerRmax << " / " << layerZmin << " / "
0521 << layerZmax);
0522
0523 double zFromTransform = !idTrf ? transform.translation().z() : 0.;
0524 ACTS_VERBOSE(
0525 " -> while created bounds are (rMin/rMax/zMin/zMax) = "
0526 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) << " / "
0527 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) << " / "
0528 << zFromTransform -
0529 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0530 << " / "
0531 << zFromTransform +
0532 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ));
0533
0534
0535 if (cylinderVolumeBounds != nullptr) {
0536
0537 if (zFromTransform -
0538 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ) <=
0539 layerZmin &&
0540 zFromTransform +
0541 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ) >=
0542 layerZmax &&
0543 cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) <= layerRmin &&
0544 cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) >= layerRmax) {
0545 return true;
0546 } else {
0547 ACTS_WARNING(
0548 "Provided layers are not contained by volume ! Bailing out. ");
0549 ACTS_WARNING("- zFromTransform: " << zFromTransform);
0550 ACTS_WARNING("- volumeZmin:"
0551 << zFromTransform - cylinderVolumeBounds->get(
0552 CylinderVolumeBounds::eHalfLengthZ)
0553 << ", layerZmin: " << layerZmin);
0554 ACTS_WARNING("- volumeZmax: "
0555 << zFromTransform + cylinderVolumeBounds->get(
0556 CylinderVolumeBounds::eHalfLengthZ)
0557 << ", layerZmax: " << layerZmax);
0558 ACTS_WARNING("- volumeRmin: "
0559 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR)
0560 << ", layerRmin: " << layerRmin);
0561 ACTS_WARNING("- volumeRmax: "
0562 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR)
0563 << ", layerRmax: " << layerRmax);
0564 return false;
0565 }
0566 }
0567
0568 ACTS_VERBOSE("Created/Checked " << *cylinderVolumeBounds);
0569 return true;
0570 }
0571
0572 bool CylinderVolumeHelper::interGlueTrackingVolume(
0573 const GeometryContext& gctx, const std::shared_ptr<TrackingVolume>& tVolume,
0574 bool rBinned, double rMin, double rGlueMin, double rMax, double zMin,
0575 double zMax) const {
0576 ACTS_VERBOSE("Glue contained TrackingVolumes of container '"
0577 << tVolume->volumeName() << "'.");
0578
0579
0580 if (tVolume->confinedVolumes()) {
0581
0582
0583 GlueVolumesDescriptor& glueDescr = tVolume->glueVolumesDescriptor();
0584
0585
0586 auto& volumes = tVolume->confinedVolumes()->arrayObjects();
0587
0588
0589
0590 std::size_t ivol = 0;
0591 for (auto& vol : volumes) {
0592 ACTS_VERBOSE("[" << ivol++ << "] - volume : " << vol->volumeName());
0593 }
0594
0595
0596 auto tVolIter = volumes.begin();
0597 auto tVolFirst = volumes.begin();
0598 auto tVolLast = volumes.end();
0599 --tVolLast;
0600 auto tVolEnd = volumes.end();
0601
0602
0603 TrackingVolumeVector glueVolumesInnerTube;
0604 TrackingVolumeVector glueVolumesOuterTube;
0605 TrackingVolumeVector glueVolumesNegativeFace;
0606 TrackingVolumeVector glueVolumesPositiveFace;
0607
0608 ivol = 0;
0609
0610 if (rBinned) {
0611
0612 for (; tVolIter != tVolEnd;) {
0613
0614 ACTS_VERBOSE("r-binning: Processing volume [" << ivol++ << "]");
0615
0616 std::shared_ptr<TrackingVolume> tVol =
0617 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0618 if (tVolIter == tVolFirst) {
0619 addFaceVolumes(tVol, tubeInnerCover, glueVolumesInnerTube);
0620 }
0621
0622 addFaceVolumes(tVol, negativeFaceXY, glueVolumesNegativeFace);
0623 addFaceVolumes(tVol, positiveFaceXY, glueVolumesPositiveFace);
0624 if (tVolIter == tVolLast) {
0625 addFaceVolumes(tVol, tubeOuterCover, glueVolumesOuterTube);
0626 ++tVolIter;
0627 } else {
0628 std::shared_ptr<TrackingVolume> tVol1 =
0629 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0630 std::shared_ptr<TrackingVolume> tVol2 =
0631 std::const_pointer_cast<TrackingVolume>(*(++tVolIter));
0632
0633
0634 double rGlueR =
0635 0.5 * (tVol1->volumeBounds()
0636 .values()[CylinderVolumeBounds::BoundValues::eMaxR] +
0637 tVol2->volumeBounds()
0638 .values()[CylinderVolumeBounds::BoundValues::eMinR]);
0639
0640 glueTrackingVolumes(gctx, tVol1, tubeOuterCover, tVol2,
0641 tubeInnerCover, rMin, rGlueR, rMax, zMin, zMax);
0642 }
0643 }
0644 } else {
0645
0646
0647 for (; tVolIter != tVolEnd;) {
0648
0649 ACTS_VERBOSE("z-binning: Processing volume '"
0650 << (*tVolIter)->volumeName() << "'.");
0651 std::shared_ptr<TrackingVolume> tVol =
0652 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0653 if (tVolIter == tVolFirst) {
0654 addFaceVolumes(tVol, negativeFaceXY, glueVolumesNegativeFace);
0655 }
0656 addFaceVolumes(tVol, tubeInnerCover, glueVolumesInnerTube);
0657 addFaceVolumes(tVol, tubeOuterCover, glueVolumesOuterTube);
0658 if (tVolIter == tVolLast) {
0659 addFaceVolumes(tVol, positiveFaceXY, glueVolumesPositiveFace);
0660 ++tVolIter;
0661 } else {
0662 std::shared_ptr<TrackingVolume> tVol1 =
0663 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0664 std::shared_ptr<TrackingVolume> tVol2 =
0665 std::const_pointer_cast<TrackingVolume>(*(++tVolIter));
0666 glueTrackingVolumes(gctx, tVol1, positiveFaceXY, tVol2,
0667 negativeFaceXY, rMin, rGlueMin, rMax, zMin, zMax);
0668 }
0669 }
0670 }
0671
0672
0673 if (!glueVolumesNegativeFace.empty()) {
0674
0675 std::shared_ptr<const TrackingVolumeArray> glueVolumesNegativeFaceArray =
0676 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0677 gctx, glueVolumesNegativeFace, AxisDirection::AxisR);
0678
0679 glueDescr.registerGlueVolumes(negativeFaceXY,
0680 glueVolumesNegativeFaceArray);
0681 }
0682 if (!glueVolumesPositiveFace.empty()) {
0683
0684 std::shared_ptr<const TrackingVolumeArray> glueVolumesPositiveFaceArray =
0685 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0686 gctx, glueVolumesPositiveFace, AxisDirection::AxisR);
0687
0688 glueDescr.registerGlueVolumes(positiveFaceXY,
0689 glueVolumesPositiveFaceArray);
0690 }
0691 if (!glueVolumesInnerTube.empty()) {
0692
0693 std::shared_ptr<const TrackingVolumeArray> glueVolumesInnerTubeArray =
0694 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0695 gctx, glueVolumesInnerTube, AxisDirection::AxisZ);
0696
0697 glueDescr.registerGlueVolumes(tubeInnerCover, glueVolumesInnerTubeArray);
0698 }
0699 if (!glueVolumesOuterTube.empty()) {
0700
0701 std::shared_ptr<const TrackingVolumeArray> glueVolumesOuterTubeArray =
0702 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0703 gctx, glueVolumesOuterTube, AxisDirection::AxisZ);
0704
0705 glueDescr.registerGlueVolumes(tubeOuterCover, glueVolumesOuterTubeArray);
0706 }
0707
0708 ACTS_VERBOSE("[GV] Register " << glueVolumesNegativeFace.size()
0709 << " volumes at face negativeFaceXY:");
0710 for (tVolIter = glueVolumesNegativeFace.begin();
0711 tVolIter != glueVolumesNegativeFace.end(); ++tVolIter) {
0712 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0713 }
0714 ACTS_VERBOSE("[GV] Register " << glueVolumesPositiveFace.size()
0715 << " volumes at face positiveFaceXY: ");
0716 for (tVolIter = glueVolumesPositiveFace.begin();
0717 tVolIter != glueVolumesPositiveFace.end(); ++tVolIter) {
0718 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0719 }
0720 ACTS_VERBOSE("[GV] Register " << glueVolumesInnerTube.size()
0721 << " volumes at face tubeInnerCover: ");
0722 for (tVolIter = glueVolumesInnerTube.begin();
0723 tVolIter != glueVolumesInnerTube.end(); ++tVolIter) {
0724 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0725 }
0726 ACTS_VERBOSE("[GV] Register " << glueVolumesOuterTube.size()
0727 << " volumes at face tubeOuterCover:");
0728 for (tVolIter = glueVolumesOuterTube.begin();
0729 tVolIter != glueVolumesOuterTube.end(); ++tVolIter) {
0730 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0731 }
0732 }
0733
0734 return true;
0735 }
0736
0737
0738 void CylinderVolumeHelper::glueTrackingVolumes(
0739 const GeometryContext& gctx, const std::shared_ptr<TrackingVolume>& tvolOne,
0740 BoundarySurfaceFace faceOne, const std::shared_ptr<TrackingVolume>& tvolTwo,
0741 BoundarySurfaceFace faceTwo, double rMin, double rGlueMin, double rMax,
0742 double zMin, double zMax) const {
0743
0744 const GlueVolumesDescriptor& gvDescriptorOne =
0745 tvolOne->glueVolumesDescriptor();
0746 const GlueVolumesDescriptor& gvDescriptorTwo =
0747 tvolTwo->glueVolumesDescriptor();
0748
0749 std::size_t volOneGlueVols =
0750 gvDescriptorOne.glueVolumes(faceOne)
0751 ? gvDescriptorOne.glueVolumes(faceOne)->arrayObjects().size()
0752 : 0;
0753 ACTS_VERBOSE("GlueVolumeDescriptor of volume '"
0754 << tvolOne->volumeName() << "' has " << volOneGlueVols << " @ "
0755 << faceOne);
0756 std::size_t volTwoGlueVols =
0757 gvDescriptorTwo.glueVolumes(faceTwo)
0758 ? gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects().size()
0759 : 0;
0760 ACTS_VERBOSE("GlueVolumeDescriptor of volume '"
0761 << tvolTwo->volumeName() << "' has " << volTwoGlueVols << " @ "
0762 << faceTwo);
0763
0764
0765 TrackingVolumePtr glueVolOne =
0766 volOneGlueVols != 0u
0767 ? gvDescriptorOne.glueVolumes(faceOne)->arrayObjects()[0]
0768 : tvolOne;
0769 TrackingVolumePtr glueVolTwo =
0770 volTwoGlueVols != 0u
0771 ? gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects()[0]
0772 : tvolTwo;
0773
0774
0775 auto mutableGlueVolOne = std::const_pointer_cast<TrackingVolume>(glueVolOne);
0776 auto mutableGlueVolTwo = std::const_pointer_cast<TrackingVolume>(glueVolTwo);
0777
0778
0779 if (volOneGlueVols <= 1 && volTwoGlueVols <= 1) {
0780
0781 ACTS_VERBOSE(" glue : one[ " << glueVolOne->volumeName() << " @ "
0782 << faceOne << " ]-to-one[ "
0783 << glueVolTwo->volumeName() << " @ "
0784 << faceTwo << " ]");
0785
0786 mutableGlueVolOne->glueTrackingVolume(gctx, faceOne,
0787 mutableGlueVolTwo.get(), faceTwo);
0788
0789 } else if (volOneGlueVols <= 1) {
0790
0791 ACTS_VERBOSE(" glue : one[ "
0792 << glueVolOne->volumeName() << " @ " << faceOne
0793 << " ]-to-many[ " << tvolTwo->volumeName() << " @ " << faceTwo
0794 << " ]");
0795 auto mutableFaceTwoVolumes = std::const_pointer_cast<TrackingVolumeArray>(
0796 gvDescriptorTwo.glueVolumes(faceTwo));
0797 mutableGlueVolOne->glueTrackingVolumes(gctx, faceOne, mutableFaceTwoVolumes,
0798 faceTwo);
0799 } else if (volTwoGlueVols <= 1) {
0800
0801 ACTS_VERBOSE(" glue : many[ "
0802 << tvolOne->volumeName() << " @ " << faceOne << " ]-to-one[ "
0803 << glueVolTwo->volumeName() << " @ " << faceTwo << " ]");
0804 auto mutableFaceOneVolumes = std::const_pointer_cast<TrackingVolumeArray>(
0805 gvDescriptorOne.glueVolumes(faceOne));
0806 mutableGlueVolTwo->glueTrackingVolumes(gctx, faceTwo, mutableFaceOneVolumes,
0807 faceOne);
0808 } else {
0809
0810 ACTS_VERBOSE(" glue : many[ "
0811 << tvolOne->volumeName() << " @ " << faceOne << " ]-to-many[ "
0812 << tvolTwo->volumeName() << " @ " << faceTwo << " ]");
0813
0814
0815 std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> boundarySurface =
0816 nullptr;
0817
0818
0819 Transform3 transform = Transform3::Identity();
0820 if (std::abs(zMin + zMax) > 0.1) {
0821
0822 transform =
0823 Transform3(Translation3(Vector3(0., 0., 0.5 * (zMin + zMax))));
0824 }
0825
0826 if (faceOne == cylinderCover || faceOne == tubeOuterCover) {
0827
0828 auto cBounds =
0829 std::make_shared<CylinderBounds>(rGlueMin, 0.5 * (zMax - zMin));
0830 auto cSurface = Surface::makeShared<CylinderSurface>(transform, cBounds);
0831 ACTS_VERBOSE(
0832 " creating a new cylindrical boundary surface "
0833 "with bounds = "
0834 << cSurface->bounds());
0835 ACTS_VERBOSE(" at " << cSurface->center(gctx).transpose());
0836 boundarySurface =
0837 std::make_shared<const BoundarySurfaceT<TrackingVolume>>(
0838 std::move(cSurface), gvDescriptorOne.glueVolumes(faceOne),
0839 gvDescriptorTwo.glueVolumes(faceTwo));
0840 } else {
0841
0842
0843
0844 auto cylVolBounds =
0845 dynamic_cast<const CylinderVolumeBounds*>(&tvolOne->volumeBounds());
0846 double zPos = tvolOne->center(gctx).z();
0847 double zHL = cylVolBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0848 transform = Transform3(Translation3(0, 0, zPos + zHL));
0849
0850
0851
0852
0853
0854 auto dSurface = Surface::makeShared<DiscSurface>(transform, rMin, rMax);
0855 ACTS_VERBOSE(
0856 " creating a new disc-like boundary surface "
0857 "with bounds = "
0858 << dSurface->bounds());
0859 ACTS_VERBOSE(" at " << dSurface->center(gctx).transpose());
0860 boundarySurface =
0861 std::make_shared<const BoundarySurfaceT<TrackingVolume>>(
0862 std::move(dSurface), gvDescriptorOne.glueVolumes(faceOne),
0863 gvDescriptorTwo.glueVolumes(faceTwo));
0864 }
0865
0866
0867 std::shared_ptr<const ISurfaceMaterial> boundaryMaterial = nullptr;
0868
0869 ACTS_VERBOSE("New Boundary surface setting for containers");
0870 ACTS_VERBOSE(" - at first volume: " << tvolOne->volumeName());
0871
0872
0873 for (auto& oneVolume :
0874 gvDescriptorOne.glueVolumes(faceOne)->arrayObjects()) {
0875 auto mutableOneVolume =
0876 std::const_pointer_cast<TrackingVolume>(oneVolume);
0877
0878 if (boundaryMaterial == nullptr) {
0879 auto oneBSurface = mutableOneVolume->boundarySurfaces()[faceOne];
0880 boundaryMaterial =
0881 oneBSurface->surfaceRepresentation().surfaceMaterialSharedPtr();
0882 }
0883 mutableOneVolume->updateBoundarySurface(faceOne, boundarySurface);
0884 ACTS_VERBOSE(" -> setting boundary surface to volume: "
0885 << mutableOneVolume->volumeName());
0886 }
0887 ACTS_VERBOSE(" - at second volume: " << tvolTwo->volumeName());
0888 for (auto& twoVolume :
0889 gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects()) {
0890 auto mutableTwoVolume =
0891 std::const_pointer_cast<TrackingVolume>(twoVolume);
0892
0893 if (boundaryMaterial == nullptr) {
0894 auto twoBSurface = mutableTwoVolume->boundarySurfaces()[faceTwo];
0895 boundaryMaterial =
0896 twoBSurface->surfaceRepresentation().surfaceMaterialSharedPtr();
0897 }
0898 mutableTwoVolume->updateBoundarySurface(faceTwo, boundarySurface);
0899 ACTS_VERBOSE(" -> setting boundary surface to volume: "
0900 << mutableTwoVolume->volumeName());
0901 }
0902
0903
0904 if (boundaryMaterial != nullptr) {
0905
0906 ACTS_VERBOSE("- the new boundary surface has boundary material: ");
0907 ACTS_VERBOSE(" " << *boundaryMaterial);
0908 RegularSurface* newSurface = const_cast<RegularSurface*>(
0909 &(boundarySurface->surfaceRepresentation()));
0910 newSurface->assignSurfaceMaterial(boundaryMaterial);
0911 }
0912
0913 }
0914 }
0915
0916
0917 void CylinderVolumeHelper::addFaceVolumes(
0918 const std::shared_ptr<TrackingVolume>& tvol, BoundarySurfaceFace glueFace,
0919 TrackingVolumeVector& vols) const {
0920 ACTS_VERBOSE("Adding face volumes of face " << glueFace << " for the volume '"
0921 << tvol->volumeName() << "'.");
0922
0923 const GlueVolumesDescriptor& gvDescriptor = tvol->glueVolumesDescriptor();
0924
0925 if (gvDescriptor.glueVolumes(glueFace)) {
0926
0927 auto volIter = gvDescriptor.glueVolumes(glueFace)->arrayObjects().begin();
0928 auto volEnd = gvDescriptor.glueVolumes(glueFace)->arrayObjects().end();
0929 for (; volIter != volEnd; ++volIter) {
0930 ACTS_VERBOSE(" -> adding : " << (*volIter)->volumeName());
0931 vols.push_back(*volIter);
0932 }
0933
0934 ACTS_VERBOSE(vols.size()
0935 << " navigation volumes registered as glue volumes.");
0936 } else {
0937
0938 ACTS_VERBOSE(" -> adding only volume itself (at navigation level).");
0939 vols.push_back(tvol);
0940 }
0941 }
0942
0943 std::shared_ptr<const Layer> CylinderVolumeHelper::createCylinderLayer(
0944 double z, double r, double halflengthZ, double thickness, int binsPhi,
0945 int binsZ) const {
0946 ACTS_VERBOSE("Creating a CylinderLayer at position " << z << " and radius "
0947 << r);
0948
0949 const Transform3 transform(Translation3(0., 0., z));
0950
0951
0952 BinUtility layerBinUtility(binsZ, z - halflengthZ, z + halflengthZ, open,
0953 AxisDirection::AxisZ);
0954 if (binsPhi == 1) {
0955
0956
0957 ACTS_VERBOSE(" -> Preparing the binned material with " << binsZ
0958 << " bins in Z. ");
0959
0960 } else {
0961
0962 BinUtility layerBinUtilityPhiZ(binsPhi, -r * std::numbers::pi,
0963 r * std::numbers::pi, closed,
0964 AxisDirection::AxisPhi);
0965 layerBinUtilityPhiZ += layerBinUtility;
0966
0967 ACTS_VERBOSE(" -> Preparing the binned material with "
0968 << binsPhi << " / " << binsZ << " bins in phi / Z. ");
0969 }
0970
0971
0972 CylinderBounds* cylinderBounds = new CylinderBounds(r, halflengthZ);
0973
0974 return CylinderLayer::create(
0975 transform, std::shared_ptr<const CylinderBounds>(cylinderBounds), nullptr,
0976 thickness);
0977 }
0978
0979 std::shared_ptr<const Layer> CylinderVolumeHelper::createDiscLayer(
0980 double z, double rMin, double rMax, double thickness, int binsPhi,
0981 int binsR) const {
0982 ACTS_VERBOSE("Creating a DiscLayer at position " << z << " and rMin/rMax "
0983 << rMin << " / " << rMax);
0984
0985
0986 const Transform3 transform(Translation3(0., 0., z));
0987
0988
0989 BinUtility materialBinUtility(binsR, rMin, rMax, open, AxisDirection::AxisR);
0990 if (binsPhi == 1) {
0991 ACTS_VERBOSE(" -> Preparing the binned material with " << binsR
0992 << " bins in R. ");
0993 } else {
0994
0995 materialBinUtility +=
0996 BinUtility(binsPhi, -std::numbers::pi_v<float>,
0997 std::numbers::pi_v<float>, closed, AxisDirection::AxisPhi);
0998 ACTS_VERBOSE(" -> Preparing the binned material with "
0999 << binsPhi << " / " << binsR << " bins in phi / R. ");
1000 }
1001
1002
1003
1004 RadialBounds* discBounds = new RadialBounds(rMin, rMax);
1005
1006 return DiscLayer::create(transform,
1007 std::shared_ptr<const DiscBounds>(discBounds),
1008 nullptr, thickness);
1009 }
1010
1011 }