Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:11:28

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