Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:12:33

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 <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Detector/CylindricalContainerBuilder.hpp"
0013 #include "Acts/Detector/DetectorComponents.hpp"
0014 #include "Acts/Detector/DetectorVolume.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Detector/interface/IDetectorComponentBuilder.hpp"
0017 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0018 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Geometry/GeometryIdentifier.hpp"
0021 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0022 #include "Acts/Navigation/InternalNavigation.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/Surface.hpp"
0028 #include "Acts/Tests/CommonHelpers/CylindricalDetector.hpp"
0029 #include "Acts/Utilities/BinningType.hpp"
0030 #include "Acts/Utilities/Enumerate.hpp"
0031 #include "Acts/Utilities/Logger.hpp"
0032 #include "Acts/Utilities/ProtoAxis.hpp"
0033 
0034 #include <any>
0035 #include <cmath>
0036 #include <iterator>
0037 #include <memory>
0038 #include <numbers>
0039 #include <stdexcept>
0040 #include <string>
0041 #include <utility>
0042 #include <vector>
0043 
0044 using namespace Acts;
0045 using namespace Acts::Test;
0046 using namespace Acts::Experimental;
0047 
0048 GeometryContext tContext;
0049 
0050 class VolumeGeoIdGenerator : public IGeometryIdGenerator {
0051  public:
0052   struct Cache {
0053     unsigned int volumeCount = 0;
0054   };
0055 
0056   IGeometryIdGenerator::GeoIdCache generateCache() const final {
0057     return Cache{0};
0058   }
0059 
0060   void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
0061                         DetectorVolume& dVolume) const final {
0062     auto& ccache = std::any_cast<Cache&>(cache);
0063     ccache.volumeCount += 1;
0064     dVolume.assignGeometryId(
0065         Acts::GeometryIdentifier().withVolume(ccache.volumeCount));
0066   }
0067 
0068   void assignGeometryId(
0069       Acts::Experimental::IGeometryIdGenerator::GeoIdCache& /*cache*/,
0070       Acts::Experimental::Portal& /*portal*/) const final {}
0071 
0072   void assignGeometryId(
0073       Acts::Experimental::IGeometryIdGenerator::GeoIdCache& /*cache*/,
0074       Acts::Surface& /*surface*/) const final {}
0075 };
0076 
0077 BOOST_AUTO_TEST_SUITE(Detector)
0078 
0079 BOOST_AUTO_TEST_CASE(CylindricaContainerBuilder_Misconfiguration) {
0080   // misconfiruation: no builders
0081   CylindricalContainerBuilder::Config misCfg;
0082   BOOST_CHECK_THROW(auto a = CylindricalContainerBuilder(misCfg),
0083                     std::invalid_argument);
0084   // misconfiguration - 1D binning not in z, r, phi
0085   misCfg.builders = {nullptr};
0086   misCfg.binning = {Acts::AxisDirection::AxisX};
0087   BOOST_CHECK_THROW(auto b = CylindricalContainerBuilder(misCfg),
0088                     std::invalid_argument);
0089 
0090   // misconfiguration - 2D binning not in z, r,
0091   misCfg.builders = {nullptr, nullptr};
0092   misCfg.binning = {Acts::AxisDirection::AxisZ, Acts::AxisDirection::AxisPhi};
0093   BOOST_CHECK_THROW(auto c = CylindricalContainerBuilder(misCfg),
0094                     std::invalid_argument);
0095 
0096   // misconfiguration - 2D binning  in z, r, but not exactly 2 builders
0097   misCfg.builders = {nullptr, nullptr, nullptr};
0098   misCfg.binning = {Acts::AxisDirection::AxisZ, Acts::AxisDirection::AxisR};
0099   BOOST_CHECK_THROW(auto d = CylindricalContainerBuilder(misCfg),
0100                     std::invalid_argument);
0101 }
0102 
0103 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingZ) {
0104   // Declare a negative disc builder
0105   Transform3 negZ = Transform3::Identity();
0106   negZ.pretranslate(Vector3(0., 0., -300.));
0107   auto negDisc =
0108       std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0109           negZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
0110           "NegativeDisc");
0111 
0112   // Declare a barrel builder
0113   auto barrel = std::make_shared<
0114       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0115       Transform3::Identity(), CylinderVolumeBounds(50., 200., 200.),
0116       CylinderBounds(80., 190.), "Barrel");
0117   // Declare a positive disc builder
0118   Transform3 posZ = Transform3::Identity();
0119   posZ.pretranslate(Vector3(0., 0., 300.));
0120   auto posDisc =
0121       std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0122           posZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
0123           "PositiveDisc");
0124 
0125   // Create the container builder
0126   CylindricalContainerBuilder::Config tripleZCfg;
0127   tripleZCfg.auxiliary = "*** Test 0 - Build triple in Z ***";
0128   tripleZCfg.builders = {negDisc, barrel, posDisc};
0129   tripleZCfg.binning = {AxisDirection::AxisZ};
0130   tripleZCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
0131   // Create a materialBinning
0132   tripleZCfg.portalMaterialBinning[2u] = {
0133       DirectedProtoAxis(AxisDirection::AxisZ, AxisBoundaryType::Bound, 50),
0134       DirectedProtoAxis(AxisDirection::AxisPhi, Acts::AxisBoundaryType::Closed,
0135                         -std::numbers::pi, std::numbers::pi, 12)};
0136 
0137   // Let's test the reverse generation
0138   tripleZCfg.geoIdReverseGen = true;
0139 
0140   auto tripleZ = std::make_shared<CylindricalContainerBuilder>(
0141       tripleZCfg, getDefaultLogger("TripleBuilderZ", Logging::VERBOSE));
0142 
0143   auto [volumes, portals, roots] = tripleZ->construct(tContext);
0144 
0145   BOOST_CHECK_EQUAL(portals.size(), 4u);
0146   BOOST_CHECK_EQUAL(roots.volumes.size(), 3u);
0147   BOOST_CHECK_EQUAL(roots.volumes[0]->geometryId().volume(), 3u);
0148   BOOST_CHECK_EQUAL(roots.volumes[1]->geometryId().volume(), 2u);
0149   BOOST_CHECK_EQUAL(roots.volumes[2]->geometryId().volume(), 1u);
0150 
0151   // The outside surface should have a proto material description now
0152   BOOST_CHECK_NE(portals[2u]->surface().surfaceMaterial(), nullptr);
0153   // others should not have a proto material description
0154   BOOST_CHECK_EQUAL(portals[0u]->surface().surfaceMaterial(), nullptr);
0155   BOOST_CHECK_EQUAL(portals[1u]->surface().surfaceMaterial(), nullptr);
0156   BOOST_CHECK_EQUAL(portals[3u]->surface().surfaceMaterial(), nullptr);
0157 }
0158 
0159 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingR) {
0160   // Declare a barrel builder
0161   auto barrel0 = std::make_shared<
0162       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0163       Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0164       CylinderBounds(65., 190.), "Barrel0");
0165 
0166   // Declare a barrel builder
0167   auto barrel1 = std::make_shared<
0168       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0169       Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0170       CylinderBounds(95., 190.), "Barrel1");
0171 
0172   // Declare a barrel builder
0173   auto barrel2 = std::make_shared<
0174       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0175       Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0176       CylinderBounds(125., 190.), "Barrel2");
0177 
0178   // Create the container builder
0179   CylindricalContainerBuilder::Config barrelRCfg;
0180   barrelRCfg.auxiliary = "*** Test 1 - Build multilayer barrel ***";
0181   barrelRCfg.builders = {barrel0, barrel1, barrel2};
0182   barrelRCfg.binning = {AxisDirection::AxisR};
0183   barrelRCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
0184 
0185   auto barrelR = std::make_shared<CylindricalContainerBuilder>(
0186       barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
0187 
0188   auto [volumes, portals, roots] = barrelR->construct(tContext);
0189 
0190   BOOST_CHECK_EQUAL(portals.size(), 4u);
0191   BOOST_CHECK_EQUAL(roots.volumes.size(), 3u);
0192   BOOST_CHECK_EQUAL(roots.volumes[0]->geometryId().volume(), 1u);
0193   BOOST_CHECK_EQUAL(roots.volumes[1]->geometryId().volume(), 2u);
0194   BOOST_CHECK_EQUAL(roots.volumes[2]->geometryId().volume(), 3u);
0195 }
0196 
0197 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingPhi) {
0198   // Create the container builder
0199   CylindricalContainerBuilder::Config barrelPhiCfg;
0200   barrelPhiCfg.auxiliary = "*** Test 2 - Build segmented phi barrel ***";
0201   barrelPhiCfg.binning = {AxisDirection::AxisPhi};
0202 
0203   unsigned int phiSectors = 5;
0204   double phiHalfSector = std::numbers::pi / phiSectors;
0205 
0206   std::vector<std::shared_ptr<DetectorVolume>> phiVolumes = {};
0207   for (unsigned int i = 0; i < phiSectors; ++i) {
0208     // The volume bounds
0209     Acts::CylinderVolumeBounds volumeBounds(
0210         10., 100., 100., phiHalfSector,
0211         -std::numbers::pi + (2u * i + 1u) * phiHalfSector);
0212     // The surface bounds
0213     Acts::CylinderBounds surfaceBounds(
0214         50., 90., 0.99 * phiHalfSector,
0215         -std::numbers::pi + (2u * i + 1u) * phiHalfSector);
0216 
0217     auto builder = std::make_shared<
0218         CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0219         Transform3::Identity(), volumeBounds, surfaceBounds,
0220         std::string("Sector_") + std::to_string(i));
0221     barrelPhiCfg.builders.push_back(builder);
0222   }
0223 
0224   auto barrelPhi = std::make_shared<CylindricalContainerBuilder>(
0225       barrelPhiCfg, getDefaultLogger("BarrelBuilderPhi", Logging::VERBOSE));
0226 
0227   auto [volumes, portals, roots] = barrelPhi->construct(tContext);
0228 
0229   BOOST_CHECK_EQUAL(portals.size(), 4u);
0230   BOOST_CHECK_EQUAL(roots.volumes.size(), 5u);
0231 }
0232 
0233 BOOST_AUTO_TEST_CASE(CylindricalContainerBuilderDetector) {
0234   // Declare a barrel sub builder
0235   auto beampipe = std::make_shared<
0236       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0237       Transform3::Identity(), CylinderVolumeBounds(0., 50., 600.),
0238       CylinderBounds(25., 590.), "BeamPipe");
0239 
0240   // Declare a negative disc builder
0241   Transform3 negZ = Transform3::Identity();
0242   negZ.pretranslate(Vector3(0., 0., -300.));
0243   auto endcapN =
0244       std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0245           negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
0246           "NegativeEndcap");
0247 
0248   // Declare a barrel sub builder
0249   auto barrel0 = std::make_shared<
0250       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0251       Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0252       CylinderBounds(65., 190.), "Barrel0");
0253 
0254   // Declare a barrel sub builder
0255   auto barrel1 = std::make_shared<
0256       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0257       Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0258       CylinderBounds(95., 190.), "Barrel1");
0259 
0260   // Declare a barrel sub builder
0261   auto barrel2 = std::make_shared<
0262       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0263       Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0264       CylinderBounds(125., 190.), "Barrel2");
0265 
0266   // Create the barrel container builder
0267   CylindricalContainerBuilder::Config barrelRCfg;
0268   barrelRCfg.builders = {barrel0, barrel1, barrel2};
0269   barrelRCfg.binning = {AxisDirection::AxisR};
0270 
0271   auto barrel = std::make_shared<CylindricalContainerBuilder>(
0272       barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
0273 
0274   Transform3 posZ = Transform3::Identity();
0275   posZ.pretranslate(Vector3(0., 0., 300.));
0276   auto endcapP =
0277       std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0278           posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
0279           "PositiveEndcap");
0280 
0281   // Create the barrel container builder
0282   CylindricalContainerBuilder::Config barrelEndcapCfg;
0283   barrelEndcapCfg.builders = {endcapN, barrel, endcapP};
0284   barrelEndcapCfg.binning = {AxisDirection::AxisZ};
0285 
0286   auto barrelEndcap = std::make_shared<CylindricalContainerBuilder>(
0287       barrelEndcapCfg,
0288       getDefaultLogger("BarrelEndcapBuilder", Logging::VERBOSE));
0289 
0290   // Create the barrel container builder
0291   CylindricalContainerBuilder::Config detectorCfg;
0292   detectorCfg.builders = {beampipe, barrelEndcap};
0293   detectorCfg.binning = {AxisDirection::AxisR};
0294 
0295   auto detector = std::make_shared<CylindricalContainerBuilder>(
0296       detectorCfg, getDefaultLogger("DetectorBuilder", Logging::VERBOSE));
0297 
0298   auto [volumes, portals, roots] = detector->construct(tContext);
0299   BOOST_CHECK_EQUAL(portals.size(), 3u);
0300   BOOST_CHECK_EQUAL(roots.volumes.size(), 6u);
0301 }
0302 
0303 BOOST_AUTO_TEST_SUITE_END()