Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PortalTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PortalTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/unit_test.hpp>
10 
14 #include "Acts/Detector/Portal.hpp"
25 
26 #include <array>
27 #include <memory>
28 #include <stdexcept>
29 #include <utility>
30 #include <vector>
31 
32 namespace Acts {
33 namespace Experimental {
34 
37  public:
38  std::shared_ptr<DetectorVolume> dVolume = nullptr;
39 
41  LinkToVolumeImpl(std::shared_ptr<DetectorVolume> dv)
42  : dVolume(std::move(dv)) {}
43 
46  void link(const GeometryContext& /*gctx*/, NavigationState& nState) const {
47  nState.currentVolume = dVolume.get();
48  }
49 };
50 
51 } // namespace Experimental
52 } // namespace Acts
53 
61 template <typename referenced_type>
62 std::shared_ptr<referenced_type> unpackToShared(referenced_type& rt) {
63  return rt.getSharedPtr();
64 }
65 
66 using namespace Acts::Experimental;
67 
68 // A test context
70 
71 BOOST_AUTO_TEST_SUITE(Detector)
72 
73 BOOST_AUTO_TEST_CASE(PortalTest) {
74  auto dTransform = Acts::Transform3::Identity();
75  auto pGenerator = defaultPortalGenerator();
77  pGenerator, tContext, "dummyA", dTransform,
78  std::make_unique<Acts::CuboidVolumeBounds>(1, 1, 1),
81  pGenerator, tContext, "dummyB", dTransform,
82  std::make_unique<Acts::CuboidVolumeBounds>(1, 1, 1),
84 
85  // A rectangle bound surface
86  auto rectangle = std::make_shared<Acts::RectangleBounds>(10., 100.);
87  auto surface =
88  Acts::Surface::makeShared<Acts::PlaneSurface>(dTransform, rectangle);
89 
90  // Create a portal out of it
92 
93  BOOST_CHECK(&(portalA->surface()) == surface.get());
94 
95  portalA->assignGeometryId(Acts::GeometryIdentifier{5});
96  BOOST_CHECK(portalA->surface().geometryId() == Acts::GeometryIdentifier{5});
97 
98  BOOST_CHECK(portalA == unpackToShared<Portal>(*portalA));
99  BOOST_CHECK(portalA == unpackToShared<const Portal>(*portalA));
100 
101  // Create a links to volumes
102  auto linkToAImpl = std::make_unique<const LinkToVolumeImpl>(volumeA);
103  DetectorVolumeUpdator linkToA;
104  linkToA.connect<&LinkToVolumeImpl::link>(std::move(linkToAImpl));
105  portalA->assignDetectorVolumeUpdator(Acts::Direction::Positive,
106  std::move(linkToA), {volumeA});
107 
108  auto attachedDetectorVolumes = portalA->attachedDetectorVolumes();
109  BOOST_CHECK(attachedDetectorVolumes[0u].empty());
110  BOOST_CHECK(attachedDetectorVolumes[1u].size() == 1u);
111  BOOST_CHECK(attachedDetectorVolumes[1u][0u] == volumeA);
112 
114  nState.position = Acts::Vector3(0., 0., 0.);
115  nState.direction = Acts::Vector3(0., 0., 1.);
116  // The next volume in positive should be volume A
117  portalA->updateDetectorVolume(tContext, nState);
118  BOOST_CHECK(nState.currentVolume == volumeA.get());
119  // negative should yield nullptr
120  nState.direction = Acts::Vector3(0., 0., -1.);
121  portalA->updateDetectorVolume(tContext, nState);
122  BOOST_CHECK(nState.currentVolume == nullptr);
123 
125  DetectorVolumeUpdator linkToB;
126  auto linkToBImpl = std::make_unique<const LinkToVolumeImpl>(volumeB);
127  linkToB.connect<&LinkToVolumeImpl::link>(std::move(linkToBImpl));
128  portalB->assignDetectorVolumeUpdator(Acts::Direction::Negative,
129  std::move(linkToB), {volumeB});
130 
131  // Reverse: positive volume nullptr, negative volume volumeB
132  nState.direction = Acts::Vector3(0., 0., 1.);
133  portalB->updateDetectorVolume(tContext, nState);
134  BOOST_CHECK(nState.currentVolume == nullptr);
135  nState.direction = Acts::Vector3(0., 0., -1.);
136  portalB->updateDetectorVolume(tContext, nState);
137  BOOST_CHECK(nState.currentVolume == volumeB.get());
138 
139  // Now fuse the portals together, both links valid
140  portalA->fuse(portalB);
141  nState.direction = Acts::Vector3(0., 0., 1.);
142  portalA->updateDetectorVolume(tContext, nState);
143  BOOST_CHECK(nState.currentVolume == volumeA.get());
144  nState.direction = Acts::Vector3(0., 0., -1.);
145  portalA->updateDetectorVolume(tContext, nState);
146  BOOST_CHECK(nState.currentVolume == volumeB.get());
147 
148  // Portal A is now identical to portal B
149  BOOST_CHECK(portalA == portalB);
150 
151  // An invalid fusing setup
152  auto linkToAIImpl = std::make_unique<const LinkToVolumeImpl>(volumeA);
153  auto linkToBIImpl = std::make_unique<const LinkToVolumeImpl>(volumeB);
154 
155  auto portalAI = Portal::makeShared(surface);
156  DetectorVolumeUpdator linkToAI;
157  linkToAI.connect<&LinkToVolumeImpl::link>(std::move(linkToAIImpl));
158  portalAI->assignDetectorVolumeUpdator(Acts::Direction::Positive,
159  std::move(linkToAI), {volumeA});
160 
161  auto portalBI = Portal::makeShared(surface);
162  DetectorVolumeUpdator linkToBI;
163  linkToBI.connect<&LinkToVolumeImpl::link>(std::move(linkToBIImpl));
164  portalBI->assignDetectorVolumeUpdator(Acts::Direction::Positive,
165  std::move(linkToBI), {volumeB});
166 
167  BOOST_CHECK_THROW(portalAI->fuse(portalBI), std::runtime_error);
168 }
169 
170 BOOST_AUTO_TEST_SUITE_END()