File indexing completed on 2025-07-06 07:53:08
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/DetectorComponents.hpp"
0013 #include "Acts/Detector/DetectorVolume.hpp"
0014 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Detector/interface/IExternalStructureBuilder.hpp"
0017 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0018 #include "Acts/Detector/interface/IInternalStructureBuilder.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/InternalNavigation.hpp"
0024 #include "Acts/Surfaces/CylinderBounds.hpp"
0025 #include "Acts/Surfaces/CylinderSurface.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Utilities/Logger.hpp"
0028 #include "Acts/Utilities/ProtoAxis.hpp"
0029
0030 #include <memory>
0031 #include <numbers>
0032 #include <stdexcept>
0033 #include <string>
0034 #include <utility>
0035 #include <vector>
0036
0037 using namespace Acts;
0038 using namespace Acts::Experimental;
0039
0040 GeometryContext tContext;
0041
0042
0043
0044 template <typename bounds_type>
0045 class ExternalsBuilder : public IExternalStructureBuilder {
0046 public:
0047 ExternalsBuilder(const Transform3& transform, const bounds_type& bounds)
0048 : IExternalStructureBuilder(),
0049 m_transform(transform),
0050 m_bounds(std::move(bounds)) {}
0051
0052 ExternalStructure construct(
0053 [[maybe_unused]] const GeometryContext& gctx) const final {
0054 return {m_transform, std::make_unique<bounds_type>(m_bounds),
0055 defaultPortalGenerator()};
0056 }
0057
0058 private:
0059 Transform3 m_transform = Transform3::Identity();
0060 bounds_type m_bounds;
0061 };
0062
0063
0064
0065
0066 template <typename surface_type, typename bounds_type>
0067 class InternalSurfaceBuilder : public IInternalStructureBuilder {
0068 public:
0069 InternalSurfaceBuilder(const Transform3& transform, const bounds_type& bounds)
0070 : IInternalStructureBuilder(),
0071 m_transform(transform),
0072 m_bounds(std::move(bounds)) {}
0073
0074 InternalStructure construct(
0075 [[maybe_unused]] const GeometryContext& gctx) const final {
0076 auto surface = Surface::makeShared<surface_type>(
0077 m_transform, std::make_shared<bounds_type>(m_bounds));
0078 return {{surface}, {}, tryAllPortalsAndSurfaces(), tryNoVolumes()};
0079 }
0080
0081 private:
0082 Transform3 m_transform = Transform3::Identity();
0083 bounds_type m_bounds;
0084 };
0085
0086 class SurfaceGeoIdGenerator : public Acts::Experimental::IGeometryIdGenerator {
0087 public:
0088 Acts::Experimental::IGeometryIdGenerator::GeoIdCache generateCache()
0089 const final {
0090 return std::any();
0091 }
0092
0093 void assignGeometryId(
0094 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0095 Acts::Experimental::DetectorVolume& dVolume) const final {
0096 for (auto [is, s] : Acts::enumerate(dVolume.surfacePtrs())) {
0097 s->assignGeometryId(GeometryIdentifier().withPassive(is + 1));
0098 }
0099 }
0100
0101 void assignGeometryId(
0102 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0103 Acts::Experimental::Portal& ) const final {}
0104
0105 void assignGeometryId(
0106 Acts::Experimental::IGeometryIdGenerator::GeoIdCache& ,
0107 Acts::Surface& ) const final {}
0108 };
0109
0110
0111
0112
0113 template <typename bounds_type>
0114 class InternalVolumeBuilder : public IInternalStructureBuilder {
0115 public:
0116 InternalVolumeBuilder(const Transform3& transform, const bounds_type& bounds)
0117 : IInternalStructureBuilder(),
0118 m_transform(transform),
0119 m_bounds(std::move(bounds)) {}
0120
0121 InternalStructure construct(
0122 [[maybe_unused]] const GeometryContext& gctx) const final {
0123 auto bounds = std::make_unique<bounds_type>(m_bounds);
0124 auto portalGenerator = defaultPortalGenerator();
0125 auto volume = DetectorVolumeFactory::construct(
0126 portalGenerator, tContext, "InternalVolume", m_transform,
0127 std::move(bounds), tryAllPortals());
0128 return {{}, {volume}, tryAllPortals(), tryRootVolumes()};
0129 }
0130
0131 private:
0132 Transform3 m_transform = Transform3::Identity();
0133 bounds_type m_bounds;
0134 };
0135
0136 BOOST_AUTO_TEST_SUITE(Detector)
0137
0138 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_Misconfigured) {
0139
0140 DetectorVolumeBuilder::Config dvCfg;
0141 dvCfg.auxiliary = "*** Test X * Misconfigued ***";
0142 dvCfg.name = "EmptyCylinder";
0143 dvCfg.externalsBuilder = nullptr;
0144 dvCfg.internalsBuilder = nullptr;
0145
0146 BOOST_CHECK_THROW(auto a = DetectorVolumeBuilder(dvCfg),
0147 std::invalid_argument);
0148 }
0149
0150 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_EmptyVolume) {
0151 CylinderVolumeBounds cBounds(10, 100, 200);
0152 auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0153 Transform3::Identity(), cBounds);
0154
0155 DetectorVolumeBuilder::Config dvCfg;
0156 dvCfg.auxiliary = "*** Test 0 - Empty Cylinder ***";
0157 dvCfg.name = "EmptyCylinder";
0158 dvCfg.externalsBuilder = cBuilder;
0159 dvCfg.internalsBuilder = nullptr;
0160
0161
0162 dvCfg.portalMaterialBinning[2u] = {
0163 DirectedProtoAxis(AxisDirection::AxisZ, AxisBoundaryType::Bound, 50),
0164 DirectedProtoAxis(AxisDirection::AxisPhi, AxisBoundaryType::Closed,
0165 -std::numbers::pi, std::numbers::pi, 12)};
0166
0167 auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0168 dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0169
0170 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0171
0172 BOOST_CHECK_EQUAL(volumes.size(), 1u);
0173 BOOST_CHECK(volumes.front()->surfaces().empty());
0174 BOOST_CHECK(volumes.front()->volumes().empty());
0175
0176 BOOST_CHECK_EQUAL(portals.size(), 4u);
0177
0178 BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0179 BOOST_CHECK(roots.volumeFinder.connected());
0180
0181
0182 BOOST_CHECK_NE(portals[2u]->surface().surfaceMaterial(), nullptr);
0183
0184 BOOST_CHECK_EQUAL(portals[0u]->surface().surfaceMaterial(), nullptr);
0185 BOOST_CHECK_EQUAL(portals[1u]->surface().surfaceMaterial(), nullptr);
0186 BOOST_CHECK_EQUAL(portals[3u]->surface().surfaceMaterial(), nullptr);
0187 }
0188
0189 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithSurface) {
0190 CylinderVolumeBounds cvBounds(10, 100, 200);
0191 auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0192 Transform3::Identity(), cvBounds);
0193
0194 CylinderBounds csBounds(55., 195.);
0195 auto sBuilder =
0196 std::make_shared<InternalSurfaceBuilder<CylinderSurface, CylinderBounds>>(
0197 Transform3::Identity(), csBounds);
0198
0199 DetectorVolumeBuilder::Config dvCfg;
0200 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0201 dvCfg.name = "CylinderWithSurface";
0202 dvCfg.externalsBuilder = cBuilder;
0203 dvCfg.internalsBuilder = sBuilder;
0204 dvCfg.geoIdGenerator = std::make_shared<SurfaceGeoIdGenerator>();
0205
0206 auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0207 dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0208
0209 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0210
0211 BOOST_CHECK_EQUAL(volumes.size(), 1u);
0212 BOOST_CHECK_EQUAL(volumes.front()->surfaces().size(), 1u);
0213
0214 BOOST_CHECK_EQUAL(volumes.front()->surfaces().front()->geometryId().passive(),
0215 1u);
0216 BOOST_CHECK(volumes.front()->volumes().empty());
0217
0218 BOOST_CHECK_EQUAL(portals.size(), 4u);
0219
0220 BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0221 BOOST_CHECK(roots.volumeFinder.connected());
0222 }
0223
0224 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithVolume) {
0225 CylinderVolumeBounds cvBounds(10, 100, 200);
0226 auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0227 Transform3::Identity(), cvBounds);
0228
0229 CylinderVolumeBounds ciBounds(15., 95., 195.);
0230 auto iBuilder = std::make_shared<InternalVolumeBuilder<CylinderVolumeBounds>>(
0231 Transform3::Identity(), ciBounds);
0232
0233 DetectorVolumeBuilder::Config dvCfg;
0234 dvCfg.auxiliary = "*** Test 2 - Cylinder with internal Volume ***";
0235 dvCfg.name = "CylinderWithVolume";
0236 dvCfg.externalsBuilder = cBuilder;
0237 dvCfg.internalsBuilder = iBuilder;
0238 dvCfg.addInternalsToRoot = false;
0239
0240 auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0241 dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0242
0243 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0244
0245 BOOST_CHECK_EQUAL(volumes.size(), 1u);
0246 BOOST_CHECK_EQUAL(portals.size(), 4u);
0247 BOOST_CHECK_EQUAL(roots.volumes.size(), 1u);
0248 }
0249
0250 BOOST_AUTO_TEST_CASE(DetectorVolumeBuilder_VolumeWithVolumeToRoot) {
0251 CylinderVolumeBounds cvBounds(10, 100, 200);
0252 auto cBuilder = std::make_shared<ExternalsBuilder<CylinderVolumeBounds>>(
0253 Transform3::Identity(), cvBounds);
0254
0255 CylinderVolumeBounds ciBounds(15., 95., 195.);
0256 auto iBuilder = std::make_shared<InternalVolumeBuilder<CylinderVolumeBounds>>(
0257 Transform3::Identity(), ciBounds);
0258
0259 DetectorVolumeBuilder::Config dvCfg;
0260 dvCfg.auxiliary =
0261 "*** Test 3 - Cylinder with internal Volume, adding to root ***";
0262 dvCfg.name = "CylinderWithVolume";
0263 dvCfg.externalsBuilder = cBuilder;
0264 dvCfg.internalsBuilder = iBuilder;
0265 dvCfg.addInternalsToRoot = true;
0266
0267 auto dvBuilder = std::make_shared<DetectorVolumeBuilder>(
0268 dvCfg, getDefaultLogger("DetectorVolumeBuilder", Logging::VERBOSE));
0269
0270 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0271
0272 BOOST_CHECK_EQUAL(volumes.size(), 1u);
0273 BOOST_CHECK(volumes.front()->surfaces().empty());
0274 BOOST_CHECK_EQUAL(volumes.front()->volumes().size(), 1u);
0275
0276 BOOST_CHECK_EQUAL(portals.size(), 4u);
0277
0278 BOOST_CHECK_EQUAL(roots.volumes.size(), 2u);
0279 BOOST_CHECK(roots.volumeFinder.connected());
0280 }
0281
0282 BOOST_AUTO_TEST_SUITE_END()