File indexing completed on 2025-08-28 08:13:01
0001
0002
0003
0004
0005
0006
0007
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
0039 MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
0040
0041
0042 std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
0043 std::shared_ptr<const ISurfaceMaterial>(
0044 new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
0045
0046
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
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
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
0085 MaterialSlab moduleMaterial(makeSilicon(), moduleThickness);
0086
0087
0088 std::shared_ptr<const ISurfaceMaterial> moduleMaterialPtr =
0089 std::shared_ptr<const ISurfaceMaterial>(
0090 new Acts::HomogeneousSurfaceMaterial(moduleMaterial));
0091
0092
0093 auto mBounds = std::make_shared<RectangleBounds>(moduleHalfX, moduleHalfY);
0094
0095
0096 auto moduleCenters =
0097 modulePositionsCylinder(layerRadius, radialStagger, moduleHalfY,
0098 longitudinalOverlap, binningSchema);
0099
0100 for (auto& mCenter : moduleCenters) {
0101
0102 double modulePhi = VectorHelpers::phi(mCenter);
0103
0104 Vector3 moduleLocalZ(cos(modulePhi + moduleTiltPhi),
0105 sin(modulePhi + moduleTiltPhi), 0.);
0106
0107 Vector3 moduleLocalY(0., 0., 1);
0108
0109 Vector3 moduleLocalX(-sin(modulePhi + moduleTiltPhi),
0110 cos(modulePhi + moduleTiltPhi), 0.);
0111
0112 RotationMatrix3 moduleRotation;
0113 moduleRotation.col(0) = moduleLocalX;
0114 moduleRotation.col(1) = moduleLocalY;
0115 moduleRotation.col(2) = moduleLocalZ;
0116
0117 auto mModuleTransform = Transform3(Translation3(mCenter) * moduleRotation);
0118
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
0129
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
0136 std::vector<Vector3> mPositions;
0137 mPositions.reserve(nPhiBins * nZbins);
0138
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
0144 for (std::size_t zBin = 0; zBin < static_cast<std::size_t>(nZbins); ++zBin) {
0145
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
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
0168 auto surfaceArrayCreator = std::make_shared<const SurfaceArrayCreator>(
0169 getDefaultLogger("SurfaceArrayCreator", surfaceLLevel));
0170
0171 LayerCreator::Config lcConfig;
0172 lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0173 auto layerCreator = std::make_shared<const LayerCreator>(
0174 lcConfig, getDefaultLogger("LayerCreator", layerLLevel));
0175
0176 LayerArrayCreator::Config lacConfig;
0177 auto layerArrayCreator = std::make_shared<const LayerArrayCreator>(
0178 lacConfig, getDefaultLogger("LayerArrayCreator", layerLLevel));
0179
0180
0181 TrackingVolumeArrayCreator::Config tvacConfig;
0182 auto tVolumeArrayCreator = std::make_shared<const TrackingVolumeArrayCreator>(
0183 tvacConfig, getDefaultLogger("TrackingVolumeArrayCreator", volumeLLevel));
0184
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
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
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
0214 auto beamPipeBounds =
0215 std::make_shared<const CylinderVolumeBounds>(0., 25., 1100.);
0216 auto beamPipeVolume = beamPipeVolumeBuilder->trackingVolume(
0217 geoContext, nullptr, beamPipeBounds);
0218
0219
0220
0221
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
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
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
0258 pLayers.push_back(pLayer);
0259
0260 }
0261
0262
0263 auto pLayerArray = layerArrayCreator->layerArray(
0264 geoContext, pLayers, 25., 300., arbitrary, AxisDirection::AxisR);
0265 auto pVolumeBounds = std::make_shared<CylinderVolumeBounds>(25., 300., 1100.);
0266
0267 auto pVolume = std::make_shared<TrackingVolume>(
0268 Transform3::Identity(), pVolumeBounds, nullptr, std::move(pLayerArray),
0269 nullptr, MutableTrackingVolumeVector{}, "Pixel::Barrel");
0270
0271
0272 auto detectorVolume = cylinderVolumeHelper->createContainerTrackingVolume(
0273 geoContext, {beamPipeVolume, pVolume});
0274
0275
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
0289 std::vector<float> binEdges = {
0290 0., 5.,
0291 179.48552,
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
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
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 }
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 }