File indexing completed on 2025-08-06 08:11:16
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/ProtoBinning.hpp"
0017 #include "Acts/Detector/interface/IDetectorComponentBuilder.hpp"
0018 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0019 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/Geometry/GeometryIdentifier.hpp"
0022 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0023 #include "Acts/Navigation/SurfaceCandidatesUpdaters.hpp"
0024 #include "Acts/Surfaces/CylinderBounds.hpp"
0025 #include "Acts/Surfaces/CylinderSurface.hpp"
0026 #include "Acts/Surfaces/DiscSurface.hpp"
0027 #include "Acts/Surfaces/RadialBounds.hpp"
0028 #include "Acts/Surfaces/Surface.hpp"
0029 #include "Acts/Utilities/BinningType.hpp"
0030 #include "Acts/Utilities/Enumerate.hpp"
0031 #include "Acts/Utilities/Logger.hpp"
0032
0033 #include <any>
0034 #include <cmath>
0035 #include <iterator>
0036 #include <memory>
0037 #include <stdexcept>
0038 #include <string>
0039 #include <utility>
0040 #include <vector>
0041
0042 using namespace Acts;
0043 using namespace Acts::Experimental;
0044
0045 GeometryContext tContext;
0046
0047
0048
0049
0050 template <typename surface_type, typename surface_bounds_type>
0051 class CylindricalVolumeBuilder : public IDetectorComponentBuilder {
0052 public:
0053 CylindricalVolumeBuilder(const Transform3& transform,
0054 const CylinderVolumeBounds& vBounds,
0055 const surface_bounds_type& sBounds,
0056 const std::string& vName)
0057 : IDetectorComponentBuilder(),
0058 m_transform(transform),
0059 m_volumeBounds(vBounds),
0060 m_surfaceBounds(sBounds),
0061 m_name(vName) {}
0062
0063 DetectorComponent construct(
0064 [[maybe_unused]] const GeometryContext& gctx) const final {
0065
0066 std::vector<std::shared_ptr<DetectorVolume>> rootVolumes;
0067
0068
0069 auto surface = Surface::makeShared<surface_type>(
0070 (m_transform), std::make_shared<surface_bounds_type>(m_surfaceBounds));
0071
0072 auto bounds = std::make_unique<CylinderVolumeBounds>(m_volumeBounds);
0073 auto portalGenerator = defaultPortalGenerator();
0074 auto volume = DetectorVolumeFactory::construct(
0075 portalGenerator, tContext, m_name, m_transform, std::move(bounds),
0076 {surface}, {}, tryNoVolumes(), tryAllPortalsAndSurfaces());
0077
0078
0079 rootVolumes.push_back(volume);
0080
0081 DetectorComponent::PortalContainer dContainer;
0082 for (auto [ip, p] : enumerate(volume->portalPtrs())) {
0083 dContainer[ip] = p;
0084 }
0085 return DetectorComponent{
0086 {volume},
0087 dContainer,
0088 RootDetectorVolumes{rootVolumes, tryRootVolumes()}};
0089 }
0090
0091 private:
0092 Transform3 m_transform;
0093 CylinderVolumeBounds m_volumeBounds;
0094 surface_bounds_type m_surfaceBounds;
0095 std::string m_name;
0096 };
0097
0098 class VolumeGeoIdGenerator : public IGeometryIdGenerator {
0099 public:
0100 struct Cache {
0101 unsigned int volumeCount = 0;
0102 };
0103
0104 IGeometryIdGenerator::GeoIdCache generateCache() const final {
0105 return Cache{0};
0106 }
0107
0108 void assignGeometryId(IGeometryIdGenerator::GeoIdCache& cache,
0109 DetectorVolume& dVolume) const final {
0110 auto& ccache = std::any_cast<Cache&>(cache);
0111 ccache.volumeCount += 1;
0112 Acts::GeometryIdentifier geoID;
0113 geoID.setVolume(ccache.volumeCount);
0114 dVolume.assignGeometryId(geoID);
0115 }
0116
0117 void assignGeometryId(
0118 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0119 Acts::Experimental::Portal& ) const final {}
0120
0121 void assignGeometryId(
0122 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0123 Acts::Surface& ) const final {}
0124 };
0125
0126 BOOST_AUTO_TEST_SUITE(Detector)
0127
0128 BOOST_AUTO_TEST_CASE(CylindricaContainerBuilder_Misconfiguration) {
0129
0130 CylindricalContainerBuilder::Config misCfg;
0131 BOOST_CHECK_THROW(auto a = CylindricalContainerBuilder(misCfg),
0132 std::invalid_argument);
0133
0134 misCfg.builders = {nullptr};
0135 misCfg.binning = {Acts::binX};
0136 BOOST_CHECK_THROW(auto b = CylindricalContainerBuilder(misCfg),
0137 std::invalid_argument);
0138
0139
0140 misCfg.builders = {nullptr, nullptr};
0141 misCfg.binning = {Acts::binZ, Acts::binPhi};
0142 BOOST_CHECK_THROW(auto c = CylindricalContainerBuilder(misCfg),
0143 std::invalid_argument);
0144
0145
0146 misCfg.builders = {nullptr, nullptr, nullptr};
0147 misCfg.binning = {Acts::binZ, Acts::binR};
0148 BOOST_CHECK_THROW(auto d = CylindricalContainerBuilder(misCfg),
0149 std::invalid_argument);
0150 }
0151
0152 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingZ) {
0153
0154 Transform3 negZ = Transform3::Identity();
0155 negZ.pretranslate(Vector3(0., 0., -300.));
0156 auto negDisc =
0157 std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0158 negZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
0159 "NegativeDisc");
0160
0161
0162 auto barrel = std::make_shared<
0163 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0164 Transform3::Identity(), CylinderVolumeBounds(50., 200., 200.),
0165 CylinderBounds(80., 190.), "Barrel");
0166
0167 Transform3 posZ = Transform3::Identity();
0168 posZ.pretranslate(Vector3(0., 0., 300.));
0169 auto posDisc =
0170 std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0171 posZ, CylinderVolumeBounds(50., 200., 100.), RadialBounds(60., 190.),
0172 "PositiveDisc");
0173
0174
0175 CylindricalContainerBuilder::Config tripleZCfg;
0176 tripleZCfg.auxiliary = "*** Test 0 - Build triple in Z ***";
0177 tripleZCfg.builders = {negDisc, barrel, posDisc};
0178 tripleZCfg.binning = {binZ};
0179 tripleZCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
0180
0181 tripleZCfg.portalMaterialBinning[2u] = BinningDescription{
0182 {ProtoBinning(binZ, Acts::detail::AxisBoundaryType::Bound, 50),
0183 ProtoBinning(binPhi, Acts::detail::AxisBoundaryType::Closed, -M_PI, M_PI,
0184 12)}};
0185
0186
0187 tripleZCfg.geoIdReverseGen = true;
0188
0189 auto tripleZ = std::make_shared<CylindricalContainerBuilder>(
0190 tripleZCfg, getDefaultLogger("TripleBuilderZ", Logging::VERBOSE));
0191
0192 auto [volumes, portals, roots] = tripleZ->construct(tContext);
0193
0194 BOOST_CHECK_EQUAL(portals.size(), 4u);
0195 BOOST_CHECK_EQUAL(roots.volumes.size(), 3u);
0196 BOOST_CHECK_EQUAL(roots.volumes[0]->geometryId().volume(), 3u);
0197 BOOST_CHECK_EQUAL(roots.volumes[1]->geometryId().volume(), 2u);
0198 BOOST_CHECK_EQUAL(roots.volumes[2]->geometryId().volume(), 1u);
0199
0200
0201 BOOST_CHECK_NE(portals[2u]->surface().surfaceMaterial(), nullptr);
0202
0203 BOOST_CHECK_EQUAL(portals[0u]->surface().surfaceMaterial(), nullptr);
0204 BOOST_CHECK_EQUAL(portals[1u]->surface().surfaceMaterial(), nullptr);
0205 BOOST_CHECK_EQUAL(portals[3u]->surface().surfaceMaterial(), nullptr);
0206 }
0207
0208 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingR) {
0209
0210 auto barrel0 = std::make_shared<
0211 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0212 Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0213 CylinderBounds(65., 190.), "Barrel0");
0214
0215
0216 auto barrel1 = std::make_shared<
0217 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0218 Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0219 CylinderBounds(95., 190.), "Barrel1");
0220
0221
0222 auto barrel2 = std::make_shared<
0223 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0224 Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0225 CylinderBounds(125., 190.), "Barrel2");
0226
0227
0228 CylindricalContainerBuilder::Config barrelRCfg;
0229 barrelRCfg.auxiliary = "*** Test 1 - Build multilayer barrel ***";
0230 barrelRCfg.builders = {barrel0, barrel1, barrel2};
0231 barrelRCfg.binning = {binR};
0232 barrelRCfg.geoIdGenerator = std::make_shared<VolumeGeoIdGenerator>();
0233
0234 auto barrelR = std::make_shared<CylindricalContainerBuilder>(
0235 barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
0236
0237 auto [volumes, portals, roots] = barrelR->construct(tContext);
0238
0239 BOOST_CHECK_EQUAL(portals.size(), 4u);
0240 BOOST_CHECK_EQUAL(roots.volumes.size(), 3u);
0241 BOOST_CHECK_EQUAL(roots.volumes[0]->geometryId().volume(), 1u);
0242 BOOST_CHECK_EQUAL(roots.volumes[1]->geometryId().volume(), 2u);
0243 BOOST_CHECK_EQUAL(roots.volumes[2]->geometryId().volume(), 3u);
0244 }
0245
0246 BOOST_AUTO_TEST_CASE(CylindricaContainerBuildingPhi) {
0247
0248 CylindricalContainerBuilder::Config barrelPhiCfg;
0249 barrelPhiCfg.auxiliary = "*** Test 2 - Build segmented phi barrel ***";
0250 barrelPhiCfg.binning = {binPhi};
0251
0252 unsigned int phiSectors = 5;
0253 Acts::ActsScalar phiHalfSector = M_PI / phiSectors;
0254
0255 std::vector<std::shared_ptr<DetectorVolume>> phiVolumes = {};
0256 for (unsigned int i = 0; i < phiSectors; ++i) {
0257
0258 Acts::CylinderVolumeBounds volumeBounds(
0259 10., 100., 100., phiHalfSector, -M_PI + (2u * i + 1u) * phiHalfSector);
0260
0261 Acts::CylinderBounds surfaceBounds(50., 90., 0.99 * phiHalfSector,
0262 -M_PI + (2u * i + 1u) * phiHalfSector);
0263
0264 auto builder = std::make_shared<
0265 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0266 Transform3::Identity(), volumeBounds, surfaceBounds,
0267 std::string("Sector_") + std::to_string(i));
0268 barrelPhiCfg.builders.push_back(builder);
0269 }
0270
0271 auto barrelPhi = std::make_shared<CylindricalContainerBuilder>(
0272 barrelPhiCfg, getDefaultLogger("BarrelBuilderPhi", Logging::VERBOSE));
0273
0274 auto [volumes, portals, roots] = barrelPhi->construct(tContext);
0275
0276 BOOST_CHECK_EQUAL(portals.size(), 4u);
0277 BOOST_CHECK_EQUAL(roots.volumes.size(), 5u);
0278 }
0279
0280 BOOST_AUTO_TEST_CASE(CylindricalContainerBuilderDetector) {
0281
0282 auto beampipe = std::make_shared<
0283 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0284 Transform3::Identity(), CylinderVolumeBounds(0., 50., 600.),
0285 CylinderBounds(25., 590.), "BeamPipe");
0286
0287
0288 Transform3 negZ = Transform3::Identity();
0289 negZ.pretranslate(Vector3(0., 0., -300.));
0290 auto endcapN =
0291 std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0292 negZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
0293 "NegativeEndcap");
0294
0295
0296 auto barrel0 = std::make_shared<
0297 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0298 Transform3::Identity(), CylinderVolumeBounds(50., 80., 200.),
0299 CylinderBounds(65., 190.), "Barrel0");
0300
0301
0302 auto barrel1 = std::make_shared<
0303 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0304 Transform3::Identity(), CylinderVolumeBounds(80., 110., 200.),
0305 CylinderBounds(95., 190.), "Barrel1");
0306
0307
0308 auto barrel2 = std::make_shared<
0309 CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0310 Transform3::Identity(), CylinderVolumeBounds(110., 140., 200.),
0311 CylinderBounds(125., 190.), "Barrel2");
0312
0313
0314 CylindricalContainerBuilder::Config barrelRCfg;
0315 barrelRCfg.builders = {barrel0, barrel1, barrel2};
0316 barrelRCfg.binning = {binR};
0317
0318 auto barrel = std::make_shared<CylindricalContainerBuilder>(
0319 barrelRCfg, getDefaultLogger("BarrelBuilderR", Logging::VERBOSE));
0320
0321 Transform3 posZ = Transform3::Identity();
0322 posZ.pretranslate(Vector3(0., 0., 300.));
0323 auto endcapP =
0324 std::make_shared<CylindricalVolumeBuilder<DiscSurface, RadialBounds>>(
0325 posZ, CylinderVolumeBounds(50., 140., 100.), RadialBounds(60., 130.),
0326 "PositiveEndcap");
0327
0328
0329 CylindricalContainerBuilder::Config barrelEndcapCfg;
0330 barrelEndcapCfg.builders = {endcapN, barrel, endcapP};
0331 barrelEndcapCfg.binning = {binZ};
0332
0333 auto barrelEndcap = std::make_shared<CylindricalContainerBuilder>(
0334 barrelEndcapCfg,
0335 getDefaultLogger("BarrelEndcapBuilder", Logging::VERBOSE));
0336
0337
0338 CylindricalContainerBuilder::Config detectorCfg;
0339 detectorCfg.builders = {beampipe, barrelEndcap};
0340 detectorCfg.binning = {binR};
0341
0342 auto detector = std::make_shared<CylindricalContainerBuilder>(
0343 detectorCfg, getDefaultLogger("DetectorBuilder", Logging::VERBOSE));
0344
0345 auto [volumes, portals, roots] = detector->construct(tContext);
0346 BOOST_CHECK_EQUAL(portals.size(), 3u);
0347 BOOST_CHECK_EQUAL(roots.volumes.size(), 6u);
0348 }
0349
0350 BOOST_AUTO_TEST_SUITE_END()