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