File indexing completed on 2025-10-21 08:04:04
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/Definitions/Direction.hpp"
0013 #include "Acts/Detector/DetectorVolume.hpp"
0014 #include "Acts/Detector/Portal.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0020 #include "Acts/Material/MaterialSlab.hpp"
0021 #include "Acts/Navigation/InternalNavigation.hpp"
0022 #include "Acts/Navigation/NavigationDelegates.hpp"
0023 #include "Acts/Navigation/NavigationState.hpp"
0024 #include "Acts/Surfaces/PlaneSurface.hpp"
0025 #include "Acts/Surfaces/RectangleBounds.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027
0028 #include <array>
0029 #include <memory>
0030 #include <stdexcept>
0031 #include <utility>
0032 #include <vector>
0033
0034 namespace Acts::Experimental {
0035
0036
0037 class LinkToVolumeImpl : public IExternalNavigation {
0038 public:
0039 std::shared_ptr<DetectorVolume> dVolume = nullptr;
0040
0041
0042 explicit LinkToVolumeImpl(std::shared_ptr<DetectorVolume> dv)
0043 : dVolume(std::move(dv)) {}
0044
0045
0046
0047 void link(const GeometryContext& , NavigationState& nState) const {
0048 nState.currentVolume = dVolume.get();
0049 }
0050 };
0051
0052 }
0053
0054 using namespace Acts;
0055 using namespace Acts::Experimental;
0056
0057
0058 GeometryContext tContext;
0059
0060 namespace ActsTests {
0061
0062 BOOST_AUTO_TEST_SUITE(DetectorSuite)
0063
0064 BOOST_AUTO_TEST_CASE(PortalTest) {
0065 auto dTransform = Transform3::Identity();
0066 auto pGenerator = defaultPortalGenerator();
0067 auto volumeA = DetectorVolumeFactory::construct(
0068 pGenerator, tContext, "dummyA", dTransform,
0069 std::make_unique<CuboidVolumeBounds>(1, 1, 1),
0070 tryAllPortalsAndSurfaces());
0071 auto volumeB = DetectorVolumeFactory::construct(
0072 pGenerator, tContext, "dummyB", dTransform,
0073 std::make_unique<CuboidVolumeBounds>(1, 1, 1),
0074 tryAllPortalsAndSurfaces());
0075
0076
0077 auto rectangle = std::make_shared<RectangleBounds>(10., 100.);
0078 auto surface = Surface::makeShared<PlaneSurface>(dTransform, rectangle);
0079
0080
0081 auto portalA = std::make_shared<Experimental::Portal>(surface);
0082
0083 BOOST_CHECK_EQUAL(&(portalA->surface()), surface.get());
0084
0085 portalA->assignGeometryId(GeometryIdentifier{5});
0086 BOOST_CHECK_EQUAL(portalA->surface().geometryId(), GeometryIdentifier{5});
0087
0088
0089 auto linkToAImpl = std::make_unique<const LinkToVolumeImpl>(volumeA);
0090 ExternalNavigationDelegate linkToA;
0091 linkToA.connect<&LinkToVolumeImpl::link>(std::move(linkToAImpl));
0092 portalA->assignPortalNavigation(Direction::Positive(), std::move(linkToA),
0093 {volumeA});
0094
0095 auto attachedDetectorVolumes = portalA->attachedDetectorVolumes();
0096 BOOST_CHECK(attachedDetectorVolumes[0u].empty());
0097 BOOST_CHECK_EQUAL(attachedDetectorVolumes[1u].size(), 1u);
0098 BOOST_CHECK_EQUAL(attachedDetectorVolumes[1u][0u], volumeA);
0099
0100 NavigationState nState;
0101 nState.position = Vector3(0., 0., 0.);
0102 nState.direction = Vector3(0., 0., 1.);
0103
0104 portalA->updateDetectorVolume(tContext, nState);
0105 BOOST_CHECK_EQUAL(nState.currentVolume, volumeA.get());
0106
0107 nState.direction = Vector3(0., 0., -1.);
0108 portalA->updateDetectorVolume(tContext, nState);
0109 BOOST_CHECK_EQUAL(nState.currentVolume, nullptr);
0110
0111 auto portalB = std::make_shared<Experimental::Portal>(surface);
0112 ExternalNavigationDelegate linkToB;
0113 auto linkToBImpl = std::make_unique<const LinkToVolumeImpl>(volumeB);
0114 linkToB.connect<&LinkToVolumeImpl::link>(std::move(linkToBImpl));
0115 portalB->assignPortalNavigation(Direction::Negative(), std::move(linkToB),
0116 {volumeB});
0117
0118
0119 nState.direction = Vector3(0., 0., 1.);
0120 portalB->updateDetectorVolume(tContext, nState);
0121 BOOST_CHECK_EQUAL(nState.currentVolume, nullptr);
0122 nState.direction = Vector3(0., 0., -1.);
0123 portalB->updateDetectorVolume(tContext, nState);
0124 BOOST_CHECK_EQUAL(nState.currentVolume, volumeB.get());
0125
0126 GeometryContext gctx;
0127 BOOST_CHECK_EQUAL(portalA->surface().center(gctx),
0128 portalB->surface().center(gctx));
0129
0130
0131 BOOST_CHECK_EQUAL(portalA, Experimental::Portal::fuse(portalA, portalA));
0132
0133
0134 portalA = Experimental::Portal::fuse(portalA, portalB);
0135
0136 nState.direction = Vector3(0., 0., 1.);
0137 portalA->updateDetectorVolume(tContext, nState);
0138 BOOST_CHECK_EQUAL(nState.currentVolume, volumeA.get());
0139 nState.direction = Vector3(0., 0., -1.);
0140 portalA->updateDetectorVolume(tContext, nState);
0141 BOOST_CHECK_EQUAL(nState.currentVolume, volumeB.get());
0142
0143
0144 BOOST_CHECK_EQUAL(portalA->surface().center(gctx),
0145 portalB->surface().center(gctx));
0146
0147
0148 bool reached = false;
0149 const Experimental::Portal* cportalB = portalB.get();
0150 cportalB->visitSurface([&reached](const auto* s) {
0151 if (s != nullptr) {
0152 reached = true;
0153 }
0154 });
0155 BOOST_CHECK(reached);
0156
0157
0158 struct SetMaterial {
0159
0160 std::shared_ptr<const HomogeneousSurfaceMaterial> material =
0161 std::make_shared<HomogeneousSurfaceMaterial>(
0162 MaterialSlab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 1.));
0163
0164 void operator()(Surface* s) {
0165 if (s != nullptr) {
0166 s->assignSurfaceMaterial(material);
0167 }
0168 }
0169 };
0170
0171 SetMaterial setMaterial;
0172 BOOST_CHECK(portalA->surface().surfaceMaterial() == nullptr);
0173 portalA->visitMutableSurface(setMaterial);
0174 BOOST_CHECK(portalA->surface().surfaceMaterial() ==
0175 setMaterial.material.get());
0176 }
0177
0178 BOOST_AUTO_TEST_CASE(PortalMaterialTest) {
0179
0180 auto dTransform = Transform3::Identity();
0181 auto pGenerator = defaultPortalGenerator();
0182 auto volumeA = DetectorVolumeFactory::construct(
0183 pGenerator, tContext, "dummyA", dTransform,
0184 std::make_unique<CuboidVolumeBounds>(1, 1, 1),
0185 tryAllPortalsAndSurfaces());
0186 auto volumeB = DetectorVolumeFactory::construct(
0187 pGenerator, tContext, "dummyB", dTransform,
0188 std::make_unique<CuboidVolumeBounds>(1, 1, 1),
0189 tryAllPortalsAndSurfaces());
0190
0191
0192 auto materialSlab =
0193 MaterialSlab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 1.);
0194 auto materialA = std::make_shared<HomogeneousSurfaceMaterial>(materialSlab);
0195 auto materialB = std::make_shared<HomogeneousSurfaceMaterial>(materialSlab);
0196
0197
0198 auto rectangle = std::make_shared<RectangleBounds>(10., 100.);
0199
0200 auto surfaceA =
0201 Surface::makeShared<PlaneSurface>(Transform3::Identity(), rectangle);
0202 surfaceA->assignSurfaceMaterial(materialA);
0203 auto portalA = std::make_shared<Experimental::Portal>(surfaceA);
0204
0205 ExternalNavigationDelegate linkToA;
0206 auto linkToAImpl = std::make_unique<const LinkToVolumeImpl>(volumeA);
0207 linkToA.connect<&LinkToVolumeImpl::link>(std::move(linkToAImpl));
0208 portalA->assignPortalNavigation(Direction::Positive(), std::move(linkToA),
0209 {volumeA});
0210
0211 auto surfaceB =
0212 Surface::makeShared<PlaneSurface>(Transform3::Identity(), rectangle);
0213 auto portalB = std::make_shared<Experimental::Portal>(surfaceB);
0214 ExternalNavigationDelegate linkToB;
0215 auto linkToBImpl = std::make_unique<const LinkToVolumeImpl>(volumeB);
0216 linkToB.connect<&LinkToVolumeImpl::link>(std::move(linkToBImpl));
0217 portalB->assignPortalNavigation(Direction::Negative(), std::move(linkToB),
0218 {volumeB});
0219
0220
0221
0222 portalA = Experimental::Portal::fuse(portalA, portalB);
0223 BOOST_CHECK_EQUAL(portalA->surface().surfaceMaterial(), materialA.get());
0224
0225
0226 portalB = std::make_shared<Experimental::Portal>(surfaceB);
0227 ExternalNavigationDelegate linkToB2;
0228 auto linkToB2Impl = std::make_unique<const LinkToVolumeImpl>(volumeB);
0229 linkToB2.connect<&LinkToVolumeImpl::link>(std::move(linkToB2Impl));
0230 portalB->assignPortalNavigation(Direction::Negative(), std::move(linkToB2),
0231 {volumeB});
0232
0233
0234
0235 BOOST_REQUIRE_NE(portalA, portalB);
0236
0237
0238 BOOST_CHECK_THROW(Experimental::Portal::fuse(portalB, portalA),
0239 std::invalid_argument);
0240
0241 portalA->assignPortalNavigation(Direction::Negative(),
0242 ExternalNavigationDelegate{}, {});
0243
0244 portalB = Experimental::Portal::fuse(portalB, portalA);
0245 BOOST_CHECK_EQUAL(portalB->surface().surfaceMaterial(), materialA.get());
0246
0247
0248 portalA = std::make_shared<Experimental::Portal>(surfaceA);
0249 ExternalNavigationDelegate linkToA2;
0250 auto linkToA2Impl = std::make_unique<const LinkToVolumeImpl>(volumeA);
0251 linkToA2.connect<&LinkToVolumeImpl::link>(std::move(linkToA2Impl));
0252 portalA->assignPortalNavigation(Direction::Positive(), std::move(linkToA2),
0253 {volumeA});
0254
0255 surfaceB->assignSurfaceMaterial(materialB);
0256 portalB = std::make_shared<Experimental::Portal>(surfaceB);
0257 ExternalNavigationDelegate linkToB3;
0258 auto linkToB3Impl = std::make_unique<const LinkToVolumeImpl>(volumeB);
0259 linkToB3.connect<&LinkToVolumeImpl::link>(std::move(linkToB3Impl));
0260 portalB->assignPortalNavigation(Direction::Negative(), std::move(linkToB3),
0261 {volumeB});
0262
0263
0264 BOOST_CHECK_THROW(Experimental::Portal::fuse(portalA, portalB),
0265 std::runtime_error);
0266
0267 BOOST_CHECK_THROW(Experimental::Portal::fuse(portalB, portalA),
0268 std::runtime_error);
0269 }
0270
0271 BOOST_AUTO_TEST_SUITE_END()
0272
0273 }