File indexing completed on 2025-07-05 08:12:33
0001
0002
0003
0004
0005
0006
0007
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& ,
0070 Acts::Experimental::Portal& ) const final {}
0071
0072 void assignGeometryId(
0073 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0074 Acts::Surface& ) const final {}
0075 };
0076
0077 BOOST_AUTO_TEST_SUITE(Detector)
0078
0079 BOOST_AUTO_TEST_CASE(CylindricaContainerBuilder_Misconfiguration) {
0080
0081 CylindricalContainerBuilder::Config misCfg;
0082 BOOST_CHECK_THROW(auto a = CylindricalContainerBuilder(misCfg),
0083 std::invalid_argument);
0084
0085 misCfg.builders = {nullptr};
0086 misCfg.binning = {Acts::AxisDirection::AxisX};
0087 BOOST_CHECK_THROW(auto b = CylindricalContainerBuilder(misCfg),
0088 std::invalid_argument);
0089
0090
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
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
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
0113 auto barrel = std::make_shared<
0114 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0115 Transform3::Identity(), CylinderVolumeBounds(50., 200., 200.),
0116 CylinderBounds(80., 190.), "Barrel");
0117
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
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
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
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
0152 BOOST_CHECK_NE(portals[2u]->surface().surfaceMaterial(), nullptr);
0153
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
0161 auto barrel0 = std::make_shared<
0162 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0163 Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0164 CylinderBounds(65., 190.), "Barrel0");
0165
0166
0167 auto barrel1 = std::make_shared<
0168 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0169 Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0170 CylinderBounds(95., 190.), "Barrel1");
0171
0172
0173 auto barrel2 = std::make_shared<
0174 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0175 Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0176 CylinderBounds(125., 190.), "Barrel2");
0177
0178
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
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
0209 Acts::CylinderVolumeBounds volumeBounds(
0210 10., 100., 100., phiHalfSector,
0211 -std::numbers::pi + (2u * i + 1u) * phiHalfSector);
0212
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
0235 auto beampipe = std::make_shared<
0236 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0237 Transform3::Identity(), CylinderVolumeBounds(0., 50., 600.),
0238 CylinderBounds(25., 590.), "BeamPipe");
0239
0240
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
0249 auto barrel0 = std::make_shared<
0250 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0251 Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0252 CylinderBounds(65., 190.), "Barrel0");
0253
0254
0255 auto barrel1 = std::make_shared<
0256 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0257 Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0258 CylinderBounds(95., 190.), "Barrel1");
0259
0260
0261 auto barrel2 = std::make_shared<
0262 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0263 Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0264 CylinderBounds(125., 190.), "Barrel2");
0265
0266
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
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
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()