File indexing completed on 2025-09-17 08:02:15
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(
0150 "Created cylindrical volume at z-position :" << tVolume->center().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 : " << (*firstVolume)->center().x() << ", "
0294 << (*firstVolume)->center().y() << ", "
0295 << (*firstVolume)->center().z());
0296
0297 ACTS_VERBOSE(" with bounds : " << (*firstVolume)->volumeBounds());
0298
0299 volumeName += (*firstVolume)->volumeName();
0300 if (ivol + 1 < volumes.size()) {
0301 volumeName += " | ";
0302 }
0303 }
0304
0305 volumeName += " }";
0306
0307 firstVolume = volumes.begin();
0308 --lastVolume;
0309
0310 if (firstVolume == lastVolume) {
0311 ACTS_WARNING(
0312 "Only one TrackingVolume given to create Top level volume "
0313 "(min required: 2) - returning 0 ");
0314 return nullptr;
0315 }
0316
0317 const CylinderVolumeBounds* firstVolumeBounds =
0318 dynamic_cast<const CylinderVolumeBounds*>(
0319 &((*firstVolume)->volumeBounds()));
0320 const CylinderVolumeBounds* lastVolumeBounds =
0321 dynamic_cast<const CylinderVolumeBounds*>(
0322 &((*lastVolume)->volumeBounds()));
0323
0324 if ((firstVolumeBounds == nullptr) || (lastVolumeBounds == nullptr)) {
0325 ACTS_WARNING(
0326 "VolumeBounds given are not of type: CylinderVolumeBounds "
0327 "(required) - returning 0 ");
0328 return nullptr;
0329 }
0330
0331 bool rCase =
0332 std::abs(firstVolumeBounds->get(CylinderVolumeBounds::eMinR) -
0333 lastVolumeBounds->get(CylinderVolumeBounds::eMinR)) > 0.1;
0334
0335
0336 double zMin = 0.;
0337 double zMax = 0.;
0338 double rMin = 0.;
0339 double rGlueMin = 0.;
0340 double rMax = 0.;
0341 double zSep1 = 0.;
0342 double zSep2 = 0.;
0343 if (rCase) {
0344 zMin = (*firstVolume)->center().z() -
0345 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0346 zMax = (*firstVolume)->center().z() +
0347 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0348 zSep1 = zMin;
0349 zSep2 = zMax;
0350 rMin = firstVolumeBounds->get(CylinderVolumeBounds::eMinR);
0351 rGlueMin = firstVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0352 rMax = lastVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0353 } else {
0354 zMin = (*firstVolume)->center().z() -
0355 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0356 zMax = (*lastVolume)->center().z() +
0357 lastVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0358 zSep1 = (*firstVolume)->center().z() +
0359 firstVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0360 zSep2 = zSep1;
0361 rMin = firstVolumeBounds->get(CylinderVolumeBounds::eMinR);
0362 rMax = firstVolumeBounds->get(CylinderVolumeBounds::eMaxR);
0363 }
0364
0365 double zPos = 0.5 * (zMin + zMax);
0366
0367 const Transform3 topVolumeTransform = Transform3(Translation3(0., 0., zPos));
0368
0369 auto topVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0370 rMin, rMax, 0.5 * std::abs(zMax - zMin));
0371
0372
0373 ACTS_VERBOSE("Container volume bounds are " << (*topVolumeBounds));
0374
0375
0376 std::shared_ptr<const TrackingVolumeArray> volumeArray =
0377 (rCase) ? m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0378 gctx, volumes, AxisDirection::AxisR)
0379 : m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0380 gctx, volumes, AxisDirection::AxisZ);
0381 if (volumeArray == nullptr) {
0382 ACTS_WARNING(
0383 "Creation of TrackingVolume array did not succeed - returning 0 ");
0384 return nullptr;
0385 }
0386
0387 std::shared_ptr<TrackingVolume> topVolume = std::make_shared<TrackingVolume>(
0388 topVolumeTransform, topVolumeBounds, nullptr, nullptr, volumeArray,
0389 MutableTrackingVolumeVector{}, volumeName);
0390
0391
0392 if (!interGlueTrackingVolume(gctx, topVolume, rCase, rMin, rGlueMin, rMax,
0393 zSep1, zSep2)) {
0394 ACTS_WARNING(
0395 "Problem with inter-glueing of TrackingVolumes (needed) - "
0396 "returning 0 ");
0397 return nullptr;
0398 }
0399
0400 ACTS_VERBOSE(
0401 "[ end ] return newly created container : " << topVolume->volumeName());
0402
0403 return topVolume;
0404 }
0405
0406
0407
0408 bool CylinderVolumeHelper::estimateAndCheckDimension(
0409 const GeometryContext& gctx, const LayerVector& layers,
0410 std::shared_ptr<CylinderVolumeBounds>& cylinderVolumeBounds,
0411 const Transform3& transform, double& rMinClean, double& rMaxClean,
0412 double& zMinClean, double& zMaxClean, AxisDirection& bValue,
0413 BinningType ) const {
0414
0415
0416 ACTS_VERBOSE("Parsing the " << layers.size()
0417 << " layers to gather overall dimensions");
0418 if (cylinderVolumeBounds != nullptr) {
0419 ACTS_VERBOSE(
0420 "Cylinder volume bounds are given: (rmin/rmax/dz) = "
0421 << "(" << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) << "/"
0422 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) << "/"
0423 << cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0424 << ")");
0425 }
0426
0427
0428 double layerRmin = 10e10;
0429 double layerRmax = 0.;
0430 double layerZmin = 10e10;
0431 double layerZmax = -10e10;
0432 bool radial = false;
0433
0434 rMinClean = 10e10;
0435 rMaxClean = 0.;
0436 zMinClean = 10e10;
0437 zMaxClean = -10e10;
0438
0439
0440 for (auto& layerIter : layers) {
0441
0442 double currentRmin = 0.;
0443 double currentRmax = 0.;
0444 double currentZmin = 0.;
0445 double currentZmax = 0.;
0446
0447 const CylinderBounds* cylBounds = dynamic_cast<const CylinderBounds*>(
0448 &(layerIter->surfaceRepresentation()).bounds());
0449
0450 if (cylBounds != nullptr) {
0451 radial = true;
0452
0453 double currentR = cylBounds->get(CylinderBounds::eR);
0454 double centerZ = (layerIter->surfaceRepresentation()).center(gctx).z();
0455
0456 currentRmin = currentR - (0.5 * (layerIter)->thickness());
0457 currentRmax = currentR + (0.5 * (layerIter)->thickness());
0458 currentZmin = centerZ - cylBounds->get(CylinderBounds::eHalfLengthZ);
0459 currentZmax = centerZ + cylBounds->get(CylinderBounds::eHalfLengthZ);
0460 }
0461
0462 const RadialBounds* discBounds = dynamic_cast<const RadialBounds*>(
0463 &(layerIter->surfaceRepresentation()).bounds());
0464 if (discBounds != nullptr) {
0465
0466 double centerZ = (layerIter->surfaceRepresentation()).center(gctx).z();
0467 currentRmin = discBounds->rMin();
0468 currentRmax = discBounds->rMax();
0469 currentZmin = centerZ - (0.5 * (layerIter)->thickness());
0470 currentZmax = centerZ + (0.5 * (layerIter)->thickness());
0471 }
0472
0473 rMinClean = std::min(rMinClean, currentRmin);
0474 rMaxClean = std::max(rMaxClean, currentRmax);
0475 zMinClean = std::min(zMinClean, currentZmin);
0476 zMaxClean = std::max(zMaxClean, currentZmax);
0477
0478 layerRmin = std::min(layerRmin, currentRmin);
0479 layerRmax = std::max(layerRmax, currentRmax);
0480 layerZmin = std::min(layerZmin, currentZmin);
0481 layerZmax = std::max(layerZmax, currentZmax);
0482 }
0483
0484
0485 bValue = radial ? AxisDirection::AxisR : AxisDirection::AxisZ;
0486
0487 ACTS_VERBOSE(
0488 "Estimate/check CylinderVolumeBounds from/w.r.t. enclosed "
0489 "layers + envelope covers");
0490
0491 double zEstFromLayerEnv = 0.5 * (layerZmax + layerZmin);
0492 double halflengthFromLayer = 0.5 * std::abs(layerZmax - layerZmin);
0493
0494
0495
0496
0497 bool concentric = std::abs(zEstFromLayerEnv) < 0.031622777;
0498
0499 bool idTrf = transform.isApprox(Transform3::Identity());
0500
0501 Transform3 vtransform = Transform3::Identity();
0502
0503 if ((cylinderVolumeBounds == nullptr) && idTrf) {
0504
0505 cylinderVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0506 layerRmin, layerRmax, halflengthFromLayer);
0507
0508 vtransform = concentric ? Transform3(Translation3(0., 0., zEstFromLayerEnv))
0509 : Transform3::Identity();
0510 } else if ((cylinderVolumeBounds != nullptr) && idTrf && !concentric) {
0511 vtransform = Transform3(Translation3(0., 0., zEstFromLayerEnv));
0512 } else if (!idTrf && (cylinderVolumeBounds == nullptr)) {
0513
0514 cylinderVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0515 layerRmin, layerRmax, halflengthFromLayer);
0516 }
0517
0518 ACTS_VERBOSE(" -> dimensions from layers (rMin/rMax/zMin/zMax) = "
0519 << layerRmin << " / " << layerRmax << " / " << layerZmin << " / "
0520 << layerZmax);
0521
0522 double zFromTransform = !idTrf ? transform.translation().z() : 0.;
0523 ACTS_VERBOSE(
0524 " -> while created bounds are (rMin/rMax/zMin/zMax) = "
0525 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) << " / "
0526 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) << " / "
0527 << zFromTransform -
0528 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ)
0529 << " / "
0530 << zFromTransform +
0531 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ));
0532
0533
0534 if (cylinderVolumeBounds != nullptr) {
0535
0536 if (zFromTransform -
0537 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ) <=
0538 layerZmin &&
0539 zFromTransform +
0540 cylinderVolumeBounds->get(CylinderVolumeBounds::eHalfLengthZ) >=
0541 layerZmax &&
0542 cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR) <= layerRmin &&
0543 cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR) >= layerRmax) {
0544 return true;
0545 } else {
0546 ACTS_WARNING(
0547 "Provided layers are not contained by volume ! Bailing out. ");
0548 ACTS_WARNING("- zFromTransform: " << zFromTransform);
0549 ACTS_WARNING("- volumeZmin:"
0550 << zFromTransform - cylinderVolumeBounds->get(
0551 CylinderVolumeBounds::eHalfLengthZ)
0552 << ", layerZmin: " << layerZmin);
0553 ACTS_WARNING("- volumeZmax: "
0554 << zFromTransform + cylinderVolumeBounds->get(
0555 CylinderVolumeBounds::eHalfLengthZ)
0556 << ", layerZmax: " << layerZmax);
0557 ACTS_WARNING("- volumeRmin: "
0558 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMinR)
0559 << ", layerRmin: " << layerRmin);
0560 ACTS_WARNING("- volumeRmax: "
0561 << cylinderVolumeBounds->get(CylinderVolumeBounds::eMaxR)
0562 << ", layerRmax: " << layerRmax);
0563 return false;
0564 }
0565 }
0566
0567 ACTS_VERBOSE("Created/Checked " << *cylinderVolumeBounds);
0568 return true;
0569 }
0570
0571 bool CylinderVolumeHelper::interGlueTrackingVolume(
0572 const GeometryContext& gctx, const std::shared_ptr<TrackingVolume>& tVolume,
0573 bool rBinned, double rMin, double rGlueMin, double rMax, double zMin,
0574 double zMax) const {
0575 ACTS_VERBOSE("Glue contained TrackingVolumes of container '"
0576 << tVolume->volumeName() << "'.");
0577
0578
0579 if (tVolume->confinedVolumes()) {
0580
0581
0582 GlueVolumesDescriptor& glueDescr = tVolume->glueVolumesDescriptor();
0583
0584
0585 auto& volumes = tVolume->confinedVolumes()->arrayObjects();
0586
0587
0588
0589 std::size_t ivol = 0;
0590 for (auto& vol : volumes) {
0591 ACTS_VERBOSE("[" << ivol++ << "] - volume : " << vol->volumeName());
0592 }
0593
0594
0595 auto tVolIter = volumes.begin();
0596 auto tVolFirst = volumes.begin();
0597 auto tVolLast = volumes.end();
0598 --tVolLast;
0599 auto tVolEnd = volumes.end();
0600
0601
0602 TrackingVolumeVector glueVolumesInnerTube;
0603 TrackingVolumeVector glueVolumesOuterTube;
0604 TrackingVolumeVector glueVolumesNegativeFace;
0605 TrackingVolumeVector glueVolumesPositiveFace;
0606
0607 ivol = 0;
0608
0609 if (rBinned) {
0610
0611 for (; tVolIter != tVolEnd;) {
0612
0613 ACTS_VERBOSE("r-binning: Processing volume [" << ivol++ << "]");
0614
0615 std::shared_ptr<TrackingVolume> tVol =
0616 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0617 if (tVolIter == tVolFirst) {
0618 addFaceVolumes(tVol, tubeInnerCover, glueVolumesInnerTube);
0619 }
0620
0621 addFaceVolumes(tVol, negativeFaceXY, glueVolumesNegativeFace);
0622 addFaceVolumes(tVol, positiveFaceXY, glueVolumesPositiveFace);
0623 if (tVolIter == tVolLast) {
0624 addFaceVolumes(tVol, tubeOuterCover, glueVolumesOuterTube);
0625 ++tVolIter;
0626 } else {
0627 std::shared_ptr<TrackingVolume> tVol1 =
0628 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0629 std::shared_ptr<TrackingVolume> tVol2 =
0630 std::const_pointer_cast<TrackingVolume>(*(++tVolIter));
0631
0632
0633 double rGlueR =
0634 0.5 * (tVol1->volumeBounds()
0635 .values()[CylinderVolumeBounds::BoundValues::eMaxR] +
0636 tVol2->volumeBounds()
0637 .values()[CylinderVolumeBounds::BoundValues::eMinR]);
0638
0639 glueTrackingVolumes(gctx, tVol1, tubeOuterCover, tVol2,
0640 tubeInnerCover, rMin, rGlueR, rMax, zMin, zMax);
0641 }
0642 }
0643 } else {
0644
0645
0646 for (; tVolIter != tVolEnd;) {
0647
0648 ACTS_VERBOSE("z-binning: Processing volume '"
0649 << (*tVolIter)->volumeName() << "'.");
0650 std::shared_ptr<TrackingVolume> tVol =
0651 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0652 if (tVolIter == tVolFirst) {
0653 addFaceVolumes(tVol, negativeFaceXY, glueVolumesNegativeFace);
0654 }
0655 addFaceVolumes(tVol, tubeInnerCover, glueVolumesInnerTube);
0656 addFaceVolumes(tVol, tubeOuterCover, glueVolumesOuterTube);
0657 if (tVolIter == tVolLast) {
0658 addFaceVolumes(tVol, positiveFaceXY, glueVolumesPositiveFace);
0659 ++tVolIter;
0660 } else {
0661 std::shared_ptr<TrackingVolume> tVol1 =
0662 std::const_pointer_cast<TrackingVolume>(*tVolIter);
0663 std::shared_ptr<TrackingVolume> tVol2 =
0664 std::const_pointer_cast<TrackingVolume>(*(++tVolIter));
0665 glueTrackingVolumes(gctx, tVol1, positiveFaceXY, tVol2,
0666 negativeFaceXY, rMin, rGlueMin, rMax, zMin, zMax);
0667 }
0668 }
0669 }
0670
0671
0672 if (!glueVolumesNegativeFace.empty()) {
0673
0674 std::shared_ptr<const TrackingVolumeArray> glueVolumesNegativeFaceArray =
0675 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0676 gctx, glueVolumesNegativeFace, AxisDirection::AxisR);
0677
0678 glueDescr.registerGlueVolumes(negativeFaceXY,
0679 glueVolumesNegativeFaceArray);
0680 }
0681 if (!glueVolumesPositiveFace.empty()) {
0682
0683 std::shared_ptr<const TrackingVolumeArray> glueVolumesPositiveFaceArray =
0684 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0685 gctx, glueVolumesPositiveFace, AxisDirection::AxisR);
0686
0687 glueDescr.registerGlueVolumes(positiveFaceXY,
0688 glueVolumesPositiveFaceArray);
0689 }
0690 if (!glueVolumesInnerTube.empty()) {
0691
0692 std::shared_ptr<const TrackingVolumeArray> glueVolumesInnerTubeArray =
0693 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0694 gctx, glueVolumesInnerTube, AxisDirection::AxisZ);
0695
0696 glueDescr.registerGlueVolumes(tubeInnerCover, glueVolumesInnerTubeArray);
0697 }
0698 if (!glueVolumesOuterTube.empty()) {
0699
0700 std::shared_ptr<const TrackingVolumeArray> glueVolumesOuterTubeArray =
0701 m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0702 gctx, glueVolumesOuterTube, AxisDirection::AxisZ);
0703
0704 glueDescr.registerGlueVolumes(tubeOuterCover, glueVolumesOuterTubeArray);
0705 }
0706
0707 ACTS_VERBOSE("[GV] Register " << glueVolumesNegativeFace.size()
0708 << " volumes at face negativeFaceXY:");
0709 for (tVolIter = glueVolumesNegativeFace.begin();
0710 tVolIter != glueVolumesNegativeFace.end(); ++tVolIter) {
0711 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0712 }
0713 ACTS_VERBOSE("[GV] Register " << glueVolumesPositiveFace.size()
0714 << " volumes at face positiveFaceXY: ");
0715 for (tVolIter = glueVolumesPositiveFace.begin();
0716 tVolIter != glueVolumesPositiveFace.end(); ++tVolIter) {
0717 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0718 }
0719 ACTS_VERBOSE("[GV] Register " << glueVolumesInnerTube.size()
0720 << " volumes at face tubeInnerCover: ");
0721 for (tVolIter = glueVolumesInnerTube.begin();
0722 tVolIter != glueVolumesInnerTube.end(); ++tVolIter) {
0723 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0724 }
0725 ACTS_VERBOSE("[GV] Register " << glueVolumesOuterTube.size()
0726 << " volumes at face tubeOuterCover:");
0727 for (tVolIter = glueVolumesOuterTube.begin();
0728 tVolIter != glueVolumesOuterTube.end(); ++tVolIter) {
0729 ACTS_VERBOSE(" -> volume '" << (*tVolIter)->volumeName() << "'");
0730 }
0731 }
0732
0733 return true;
0734 }
0735
0736
0737 void CylinderVolumeHelper::glueTrackingVolumes(
0738 const GeometryContext& gctx, const std::shared_ptr<TrackingVolume>& tvolOne,
0739 BoundarySurfaceFace faceOne, const std::shared_ptr<TrackingVolume>& tvolTwo,
0740 BoundarySurfaceFace faceTwo, double rMin, double rGlueMin, double rMax,
0741 double zMin, double zMax) const {
0742
0743 const GlueVolumesDescriptor& gvDescriptorOne =
0744 tvolOne->glueVolumesDescriptor();
0745 const GlueVolumesDescriptor& gvDescriptorTwo =
0746 tvolTwo->glueVolumesDescriptor();
0747
0748 std::size_t volOneGlueVols =
0749 gvDescriptorOne.glueVolumes(faceOne)
0750 ? gvDescriptorOne.glueVolumes(faceOne)->arrayObjects().size()
0751 : 0;
0752 ACTS_VERBOSE("GlueVolumeDescriptor of volume '"
0753 << tvolOne->volumeName() << "' has " << volOneGlueVols << " @ "
0754 << faceOne);
0755 std::size_t volTwoGlueVols =
0756 gvDescriptorTwo.glueVolumes(faceTwo)
0757 ? gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects().size()
0758 : 0;
0759 ACTS_VERBOSE("GlueVolumeDescriptor of volume '"
0760 << tvolTwo->volumeName() << "' has " << volTwoGlueVols << " @ "
0761 << faceTwo);
0762
0763
0764 TrackingVolumePtr glueVolOne =
0765 volOneGlueVols != 0u
0766 ? gvDescriptorOne.glueVolumes(faceOne)->arrayObjects()[0]
0767 : tvolOne;
0768 TrackingVolumePtr glueVolTwo =
0769 volTwoGlueVols != 0u
0770 ? gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects()[0]
0771 : tvolTwo;
0772
0773
0774 auto mutableGlueVolOne = std::const_pointer_cast<TrackingVolume>(glueVolOne);
0775 auto mutableGlueVolTwo = std::const_pointer_cast<TrackingVolume>(glueVolTwo);
0776
0777
0778 if (volOneGlueVols <= 1 && volTwoGlueVols <= 1) {
0779
0780 ACTS_VERBOSE(" glue : one[ " << glueVolOne->volumeName() << " @ "
0781 << faceOne << " ]-to-one[ "
0782 << glueVolTwo->volumeName() << " @ "
0783 << faceTwo << " ]");
0784
0785 mutableGlueVolOne->glueTrackingVolume(gctx, faceOne,
0786 mutableGlueVolTwo.get(), faceTwo);
0787
0788 } else if (volOneGlueVols <= 1) {
0789
0790 ACTS_VERBOSE(" glue : one[ "
0791 << glueVolOne->volumeName() << " @ " << faceOne
0792 << " ]-to-many[ " << tvolTwo->volumeName() << " @ " << faceTwo
0793 << " ]");
0794 auto mutableFaceTwoVolumes = std::const_pointer_cast<TrackingVolumeArray>(
0795 gvDescriptorTwo.glueVolumes(faceTwo));
0796 mutableGlueVolOne->glueTrackingVolumes(gctx, faceOne, mutableFaceTwoVolumes,
0797 faceTwo);
0798 } else if (volTwoGlueVols <= 1) {
0799
0800 ACTS_VERBOSE(" glue : many[ "
0801 << tvolOne->volumeName() << " @ " << faceOne << " ]-to-one[ "
0802 << glueVolTwo->volumeName() << " @ " << faceTwo << " ]");
0803 auto mutableFaceOneVolumes = std::const_pointer_cast<TrackingVolumeArray>(
0804 gvDescriptorOne.glueVolumes(faceOne));
0805 mutableGlueVolTwo->glueTrackingVolumes(gctx, faceTwo, mutableFaceOneVolumes,
0806 faceOne);
0807 } else {
0808
0809 ACTS_VERBOSE(" glue : many[ "
0810 << tvolOne->volumeName() << " @ " << faceOne << " ]-to-many[ "
0811 << tvolTwo->volumeName() << " @ " << faceTwo << " ]");
0812
0813
0814 std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> boundarySurface =
0815 nullptr;
0816
0817
0818 Transform3 transform = Transform3::Identity();
0819 if (std::abs(zMin + zMax) > 0.1) {
0820
0821 transform =
0822 Transform3(Translation3(Vector3(0., 0., 0.5 * (zMin + zMax))));
0823 }
0824
0825 if (faceOne == cylinderCover || faceOne == tubeOuterCover) {
0826
0827 auto cBounds =
0828 std::make_shared<CylinderBounds>(rGlueMin, 0.5 * (zMax - zMin));
0829 std::shared_ptr<const RegularSurface> cSurface =
0830 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().z();
0847 double zHL = cylVolBounds->get(CylinderVolumeBounds::eHalfLengthZ);
0848 transform = Transform3(Translation3(0, 0, zPos + zHL));
0849
0850
0851
0852
0853
0854 std::shared_ptr<const RegularSurface> dSurface =
0855 Surface::makeShared<DiscSurface>(transform, rMin, rMax);
0856 ACTS_VERBOSE(
0857 " creating a new disc-like boundary surface "
0858 "with bounds = "
0859 << dSurface->bounds());
0860 ACTS_VERBOSE(" at " << dSurface->center(gctx).transpose());
0861 boundarySurface =
0862 std::make_shared<const BoundarySurfaceT<TrackingVolume>>(
0863 std::move(dSurface), gvDescriptorOne.glueVolumes(faceOne),
0864 gvDescriptorTwo.glueVolumes(faceTwo));
0865 }
0866
0867
0868 std::shared_ptr<const ISurfaceMaterial> boundaryMaterial = nullptr;
0869
0870 ACTS_VERBOSE("New Boundary surface setting for containers");
0871 ACTS_VERBOSE(" - at first volume: " << tvolOne->volumeName());
0872
0873
0874 for (auto& oneVolume :
0875 gvDescriptorOne.glueVolumes(faceOne)->arrayObjects()) {
0876 auto mutableOneVolume =
0877 std::const_pointer_cast<TrackingVolume>(oneVolume);
0878
0879 if (boundaryMaterial == nullptr) {
0880 auto oneBSurface = mutableOneVolume->boundarySurfaces()[faceOne];
0881 boundaryMaterial =
0882 oneBSurface->surfaceRepresentation().surfaceMaterialSharedPtr();
0883 }
0884 mutableOneVolume->updateBoundarySurface(faceOne, boundarySurface);
0885 ACTS_VERBOSE(" -> setting boundary surface to volume: "
0886 << mutableOneVolume->volumeName());
0887 }
0888 ACTS_VERBOSE(" - at second volume: " << tvolTwo->volumeName());
0889 for (auto& twoVolume :
0890 gvDescriptorTwo.glueVolumes(faceTwo)->arrayObjects()) {
0891 auto mutableTwoVolume =
0892 std::const_pointer_cast<TrackingVolume>(twoVolume);
0893
0894 if (boundaryMaterial == nullptr) {
0895 auto twoBSurface = mutableTwoVolume->boundarySurfaces()[faceTwo];
0896 boundaryMaterial =
0897 twoBSurface->surfaceRepresentation().surfaceMaterialSharedPtr();
0898 }
0899 mutableTwoVolume->updateBoundarySurface(faceTwo, boundarySurface);
0900 ACTS_VERBOSE(" -> setting boundary surface to volume: "
0901 << mutableTwoVolume->volumeName());
0902 }
0903
0904
0905 if (boundaryMaterial != nullptr) {
0906
0907 ACTS_VERBOSE("- the new boundary surface has boundary material: ");
0908 ACTS_VERBOSE(" " << *boundaryMaterial);
0909 RegularSurface* newSurface = const_cast<RegularSurface*>(
0910 &(boundarySurface->surfaceRepresentation()));
0911 newSurface->assignSurfaceMaterial(boundaryMaterial);
0912 }
0913
0914 }
0915 }
0916
0917
0918 void CylinderVolumeHelper::addFaceVolumes(
0919 const std::shared_ptr<TrackingVolume>& tvol, BoundarySurfaceFace glueFace,
0920 TrackingVolumeVector& vols) const {
0921 ACTS_VERBOSE("Adding face volumes of face " << glueFace << " for the volume '"
0922 << tvol->volumeName() << "'.");
0923
0924 const GlueVolumesDescriptor& gvDescriptor = tvol->glueVolumesDescriptor();
0925
0926 if (gvDescriptor.glueVolumes(glueFace)) {
0927
0928 auto volIter = gvDescriptor.glueVolumes(glueFace)->arrayObjects().begin();
0929 auto volEnd = gvDescriptor.glueVolumes(glueFace)->arrayObjects().end();
0930 for (; volIter != volEnd; ++volIter) {
0931 ACTS_VERBOSE(" -> adding : " << (*volIter)->volumeName());
0932 vols.push_back(*volIter);
0933 }
0934
0935 ACTS_VERBOSE(vols.size()
0936 << " navigation volumes registered as glue volumes.");
0937 } else {
0938
0939 ACTS_VERBOSE(" -> adding only volume itself (at navigation level).");
0940 vols.push_back(tvol);
0941 }
0942 }
0943
0944 std::shared_ptr<const Layer> CylinderVolumeHelper::createCylinderLayer(
0945 double z, double r, double halflengthZ, double thickness, int binsPhi,
0946 int binsZ) const {
0947 ACTS_VERBOSE("Creating a CylinderLayer at position " << z << " and radius "
0948 << r);
0949
0950 const Transform3 transform(Translation3(0., 0., z));
0951
0952
0953 BinUtility layerBinUtility(binsZ, z - halflengthZ, z + halflengthZ, open,
0954 AxisDirection::AxisZ);
0955 if (binsPhi == 1) {
0956
0957
0958 ACTS_VERBOSE(" -> Preparing the binned material with " << binsZ
0959 << " bins in Z. ");
0960
0961 } else {
0962
0963 BinUtility layerBinUtilityPhiZ(binsPhi, -r * std::numbers::pi,
0964 r * std::numbers::pi, closed,
0965 AxisDirection::AxisPhi);
0966 layerBinUtilityPhiZ += layerBinUtility;
0967
0968 ACTS_VERBOSE(" -> Preparing the binned material with "
0969 << binsPhi << " / " << binsZ << " bins in phi / Z. ");
0970 }
0971
0972
0973 CylinderBounds* cylinderBounds = new CylinderBounds(r, halflengthZ);
0974
0975 return CylinderLayer::create(
0976 transform, std::shared_ptr<const CylinderBounds>(cylinderBounds), nullptr,
0977 thickness);
0978 }
0979
0980 std::shared_ptr<const Layer> CylinderVolumeHelper::createDiscLayer(
0981 double z, double rMin, double rMax, double thickness, int binsPhi,
0982 int binsR) const {
0983 ACTS_VERBOSE("Creating a DiscLayer at position " << z << " and rMin/rMax "
0984 << rMin << " / " << rMax);
0985
0986
0987 const Transform3 transform(Translation3(0., 0., z));
0988
0989
0990 BinUtility materialBinUtility(binsR, rMin, rMax, open, AxisDirection::AxisR);
0991 if (binsPhi == 1) {
0992 ACTS_VERBOSE(" -> Preparing the binned material with " << binsR
0993 << " bins in R. ");
0994 } else {
0995
0996 materialBinUtility +=
0997 BinUtility(binsPhi, -std::numbers::pi_v<float>,
0998 std::numbers::pi_v<float>, closed, AxisDirection::AxisPhi);
0999 ACTS_VERBOSE(" -> Preparing the binned material with "
1000 << binsPhi << " / " << binsR << " bins in phi / R. ");
1001 }
1002
1003
1004
1005 RadialBounds* discBounds = new RadialBounds(rMin, rMax);
1006
1007 return DiscLayer::create(transform,
1008 std::shared_ptr<const DiscBounds>(discBounds),
1009 nullptr, thickness);
1010 }
1011
1012 }