Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 08:13:01

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/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0010 
0011 #include "Acts/Geometry/Blueprint.hpp"
0012 #include "Acts/Geometry/BlueprintOptions.hpp"
0013 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0014 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBuilder.hpp"
0016 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
0017 #include "Acts/Geometry/LayerBlueprintNode.hpp"
0018 #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp"
0019 #include "Acts/Geometry/PassiveLayerBuilder.hpp"
0020 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0021 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
0022 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0023 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0024 #include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp"
0025 #include "Acts/Navigation/TryAllNavigationPolicy.hpp"
0026 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0027 #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0028 #include "Acts/Utilities/AxisDefinitions.hpp"
0029 
0030 namespace Acts::Test {
0031 
0032 std::vector<Surface*> CylindricalTrackingGeometry::surfacesRing(
0033     DetectorStore& detStore, double moduleHalfXminY, double moduleHalfXmaxY,
0034     double moduleHalfY, double moduleThickness, double moduleTilt,
0035     double ringRadius, double ringZ, double zStagger, int nPhi) {
0036   std::vector<Surface*> layerSurfaces;
0037 
0038   // Module material from input
0039   MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
0040 
0041   // Create a new surface material
0042   std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
0043       std::shared_ptr<const ISurfaceMaterial>(
0044           new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
0045 
0046   // The rectangle/trapezoid bounds for all modules
0047   std::shared_ptr<PlanarBounds> mBounds = nullptr;
0048   if (moduleHalfXminY == moduleHalfXmaxY) {
0049     mBounds = std::make_shared<RectangleBounds>(moduleHalfXminY, moduleHalfY);
0050   } else {
0051     mBounds = std::make_shared<TrapezoidBounds>(moduleHalfXminY,
0052                                                 moduleHalfXmaxY, moduleHalfY);
0053   }
0054 
0055   double phiStep = 2 * std::numbers::pi / nPhi;
0056 
0057   for (int im = 0; im < nPhi; ++im) {
0058     // Get the moduleTransform
0059     double phi = -std::numbers::pi + im * phiStep;
0060     auto mModuleTransform = Transform3(
0061         Translation3(ringRadius * std::cos(phi), ringRadius * std::sin(phi),
0062                      ringZ + (im % 2) * zStagger) *
0063         AngleAxis3(phi - std::numbers::pi / 2., Vector3::UnitZ()) *
0064         AngleAxis3(moduleTilt, Vector3::UnitY()));
0065 
0066     // Create the detector element
0067     auto detElement = std::make_unique<DetectorElementStub>(
0068         mModuleTransform, mBounds, moduleThickness, moduleMaterialPtr);
0069 
0070     layerSurfaces.push_back(&detElement->surface());
0071     detStore.push_back(std::move(detElement));
0072   }
0073 
0074   return layerSurfaces;
0075 }
0076 
0077 std::vector<Surface*> CylindricalTrackingGeometry::surfacesCylinder(
0078     DetectorStore& detStore, double moduleHalfX, double moduleHalfY,
0079     double moduleThickness, double moduleTiltPhi, double layerRadius,
0080     double radialStagger, double longitudinalOverlap,
0081     const std::pair<int, int>& binningSchema) {
0082   std::vector<Surface*> layerSurfaces;
0083 
0084   // Module material from input
0085   MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
0086 
0087   // Create a new surface material
0088   std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
0089       std::shared_ptr<const ISurfaceMaterial>(
0090           new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
0091 
0092   // The rectangle bounds for all modules
0093   auto mBounds = std::make_shared<RectangleBounds>(moduleHalfX, moduleHalfY);
0094 
0095   // Create the module centers
0096   auto moduleCenters =
0097       modulePositionsCylinder(layerRadius, radialStagger, moduleHalfY,
0098                               longitudinalOverlap, binningSchema);
0099 
0100   for (auto& mCenter : moduleCenters) {
0101     // The association transform
0102     double modulePhi = VectorHelpers::phi(mCenter);
0103     // Local z axis is the normal vector
0104     Vector3 moduleLocalZ(cos(modulePhi + moduleTiltPhi),
0105                          sin(modulePhi + moduleTiltPhi), 0.);
0106     // Local y axis is the global z axis
0107     Vector3 moduleLocalY(0., 0., 1);
0108     // Local x axis the normal to local y,z
0109     Vector3 moduleLocalX(-sin(modulePhi + moduleTiltPhi),
0110                          cos(modulePhi + moduleTiltPhi), 0.);
0111     // Create the RotationMatrix
0112     RotationMatrix3 moduleRotation;
0113     moduleRotation.col(0) = moduleLocalX;
0114     moduleRotation.col(1) = moduleLocalY;
0115     moduleRotation.col(2) = moduleLocalZ;
0116     // Get the moduleTransform
0117     auto mModuleTransform = Transform3(Translation3(mCenter) * moduleRotation);
0118     // Create the detector element
0119     auto detElement = std::make_unique<DetectorElementStub>(
0120         mModuleTransform, mBounds, moduleThickness, moduleMaterialPtr);
0121 
0122     layerSurfaces.push_back(&detElement->surface());
0123     detStore.push_back(std::move(detElement));
0124   }
0125   return layerSurfaces;
0126 }
0127 
0128 /// Helper method for cylinder layer
0129 /// create the positions for module surfaces on a cylinder
0130 std::vector<Vector3> CylindricalTrackingGeometry::modulePositionsCylinder(
0131     double radius, double zStagger, double moduleHalfLength, double lOverlap,
0132     const std::pair<int, int>& binningSchema) {
0133   int nPhiBins = binningSchema.first;
0134   int nZbins = binningSchema.second;
0135   // prepare the return value
0136   std::vector<Vector3> mPositions;
0137   mPositions.reserve(nPhiBins * nZbins);
0138   // prep work
0139   double phiStep = 2 * std::numbers::pi / (nPhiBins);
0140   double minPhi = -std::numbers::pi + phiStep / 2.;
0141   double zStart = -0.5 * (nZbins - 1) * (2 * moduleHalfLength - lOverlap);
0142   double zStep = 2 * std::abs(zStart) / (nZbins - 1);
0143   // loop over the bins
0144   for (std::size_t zBin = 0; zBin < static_cast<std::size_t>(nZbins); ++zBin) {
0145     // prepare z and r
0146     double moduleZ = zStart + zBin * zStep;
0147     double moduleR =
0148         (zBin % 2) != 0u ? radius - 0.5 * zStagger : radius + 0.5 * zStagger;
0149     for (std::size_t phiBin = 0; phiBin < static_cast<std::size_t>(nPhiBins);
0150          ++phiBin) {
0151       // calculate the current phi value
0152       double modulePhi = minPhi + phiBin * phiStep;
0153       mPositions.push_back(
0154           Vector3(moduleR * cos(modulePhi), moduleR * sin(modulePhi), moduleZ));
0155     }
0156   }
0157   return mPositions;
0158 }
0159 
0160 std::shared_ptr<TrackingGeometry> CylindricalTrackingGeometry::buildGen1() {
0161   using namespace Acts::UnitLiterals;
0162 
0163   Logging::Level surfaceLLevel = Logging::INFO;
0164   Logging::Level layerLLevel = Logging::INFO;
0165   Logging::Level volumeLLevel = Logging::INFO;
0166 
0167   // configure surface array creator
0168   auto surfaceArrayCreator = std::make_shared<const SurfaceArrayCreator>(
0169       getDefaultLogger("SurfaceArrayCreator", surfaceLLevel));
0170   // configure the layer creator that uses the surface array creator
0171   LayerCreator::Config lcConfig;
0172   lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0173   auto layerCreator = std::make_shared<const LayerCreator>(
0174       lcConfig, getDefaultLogger("LayerCreator", layerLLevel));
0175   // configure the layer array creator
0176   LayerArrayCreator::Config lacConfig;
0177   auto layerArrayCreator = std::make_shared<const LayerArrayCreator>(
0178       lacConfig, getDefaultLogger("LayerArrayCreator", layerLLevel));
0179 
0180   // tracking volume array creator
0181   TrackingVolumeArrayCreator::Config tvacConfig;
0182   auto tVolumeArrayCreator = std::make_shared<const TrackingVolumeArrayCreator>(
0183       tvacConfig, getDefaultLogger("TrackingVolumeArrayCreator", volumeLLevel));
0184   // configure the cylinder volume helper
0185   CylinderVolumeHelper::Config cvhConfig;
0186   cvhConfig.layerArrayCreator = layerArrayCreator;
0187   cvhConfig.trackingVolumeArrayCreator = tVolumeArrayCreator;
0188   auto cylinderVolumeHelper = std::make_shared<const CylinderVolumeHelper>(
0189       cvhConfig, getDefaultLogger("CylinderVolumeHelper", volumeLLevel));
0190 
0191   // ----------------- build a beam pipe -----------------------------------
0192   MaterialSlab beamPipeMaterial(makeBeryllium(), 0.8_mm);
0193   PassiveLayerBuilder::Config bplConfig;
0194   bplConfig.layerIdentification = "BeamPipe";
0195   bplConfig.centralLayerRadii = std::vector<double>(1, kBeamPipeRadius);
0196   bplConfig.centralLayerHalflengthZ =
0197       std::vector<double>(1, kBeamPipeHalfLengthZ);
0198   bplConfig.centralLayerThickness = std::vector<double>(1, kBeamPipeThickness);
0199   bplConfig.centralLayerMaterial = {
0200       std::make_shared<const HomogeneousSurfaceMaterial>(beamPipeMaterial)};
0201   auto beamPipeBuilder = std::make_shared<const PassiveLayerBuilder>(
0202       bplConfig, getDefaultLogger("BeamPipeLayerBuilder", layerLLevel));
0203   // create the volume for the beam pipe
0204   CylinderVolumeBuilder::Config bpvConfig;
0205   bpvConfig.trackingVolumeHelper = cylinderVolumeHelper;
0206   bpvConfig.volumeName = "BeamPipe";
0207   bpvConfig.layerBuilder = beamPipeBuilder;
0208   bpvConfig.layerEnvelopeR = {1_mm, 1_mm};
0209   bpvConfig.buildToRadiusZero = true;
0210   auto beamPipeVolumeBuilder = std::make_shared<const CylinderVolumeBuilder>(
0211       bpvConfig, getDefaultLogger("BeamPipeVolumeBuilder", volumeLLevel));
0212 
0213   // create the bounds and the volume
0214   auto beamPipeBounds =
0215       std::make_shared<const CylinderVolumeBounds>(0., 25., 1100.);
0216   auto beamPipeVolume = beamPipeVolumeBuilder->trackingVolume(
0217       geoContext, nullptr, beamPipeBounds);
0218 
0219   //-------------------------------------------------------------------------------------
0220   // some prep work for the material
0221   // Layer material properties - thickness, X0, L0, A, Z, Rho
0222   MaterialSlab lProperties(makeSilicon(), 1.5_mm);
0223 
0224   auto layerMaterialPtr =
0225       std::make_shared<HomogeneousSurfaceMaterial>(lProperties);
0226 
0227   std::vector<LayerPtr> pLayers;
0228 
0229   for (std::size_t ilp = 0; ilp < kLayerRadii.size(); ++ilp) {
0230     std::vector<Surface*> layerSurfacesMutable =
0231         surfacesCylinder(detectorStore, kModuleHalfX[ilp], kModuleHalfY[ilp],
0232                          kModuleThickness[ilp], kModuleTiltPhi[ilp],
0233                          kLayerRadii[ilp], 2_mm, 5_mm, kLayerBinning[ilp]);
0234 
0235     std::vector<const Surface*> layerSurfaces;
0236     std::ranges::transform(layerSurfacesMutable,
0237                            std::back_inserter(layerSurfaces),
0238                            [](Surface* s) { return s; });
0239 
0240     // Make a shared version out of it
0241     std::vector<std::shared_ptr<const Surface>> layerSurfacePtrs;
0242     layerSurfacePtrs.reserve(layerSurfaces.size());
0243     for (auto& sf : layerSurfaces) {
0244       layerSurfacePtrs.push_back(sf->getSharedPtr());
0245     }
0246 
0247     // create the layer and store it
0248     ProtoLayer protoLayer(geoContext, layerSurfaces);
0249     protoLayer.envelope[AxisDirection::AxisR] = {0.5, 0.5};
0250     auto pLayer = layerCreator->cylinderLayer(
0251         geoContext, std::move(layerSurfacePtrs), kLayerBinning[ilp].first,
0252         kLayerBinning[ilp].second, protoLayer);
0253     auto approachSurfaces = pLayer->approachDescriptor()->containedSurfaces();
0254     auto mutableOuterSurface =
0255         const_cast<Acts::Surface*>(approachSurfaces.at(1));
0256     mutableOuterSurface->assignSurfaceMaterial(layerMaterialPtr);
0257     /// now push back the layer
0258     pLayers.push_back(pLayer);
0259 
0260   }  // loop over layers
0261 
0262   // layer array
0263   auto pLayerArray = layerArrayCreator->layerArray(
0264       geoContext, pLayers, 25., 300., arbitrary, AxisDirection::AxisR);
0265   auto pVolumeBounds = std::make_shared<CylinderVolumeBounds>(25., 300., 1100.);
0266   // create the Tracking volume
0267   auto pVolume = std::make_shared<TrackingVolume>(
0268       Transform3::Identity(), pVolumeBounds, nullptr, std::move(pLayerArray),
0269       nullptr, MutableTrackingVolumeVector{}, "Pixel::Barrel");
0270 
0271   // The combined volume
0272   auto detectorVolume = cylinderVolumeHelper->createContainerTrackingVolume(
0273       geoContext, {beamPipeVolume, pVolume});
0274 
0275   // create and return the geometry
0276   return std::make_shared<TrackingGeometry>(detectorVolume);
0277 }
0278 
0279 std::shared_ptr<TrackingGeometry> CylindricalTrackingGeometry::buildGen3() {
0280   using namespace Acts::Experimental;
0281   using namespace Acts::UnitLiterals;
0282   using enum Acts::CylinderVolumeBounds::Face;
0283   using enum Acts::AxisDirection;
0284   using LayerType = LayerBlueprintNode::LayerType;
0285 
0286   const MaterialSlab lProperties(makeSilicon(), 1.5_mm);
0287 
0288   // Create a binned material in 2 bins - irregularly in r, 2 bins in phi
0289   std::vector<float> binEdges = {
0290       0., 5.,
0291       179.48552,  // empirical maximum radius
0292   };
0293   Acts::BinUtility binUtility(binEdges, Acts::BinningOption::open, AxisR);
0294   binUtility += Acts::BinUtility(2u, -std::numbers::pi, std::numbers::pi,
0295                                  Acts::BinningOption::closed, AxisPhi);
0296 
0297   std::vector<Acts::MaterialSlab> materialSlabs0 = {lProperties, lProperties};
0298   std::vector<Acts::MaterialSlab> materialSlabs1 = {lProperties, lProperties};
0299 
0300   auto binnedMaterial = std::make_shared<Acts::BinnedSurfaceMaterial>(
0301       binUtility, std::vector{materialSlabs0, materialSlabs1}, 0.,
0302       Acts::MappingType::Default);
0303 
0304   Blueprint::Config cfg;
0305   cfg.envelope = Acts::ExtentEnvelope{{
0306       .z = {20_mm, 20_mm},
0307       .r = {0_mm, 20_mm},
0308   }};
0309   Blueprint root{cfg};
0310 
0311   auto& barrelMat = root.addMaterial("BarrelMaterial");
0312   barrelMat.configureFace(PositiveDisc, binnedMaterial);
0313   barrelMat.configureFace(NegativeDisc, binnedMaterial);
0314 
0315   barrelMat.addCylinderContainer("Detector", AxisR, [&](auto& detector) {
0316     auto beampipeBounds = std::make_unique<Acts::CylinderVolumeBounds>(
0317         0_mm, kBeamPipeRadius, 100_mm);
0318     auto beampipe = std::make_unique<Acts::TrackingVolume>(
0319         Acts::Transform3::Identity(), std::move(beampipeBounds), "Beampipe");
0320 
0321     detector.addMaterial("BeampipeMaterial", [&](auto& bpMat) {
0322       MaterialSlab beamPipeMaterial(makeBeryllium(), kBeamPipeThickness);
0323       bpMat.configureFace(
0324           OuterCylinder,
0325           std::make_shared<HomogeneousSurfaceMaterial>(beamPipeMaterial));
0326       bpMat.addStaticVolume(std::move(beampipe));
0327     });
0328 
0329     auto layerMaterialPtr =
0330         std::make_shared<HomogeneousSurfaceMaterial>(lProperties);
0331 
0332     for (std::size_t ilp = 0; ilp < kLayerRadii.size(); ++ilp) {
0333       std::vector<Surface*> layerSurfaces =
0334           surfacesCylinder(detectorStore, kModuleHalfX[ilp], kModuleHalfY[ilp],
0335                            kModuleThickness[ilp], kModuleTiltPhi[ilp],
0336                            kLayerRadii[ilp], 2_mm, 5_mm, kLayerBinning[ilp]);
0337 
0338       // Make a shared version out of it
0339       std::vector<std::shared_ptr<Surface>> layerSurfacePtrs;
0340       layerSurfacePtrs.reserve(layerSurfaces.size());
0341       for (auto& sf : layerSurfaces) {
0342         layerSurfacePtrs.push_back(sf->getSharedPtr());
0343       }
0344 
0345       // create the layer and store it
0346       MutableProtoLayer protoLayer(geoContext, layerSurfaces);
0347       protoLayer.envelope[AxisR] = {0.5, 0.5};
0348 
0349       std::string layerName = "L" + std::to_string(ilp);
0350       detector.addMaterial(layerName + "_Mat", [&](auto& mat) {
0351         mat.configureFace(OuterCylinder, layerMaterialPtr);
0352         mat.addLayer(layerName, [&](auto& layer) {
0353           layer.setProtoLayer(protoLayer);
0354           layer.setLayerType(LayerType::Cylinder);
0355           layer.setEnvelope(
0356               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0357 
0358           using SrfArrayNavPol = Acts::SurfaceArrayNavigationPolicy;
0359 
0360           layer.setNavigationPolicyFactory(
0361               Acts::NavigationPolicyFactory{}
0362                   .add<Acts::TryAllNavigationPolicy>(
0363                       Acts::TryAllNavigationPolicy::Config{.sensitives = false})
0364                   .add<SrfArrayNavPol>(SrfArrayNavPol::Config{
0365                       .layerType = SrfArrayNavPol::LayerType::Cylinder,
0366                       .bins = kLayerBinning[ilp]})
0367                   .asUniquePtr());
0368         });
0369       });
0370 
0371     }  // loop over layers
0372   });
0373 
0374   BlueprintOptions opts;
0375   return root.construct(opts, geoContext);
0376 }
0377 
0378 std::shared_ptr<TrackingGeometry> CylindricalTrackingGeometry::operator()() {
0379   if (gen3) {
0380     return buildGen3();
0381   } else {
0382     return buildGen1();
0383   }
0384 }
0385 }  // namespace Acts::Test