Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-02 07:33:18

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Geometry/MultiWireVolumeBuilder.hpp"
0014 #include "Acts/Geometry/TrapezoidPortalShell.hpp"
0015 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0016 #include "Acts/Navigation/INavigationPolicy.hpp"
0017 #include "Acts/Surfaces/StrawSurface.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "ActsTests/CommonHelpers/DetectorElementStub.hpp"
0020 
0021 #include <memory>
0022 #include <numbers>
0023 #include <string>
0024 #include <vector>
0025 
0026 using namespace Acts;
0027 using namespace Acts::Experimental;
0028 using namespace Acts::detail;
0029 
0030 auto tContext = GeometryContext::dangerouslyDefaultConstruct();
0031 constexpr std::size_t nSurfacesX = 15;
0032 constexpr std::size_t nSurfacesY = 4;
0033 constexpr double radius = 15.0;
0034 constexpr double halfZ = 250.0;
0035 
0036 namespace ActsTests {
0037 
0038 BOOST_AUTO_TEST_SUITE(NavigationSuite)
0039 auto logger = getDefaultLogger("MultiWireNavigationTests", Logging::VERBOSE);
0040 
0041 // a function that constructs and returns detector elements for straw surfaces
0042 void generateStrawSurfaces(
0043     std::size_t nStraws, std::size_t nLayers, double radius, double halfZ,
0044     std::vector<std::shared_ptr<Surface>>& strawSurfaces,
0045     std::vector<std::unique_ptr<DetectorElementStub>>& elements) {
0046   // The transform of the 1st surface
0047   Vector3 ipos = {-0.5 * nStraws * 2 * radius + radius,
0048                   -0.5 * nLayers * 2 * radius + radius, 0.};
0049 
0050   Vector3 pos = ipos;
0051   auto lineBounds = std::make_shared<LineBounds>(radius, halfZ);
0052   int id = 1;
0053 
0054   // Generate the surfaces
0055   for (std::size_t i = 0; i < nLayers; i++) {
0056     for (std::size_t j = 0; j < nStraws; j++) {
0057       pos.x() = ipos.x() + 2 * j * radius;
0058 
0059       auto& element =
0060           elements.emplace_back(std::make_unique<DetectorElementStub>(
0061               Transform3(Translation3(pos)), lineBounds, 0));
0062 
0063       element->surface().assignGeometryId(GeometryIdentifier(id++));
0064 
0065       element->surface().assignSurfacePlacement(*element);
0066 
0067       strawSurfaces.push_back(element->surface().getSharedPtr());
0068     }
0069 
0070     pos.y() = ipos.y() + 2 * (i + 1) * radius;
0071   }
0072 }
0073 
0074 // This tests the multilayer navigation policy for gen3 geometry interface
0075 BOOST_AUTO_TEST_CASE(MultiLayer_NavigationPolicy) {
0076   // Create the surfaces
0077   std::vector<std::shared_ptr<Surface>> strawSurfaces = {};
0078   std::vector<std::unique_ptr<DetectorElementStub>> detElements = {};
0079 
0080   generateStrawSurfaces(nSurfacesX, nSurfacesY, radius, halfZ, strawSurfaces,
0081                         detElements);
0082 
0083   std::vector<double> vBounds = {0.5 * nSurfacesX * 2 * radius,
0084                                  0.5 * nSurfacesX * 2 * radius,
0085                                  0.5 * nSurfacesY * 2 * radius, halfZ};
0086   // Create the multi wire volume (tracking volume this time!)
0087   MultiWireVolumeBuilder::Config mwCfg;
0088   mwCfg.name = "MultiWireVolume";
0089   mwCfg.mlSurfaces = strawSurfaces;
0090   mwCfg.binning = {
0091       {DirectedProtoAxis(AxisDirection::AxisX, AxisBoundaryType::Bound,
0092                          -vBounds[0], vBounds[0], nSurfacesX),
0093        1u},
0094       {DirectedProtoAxis(AxisDirection::AxisY, AxisBoundaryType::Bound,
0095                          -vBounds[2], vBounds[2], nSurfacesY),
0096        0u}};
0097   auto boundsPtr = std::make_shared<Acts::TrapezoidVolumeBounds>(
0098       vBounds[0], vBounds[1], vBounds[2], vBounds[3]);
0099   mwCfg.bounds = boundsPtr;
0100   mwCfg.transform = Transform3(Translation3(Vector3(0., 0., 0.)));
0101 
0102   // Build the volume
0103   MultiWireVolumeBuilder mwBuilder(mwCfg);
0104   std::unique_ptr<Acts::TrackingVolume> volume = mwBuilder.buildVolume();
0105 
0106   SingleTrapezoidPortalShell portalShell{tContext, *volume};
0107   portalShell.applyToVolume();
0108 
0109   // Check the volume
0110   // we do not except any children volumes
0111   BOOST_CHECK(volume->volumes().empty());
0112 
0113   // we expect 15*4 = 60 surfaces
0114   BOOST_CHECK(volume->surfaces().size() == 60u);
0115 
0116   BOOST_CHECK(volume->portals().size() == 6u);
0117 
0118   // check the navigation policy
0119   NavigationStream main;
0120   AppendOnlyNavigationStream stream{main};
0121   Vector3 startPos = {0., -59., 0.};
0122   Vector3 startDir = {0., 1., 0.};
0123   NavigationArguments args{startPos, startDir};
0124 
0125   auto navFactory = mwBuilder.createNavigationPolicyFactory();
0126   volume->setNavigationPolicy(navFactory->build(tContext, *volume, *logger));
0127 
0128   NavigationPolicyStateManager stateManager;
0129   volume->navigationPolicy()->createState(tContext, args, stateManager,
0130                                           *logger);
0131   auto policyState = stateManager.currentState();
0132   volume->initializeNavigationCandidates(tContext, args, policyState, stream,
0133                                          *logger);
0134 
0135   // we expect 18 candidates (12 surfaces + 6 portals)
0136   BOOST_CHECK_EQUAL(main.candidates().size(), 18u);
0137 
0138   // check if we have duplicated surface candidates
0139   auto it = std::unique(main.candidates().begin(), main.candidates().end(),
0140                         [](const auto& lhs, const auto& rhs) {
0141                           return lhs.surface() == rhs.surface();
0142                         });
0143   BOOST_CHECK(it == main.candidates().end());
0144 
0145   // try with a different direction
0146   double angle = std::numbers::pi / 4.;
0147   startDir = {std::cos(angle), std::sin(angle), 0.};
0148   args.direction = startDir;
0149   // clear the candidates and re initialize with new arguments
0150   main.candidates().clear();
0151   NavigationPolicyStateManager stateManager2;
0152   volume->navigationPolicy()->createState(tContext, args, stateManager2,
0153                                           *logger);
0154   auto policyState2 = stateManager2.currentState();
0155   volume->initializeNavigationCandidates(tContext, args, policyState2, stream,
0156                                          *logger);
0157   // we expect 18 candidates (12 surfaces + 6 portals)
0158   BOOST_CHECK_EQUAL(main.candidates().size(), 18u);
0159 }
0160 
0161 BOOST_AUTO_TEST_SUITE_END()
0162 
0163 }  // namespace ActsTests