Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:02:15

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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 // configuration
0052 void CylinderVolumeHelper::setConfiguration(
0053     const CylinderVolumeHelper::Config& cvhConfig) {
0054   // @todo check consistency
0055   // copy the configuration
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   // the final one to build / sensitive Volume / Bounds
0070   MutableTrackingVolumePtr tVolume = nullptr;
0071   // the layer array
0072   std::unique_ptr<const LayerArray> layerArray = nullptr;
0073 
0074   // Cases are:
0075   // (1) volumeBounds && transform : use both information
0076   // (2) volumeBounds && transform==identity : centered around 0, but with
0077   //     given bounds
0078   // (3) !volumeBounds && transform : estimate size from layers,
0079   //     use transform
0080   // (4) !volumeBounds && transform==identity : estimate size &
0081   //     translation from layers
0082   bool idTrf = transform.isApprox(Transform3::Identity());
0083 
0084   auto cylinderBounds =
0085       std::dynamic_pointer_cast<CylinderVolumeBounds>(volumeBounds);
0086   // this is the implementation of CylinderVolumeHelper
0087   if (volumeBounds != nullptr && cylinderBounds == nullptr) {
0088     ACTS_WARNING(
0089         "[!] Problem: given bounds are not cylindrical - return nullptr");
0090     return tVolume;
0091   }
0092   // this is only needed if layers are provided
0093   if (!layers.empty()) {
0094     // the raw data
0095     double rMinRaw = 0.;
0096     double rMaxRaw = 0.;
0097     double zMinRaw = 0.;
0098     double zMaxRaw = 0.;
0099 
0100     AxisDirection bValue = AxisDirection::AxisR;
0101 
0102     // check the dimension and fill raw data
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     // we might have overwritten the bounds in estimateAndCheckDimension
0112     volumeBounds = cylinderBounds;
0113     // get the zMin/Max
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     // get the rMin/rmAx
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     // create the Layer Array
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   }  // layers are created and done
0144   // finally create the TrackingVolume
0145   tVolume = std::make_shared<TrackingVolume>(
0146       transform, volumeBounds, volumeMaterial, std::move(layerArray), nullptr,
0147       mtvVector, volumeName);
0148   // screen output
0149   ACTS_VERBOSE(
0150       "Created cylindrical volume at z-position :" << tVolume->center().z());
0151   ACTS_VERBOSE("   created bounds : " << tVolume->volumeBounds());
0152   // return the constructed TrackingVolume
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   // Screen output
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   // check for consistency
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   // create a Transform3 and VolumeBounds out of the zMin/zMax
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   // now create the cylinder volume bounds
0182   auto cBounds =
0183       std::make_shared<CylinderVolumeBounds>(rMin, rMax, halflengthZ);
0184 
0185   // transform
0186   const Transform3 transform = Transform3(Translation3(0., 0., zPosition));
0187   // call to the creation method with Bounds & Translation3
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   // screen output
0198   ACTS_VERBOSE("Create cylindrical gap TrackingVolume '"
0199                << volumeName << "' with (rMin/rMax/zMin/Max) = ");
0200   ACTS_VERBOSE("\t" << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
0201 
0202   // assign min/max
0203   double min = cylinder ? rMin : zMin;
0204   double max = cylinder ? rMax : zMax;
0205 
0206   // create the layer r/z positions
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   // now call the main method
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   // screen output
0230   ACTS_VERBOSE("Create cylindrical gap TrackingVolume '"
0231                << volumeName << "' with (rMin/rMax/zMin/Max) = ");
0232   ACTS_VERBOSE("\t" << rMin << " / " << rMax << " / " << zMin << " / " << zMax);
0233 
0234   // create the layers
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     // create cylinder layers
0242     if (cylinder) {
0243       // take envelopes into account
0244       double zMinLayer = zMin;
0245       double zMaxLayer = zMax;
0246       // create the layer
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       // take the envelopes into account
0254       double rMinLayer = rMin;
0255       double rMaxLayer = rMax;
0256       // create the layer
0257       layers.push_back(createDiscLayer(
0258           (*layerPropIter), rMinLayer, rMaxLayer, m_cfg.passiveLayerThickness,
0259           m_cfg.passiveLayerPhiBins, m_cfg.passiveLayerRzBins));
0260     }
0261   }
0262   // now call the createTrackingVolume() method
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   // check if you have more than one volume
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   // screen output
0278   std::string volumeName = "{ ";
0279   ACTS_VERBOSE("[start] Creating a container volume with " << volumes.size()
0280                                                            << " sub volumes:");
0281   // volumes need to be sorted in either r or z - both increasing
0282   // set the iterator to the volumes, the first and the end
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     // put the name together
0299     volumeName += (*firstVolume)->volumeName();
0300     if (ivol + 1 < volumes.size()) {
0301       volumeName += " | ";
0302     }
0303   }
0304   // close the volume name
0305   volumeName += " }";
0306   // reset the iterator -----
0307   firstVolume = volumes.begin();
0308   --lastVolume;  // set to the last volume
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   // get the bounds
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   // check the dynamic cast
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   // Check whether it is an r-binned case or a z-binned case
0331   bool rCase =
0332       std::abs(firstVolumeBounds->get(CylinderVolumeBounds::eMinR) -
0333                lastVolumeBounds->get(CylinderVolumeBounds::eMinR)) > 0.1;
0334 
0335   // Fill these ones depending on the rCase though assignment
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   // Estimate the z - position
0365   double zPos = 0.5 * (zMin + zMax);
0366   // Create the transform from the stuff known so far
0367   const Transform3 topVolumeTransform = Transform3(Translation3(0., 0., zPos));
0368   // Create the bounds from the information gathered so far
0369   auto topVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0370       rMin, rMax, 0.5 * std::abs(zMax - zMin));
0371 
0372   // some screen output
0373   ACTS_VERBOSE("Container volume bounds are " << (*topVolumeBounds));
0374 
0375   // create the volume array with the ITrackingVolumeArrayCreator
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   // we have the bounds and the volume array, create the volume
0387   std::shared_ptr<TrackingVolume> topVolume = std::make_shared<TrackingVolume>(
0388       topVolumeTransform, topVolumeBounds, nullptr, nullptr, volumeArray,
0389       MutableTrackingVolumeVector{}, volumeName);
0390   // glueing section
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 /** private helper method to estimate and check the dimensions of a tracking
0407  * volume */
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 /*bType*/) const {
0414   // some verbose output
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   // prepare for parsing the layers
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   // find out what is there
0440   for (auto& layerIter : layers) {
0441     // initialize
0442     double currentRmin = 0.;
0443     double currentRmax = 0.;
0444     double currentZmin = 0.;
0445     double currentZmax = 0.;
0446     // dynamic cast the bounds either to CylinderBounds or DiscBounds
0447     const CylinderBounds* cylBounds = dynamic_cast<const CylinderBounds*>(
0448         &(layerIter->surfaceRepresentation()).bounds());
0449     // cylinder bounds
0450     if (cylBounds != nullptr) {
0451       radial = true;
0452       // get the raw data
0453       double currentR = cylBounds->get(CylinderBounds::eR);
0454       double centerZ = (layerIter->surfaceRepresentation()).center(gctx).z();
0455       // check for min/max in the cylinder bounds case
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     // dynamic cast to the DiscBounds
0462     const RadialBounds* discBounds = dynamic_cast<const RadialBounds*>(
0463         &(layerIter->surfaceRepresentation()).bounds());
0464     if (discBounds != nullptr) {
0465       // check for min/max in the cylinder bounds case
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     // the raw data
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     // assign if they overrule the minima/maxima (with layers thicknesses)
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   // set the binning value
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   // the z from the layers w and w/o envelopes
0491   double zEstFromLayerEnv = 0.5 * (layerZmax + layerZmin);
0492   double halflengthFromLayer = 0.5 * std::abs(layerZmax - layerZmin);
0493 
0494   // using `sqrt(0.001) = 0.031622777` because previously it compared to
0495   // `zEstFromLayerEnv * zEstFromLayerEnv < 0.001` which was changed due to
0496   // underflow/overflow concerns
0497   bool concentric = std::abs(zEstFromLayerEnv) < 0.031622777;
0498 
0499   bool idTrf = transform.isApprox(Transform3::Identity());
0500 
0501   Transform3 vtransform = Transform3::Identity();
0502   // no CylinderBounds and Translation given - make it
0503   if ((cylinderVolumeBounds == nullptr) && idTrf) {
0504     // create the CylinderBounds from parsed layer inputs
0505     cylinderVolumeBounds = std::make_shared<CylinderVolumeBounds>(
0506         layerRmin, layerRmax, halflengthFromLayer);
0507     // and the transform
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     // create the CylinderBounds from parsed layer inputs
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   // both is NOW given --- check it -----------------------------
0534   if (cylinderVolumeBounds != nullptr) {
0535     // only check
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   // only go on if you have confinedVolumes
0579   if (tVolume->confinedVolumes()) {
0580     // get the glueVolumes descriptor of the top volume to register the outside
0581     // volumes
0582     GlueVolumesDescriptor& glueDescr = tVolume->glueVolumesDescriptor();
0583 
0584     // now retrieve the volumes
0585     auto& volumes = tVolume->confinedVolumes()->arrayObjects();
0586 
0587     // list the volume names:
0588     //  and make the screen output readable
0589     std::size_t ivol = 0;
0590     for (auto& vol : volumes) {
0591       ACTS_VERBOSE("[" << ivol++ << "] - volume : " << vol->volumeName());
0592     }
0593 
0594     // the needed iterators
0595     auto tVolIter = volumes.begin();
0596     auto tVolFirst = volumes.begin();
0597     auto tVolLast = volumes.end();
0598     --tVolLast;
0599     auto tVolEnd = volumes.end();
0600 
0601     // the glue volumes for the description
0602     TrackingVolumeVector glueVolumesInnerTube;
0603     TrackingVolumeVector glueVolumesOuterTube;
0604     TrackingVolumeVector glueVolumesNegativeFace;
0605     TrackingVolumeVector glueVolumesPositiveFace;
0606     // reset ivol counter
0607     ivol = 0;
0608     // volumes of increasing r
0609     if (rBinned) {
0610       // loop over the volumes -------------------------------
0611       for (; tVolIter != tVolEnd;) {
0612         // screen output
0613         ACTS_VERBOSE("r-binning: Processing volume [" << ivol++ << "]");
0614         // for the first one
0615         std::shared_ptr<TrackingVolume> tVol =
0616             std::const_pointer_cast<TrackingVolume>(*tVolIter);
0617         if (tVolIter == tVolFirst) {
0618           addFaceVolumes(tVol, tubeInnerCover, glueVolumesInnerTube);
0619         }
0620         // add this or the subvolumes to the negativeFace and positiveFace
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           // re-evalueate rGlueMin
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       // Volumes in increasing z
0645       // Loop over the volumes
0646       for (; tVolIter != tVolEnd;) {
0647         // screen output
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     // create BinnedArraysand register then to the glue volume descriptor for
0671     // upstream glueing
0672     if (!glueVolumesNegativeFace.empty()) {
0673       // create the outside volume array
0674       std::shared_ptr<const TrackingVolumeArray> glueVolumesNegativeFaceArray =
0675           m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0676               gctx, glueVolumesNegativeFace, AxisDirection::AxisR);
0677       // register the glue voluems
0678       glueDescr.registerGlueVolumes(negativeFaceXY,
0679                                     glueVolumesNegativeFaceArray);
0680     }
0681     if (!glueVolumesPositiveFace.empty()) {
0682       // create the outside volume array
0683       std::shared_ptr<const TrackingVolumeArray> glueVolumesPositiveFaceArray =
0684           m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0685               gctx, glueVolumesPositiveFace, AxisDirection::AxisR);
0686       // register the glue voluems
0687       glueDescr.registerGlueVolumes(positiveFaceXY,
0688                                     glueVolumesPositiveFaceArray);
0689     }
0690     if (!glueVolumesInnerTube.empty()) {
0691       // create the outside volume array
0692       std::shared_ptr<const TrackingVolumeArray> glueVolumesInnerTubeArray =
0693           m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0694               gctx, glueVolumesInnerTube, AxisDirection::AxisZ);
0695       // register the glue voluems
0696       glueDescr.registerGlueVolumes(tubeInnerCover, glueVolumesInnerTubeArray);
0697     }
0698     if (!glueVolumesOuterTube.empty()) {
0699       // create the outside volume array
0700       std::shared_ptr<const TrackingVolumeArray> glueVolumesOuterTubeArray =
0701           m_cfg.trackingVolumeArrayCreator->trackingVolumeArray(
0702               gctx, glueVolumesOuterTube, AxisDirection::AxisZ);
0703       // register the glue voluems
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   // return success
0733   return true;
0734 }
0735 
0736 /** private helper method to fill the glue volumes (or the volume itself in) */
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   // get the two gluevolume descriptors
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   // they could still be a container though - should not happen usually
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   // We'll need to mutate those volumes in order to glue them together
0774   auto mutableGlueVolOne = std::const_pointer_cast<TrackingVolume>(glueVolOne);
0775   auto mutableGlueVolTwo = std::const_pointer_cast<TrackingVolume>(glueVolTwo);
0776 
0777   // check the cases
0778   if (volOneGlueVols <= 1 && volTwoGlueVols <= 1) {
0779     // (i) one -> one
0780     ACTS_VERBOSE("      glue : one[ " << glueVolOne->volumeName() << " @ "
0781                                       << faceOne << " ]-to-one[ "
0782                                       << glueVolTwo->volumeName() << " @ "
0783                                       << faceTwo << " ]");
0784     // one to one is easy
0785     mutableGlueVolOne->glueTrackingVolume(gctx, faceOne,
0786                                           mutableGlueVolTwo.get(), faceTwo);
0787 
0788   } else if (volOneGlueVols <= 1) {
0789     // (ii) one -> many
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     // (iii) many -> one
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     // (iv) glue array to array
0809     ACTS_VERBOSE("      glue : many[ "
0810                  << tvolOne->volumeName() << " @ " << faceOne << " ]-to-many[ "
0811                  << tvolTwo->volumeName() << " @ " << faceTwo << " ]");
0812 
0813     // Create a new BoundarySurface as shared pointer
0814     std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> boundarySurface =
0815         nullptr;
0816 
0817     // the transform of the new boundary surface
0818     Transform3 transform = Transform3::Identity();
0819     if (std::abs(zMin + zMax) > 0.1) {
0820       // it's not a concentric cylinder, so create a transform
0821       transform =
0822           Transform3(Translation3(Vector3(0., 0., 0.5 * (zMin + zMax))));
0823     }
0824     // 2 cases: r-Binning and zBinning
0825     if (faceOne == cylinderCover || faceOne == tubeOuterCover) {
0826       // (1) create the Boundary CylinderSurface
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       // Calculate correct position for disc surface
0842 
0843       // we assume it's cylinder bounds
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       // this puts the surface on the positive z side of the cyl vol bounds
0850       // iteration is from neg to pos, so it should always be in between.
0851 
0852       // (2) create the BoundaryDiscSurface, in that case the zMin/zMax provided
0853       // are both the position of the disk in question
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     // Collect the material - might be ambiguous, first one wins
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     // Update the volume with the boundary surface accordingly
0873     // it's safe to access directly, they can not be nullptr
0874     for (auto& oneVolume :
0875          gvDescriptorOne.glueVolumes(faceOne)->arrayObjects()) {
0876       auto mutableOneVolume =
0877           std::const_pointer_cast<TrackingVolume>(oneVolume);
0878       // Look out for surface material
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       // Look out for surface material
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     // If we have boundary material, let's assign it
0905     if (boundaryMaterial != nullptr) {
0906       // Adapt the boundary material
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   }  // end of case (iv)
0915 }
0916 
0917 /** Private method - helper method not to duplicate code */
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   // retrieve the gluevolume descriptor
0924   const GlueVolumesDescriptor& gvDescriptor = tvol->glueVolumesDescriptor();
0925   // if volumes are registered: take them
0926   if (gvDescriptor.glueVolumes(glueFace)) {
0927     // get the navigation level subvolumes
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     // screen output
0935     ACTS_VERBOSE(vols.size()
0936                  << " navigation volumes registered as glue volumes.");
0937   } else {
0938     // the volume itself is on navigation level
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   // positioning
0950   const Transform3 transform(Translation3(0., 0., z));
0951 
0952   // z-binning
0953   BinUtility layerBinUtility(binsZ, z - halflengthZ, z + halflengthZ, open,
0954                              AxisDirection::AxisZ);
0955   if (binsPhi == 1) {
0956     // the BinUtility for the material
0957     // ---------------------> create material for the layer surface
0958     ACTS_VERBOSE(" -> Preparing the binned material with " << binsZ
0959                                                            << " bins in Z. ");
0960 
0961   } else {  // break the phi symmetry
0962     // update the BinUtility: local position on Cylinder is rPhi, z
0963     BinUtility layerBinUtilityPhiZ(binsPhi, -r * std::numbers::pi,
0964                                    r * std::numbers::pi, closed,
0965                                    AxisDirection::AxisPhi);
0966     layerBinUtilityPhiZ += layerBinUtility;
0967     // ---------------------> create material for the layer surface
0968     ACTS_VERBOSE(" -> Preparing the binned material with "
0969                  << binsPhi << " / " << binsZ << " bins in phi / Z. ");
0970   }
0971   // @todo create the SurfaceMaterial
0972   // bounds for cylinderical surface
0973   CylinderBounds* cylinderBounds = new CylinderBounds(r, halflengthZ);
0974   // create the cylinder
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   // positioning
0987   const Transform3 transform(Translation3(0., 0., z));
0988 
0989   // R is the primary binning for the material
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     // also binning in phi chosen
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   // @todo create the SurfaceMaterial
1004   // bounds for disk-like surface
1005   RadialBounds* discBounds = new RadialBounds(rMin, rMax);
1006   // create the disc
1007   return DiscLayer::create(transform,
1008                            std::shared_ptr<const DiscBounds>(discBounds),
1009                            nullptr, thickness);
1010 }
1011 
1012 }  // namespace Acts