Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:25:01

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/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Definitions/Direction.hpp"
0014 #include "Acts/Definitions/Tolerance.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/Geometry/Blueprint.hpp"
0017 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0018 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0019 #include "Acts/Geometry/CuboidVolumeBuilder.hpp"
0020 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0021 #include "Acts/Geometry/GeometryContext.hpp"
0022 #include "Acts/Geometry/StaticBlueprintNode.hpp"
0023 #include "Acts/Geometry/TrackingGeometry.hpp"
0024 #include "Acts/Geometry/TrackingGeometryBuilder.hpp"
0025 #include "Acts/Geometry/TrackingVolume.hpp"
0026 #include "Acts/MagneticField/ConstantBField.hpp"
0027 #include "Acts/Propagator/NavigationTarget.hpp"
0028 #include "Acts/Propagator/Navigator.hpp"
0029 #include "Acts/Surfaces/PerigeeSurface.hpp"
0030 #include "Acts/Surfaces/PlaneSurface.hpp"
0031 #include "Acts/Surfaces/RectangleBounds.hpp"
0032 #include "Acts/Surfaces/Surface.hpp"
0033 #include "Acts/Utilities/Intersection.hpp"
0034 #include "Acts/Utilities/Logger.hpp"
0035 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0036 #include "ActsTests/CommonHelpers/DetectorElementStub.hpp"
0037 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0038 
0039 #include <cstddef>
0040 #include <memory>
0041 #include <string>
0042 
0043 namespace bdata = boost::unit_test::data;
0044 
0045 using namespace Acts;
0046 using namespace Acts::UnitLiterals;
0047 using Acts::VectorHelpers::perp;
0048 
0049 namespace ActsTests {
0050 
0051 // Create a test context
0052 GeometryContext tgContext = GeometryContext();
0053 MagneticFieldContext mfContext = MagneticFieldContext();
0054 
0055 void step(Vector3& pos, const Vector3& dir, double stepSize) {
0056   pos += stepSize * dir;
0057 }
0058 
0059 void step(Vector3& pos, const Vector3& dir, const Surface& surface) {
0060   Intersection3D intersection =
0061       surface.intersect(tgContext, pos, dir).closestForward();
0062   step(pos, dir, intersection.pathLength());
0063 }
0064 
0065 void step(Vector3& pos, const Vector3& dir, const NavigationTarget& target) {
0066   step(pos, dir, target.surface());
0067 }
0068 
0069 /// @brief Method for testing vectors in @c Navigator::State
0070 ///
0071 /// @param [in] state Navigator state
0072 /// @param [in] navSurf Number of navigation surfaces
0073 /// @param [in] navLay Number of navigation layers
0074 /// @param [in] navBound Number of navigation boundaries
0075 /// @param [in] extSurf Number of external surfaces
0076 bool testNavigatorStateVectors(Navigator::State& state, std::size_t navSurf,
0077                                std::size_t navLay, std::size_t navBound) {
0078   return ((state.navSurfaces.size() == navSurf) &&
0079           (state.navLayers.size() == navLay) &&
0080           (state.navBoundaries.size() == navBound));
0081 }
0082 
0083 /// @brief Method for testing pointers in @c Navigator::State
0084 ///
0085 /// @param [in] state Navigation state
0086 /// @param [in] startVol Start volume
0087 /// @param [in] startLay Start layer
0088 /// @param [in] startSurf Start surface
0089 /// @param [in] currSurf Current surface
0090 /// @param [in] currVol Current volume
0091 /// @param [in] targetSurf Target surface
0092 bool testNavigatorStatePointers(Navigator::State& state,
0093                                 const TrackingVolume* startVol,
0094                                 const Layer* startLay, const Surface* startSurf,
0095                                 const Surface* currSurf,
0096                                 const TrackingVolume* currVol,
0097                                 const Surface* targetSurf) {
0098   std::cout << "startVol: " << startVol << " startLay: " << startLay
0099             << " startSurf: " << startSurf << " currSurf: " << currSurf
0100             << " currVol: " << currVol << " targetSurf: " << targetSurf
0101             << std::endl;
0102 
0103   std::cout << "state.startVolume: " << state.startVolume
0104             << " state.startLayer: " << state.startLayer
0105             << " state.startSurface: " << state.startSurface
0106             << " state.currentSurface: " << state.currentSurface
0107             << " state.currentVolume: " << state.currentVolume
0108             << " state.targetSurface: " << state.targetSurface << std::endl;
0109 
0110   return (
0111       (state.startVolume == startVol) && (state.startLayer == startLay) &&
0112       (state.startSurface == startSurf) && (state.currentSurface == currSurf) &&
0113       (state.currentVolume == currVol) && (state.targetSurface == targetSurf));
0114 }
0115 
0116 // the surface cache & the creation of the geometry
0117 CylindricalTrackingGeometry cGeometry(tgContext);
0118 auto tGeometry = cGeometry();
0119 
0120 const double Bz = 2_T;
0121 auto bField = std::make_shared<ConstantBField>(Vector3{0, 0, Bz});
0122 
0123 Logging::Level logLevel = Logging::INFO;
0124 
0125 BOOST_AUTO_TEST_SUITE(PropagatorSuite)
0126 
0127 BOOST_AUTO_TEST_CASE(Navigator_status_methods) {
0128   ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0129 
0130   // position and direction vector
0131   Vector3 position = Vector3::Zero();
0132   Vector3 direction = Vector3(1., 1., 0).normalized();
0133 
0134   ACTS_INFO("(1) Test for inactivity");
0135   ACTS_INFO("    a) Run without anything present");
0136   {
0137     auto bounds = std::make_shared<CylinderVolumeBounds>(10, 20, 20);
0138     auto tvol = std::make_shared<TrackingVolume>(Transform3::Identity(), bounds,
0139                                                  "Undefined");
0140 
0141     auto tgeo = std::make_shared<TrackingGeometry>(tvol);
0142 
0143     Navigator::Config navCfg;
0144     navCfg.resolveSensitive = false;
0145     navCfg.resolveMaterial = false;
0146     navCfg.resolvePassive = false;
0147     navCfg.trackingGeometry = tgeo;
0148     Navigator navigator{navCfg};
0149 
0150     Navigator::Options options(tgContext);
0151 
0152     Navigator::State state = navigator.makeState(options);
0153 
0154     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0155     BOOST_CHECK(testNavigatorStatePointers(state, nullptr, nullptr, nullptr,
0156                                            nullptr, nullptr, nullptr));
0157   }
0158 
0159   ACTS_INFO("    b) Run with geometry but without resolving");
0160   {
0161     Navigator::Config navCfg;
0162     navCfg.resolveSensitive = false;
0163     navCfg.resolveMaterial = false;
0164     navCfg.resolvePassive = false;
0165     navCfg.trackingGeometry = tGeometry;
0166     Navigator navigator{navCfg};
0167 
0168     Navigator::Options options(tgContext);
0169 
0170     Navigator::State state = navigator.makeState(options);
0171 
0172     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0173     BOOST_CHECK(testNavigatorStatePointers(state, nullptr, nullptr, nullptr,
0174                                            nullptr, nullptr, nullptr));
0175   }
0176 
0177   ACTS_INFO(
0178       "    c) Run with geometry and resolving but broken navigation for "
0179       "various reasons");
0180   {
0181     Navigator::Config navCfg;
0182     navCfg.resolveSensitive = true;
0183     navCfg.resolveMaterial = true;
0184     navCfg.resolvePassive = true;
0185     navCfg.trackingGeometry = tGeometry;
0186     Navigator navigator{navCfg};
0187 
0188     Navigator::Options options(tgContext);
0189 
0190     Navigator::State state = navigator.makeState(options);
0191 
0192     ACTS_INFO("        i) Because target is reached");
0193     state.navigationBreak = true;
0194     navigator.nextTarget(state, position, direction);
0195     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0196     BOOST_CHECK(testNavigatorStatePointers(state, nullptr, nullptr, nullptr,
0197                                            nullptr, nullptr, nullptr));
0198 
0199     ACTS_INFO("        ii) Because of no target surface");
0200     state.targetSurface = nullptr;
0201     navigator.nextTarget(state, position, direction);
0202     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0203     BOOST_CHECK(testNavigatorStatePointers(state, nullptr, nullptr, nullptr,
0204                                            nullptr, nullptr, nullptr));
0205 
0206     ACTS_INFO("        iii) Because the target surface is reached");
0207     auto beamline = Surface::makeShared<PerigeeSurface>(Vector3::Zero());
0208     const Surface* startSurf = beamline.get();
0209     position = startSurf->center(tgContext);
0210     const TrackingVolume* startVol =
0211         tGeometry->lowestTrackingVolume(tgContext, position);
0212     const Layer* startLay = startVol->associatedLayer(tgContext, position);
0213     state.options.startSurface = startSurf;
0214     state.options.targetSurface = startSurf;
0215     BOOST_CHECK(
0216         navigator.initialize(state, position, direction, Direction::Forward())
0217             .ok());
0218     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0219     BOOST_CHECK(testNavigatorStatePointers(state, startVol, startLay, startSurf,
0220                                            startSurf, startVol, startSurf));
0221 
0222     ACTS_INFO("(2) Test the initialisation");
0223     ACTS_INFO("    a) Initialise without additional information");
0224     state = navigator.makeState(options);
0225     position = Vector3::Zero();
0226     startVol = tGeometry->lowestTrackingVolume(tgContext, position);
0227     startLay = startVol->associatedLayer(tgContext, position);
0228     BOOST_CHECK(
0229         navigator.initialize(state, position, direction, Direction::Forward())
0230             .ok());
0231     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0232     BOOST_CHECK(testNavigatorStatePointers(state, startVol, startLay, nullptr,
0233                                            nullptr, startVol, nullptr));
0234 
0235     ACTS_INFO("    b) Initialise having a start surface");
0236     state = navigator.makeState(options);
0237     state.options.startSurface = startSurf;
0238     BOOST_CHECK(
0239         navigator.initialize(state, position, direction, Direction::Forward())
0240             .ok());
0241     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0242     BOOST_CHECK(testNavigatorStatePointers(state, startVol, startLay, startSurf,
0243                                            startSurf, startVol, nullptr));
0244 
0245     ACTS_INFO("    c) Initialise having a start volume");
0246     state = navigator.makeState(options);
0247     state.startVolume = startVol;
0248     BOOST_CHECK(
0249         navigator.initialize(state, position, direction, Direction::Forward())
0250             .ok());
0251     BOOST_CHECK(testNavigatorStateVectors(state, 0u, 0u, 0u));
0252     BOOST_CHECK(testNavigatorStatePointers(state, startVol, startLay, nullptr,
0253                                            nullptr, startVol, nullptr));
0254   }
0255 }
0256 
0257 BOOST_AUTO_TEST_CASE(Navigator_target_methods) {
0258   ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0259 
0260   // create a navigator
0261   Navigator::Config navCfg;
0262   navCfg.trackingGeometry = tGeometry;
0263   navCfg.resolveSensitive = true;
0264   navCfg.resolveMaterial = true;
0265   navCfg.resolvePassive = false;
0266   Navigator navigator{navCfg};
0267 
0268   Navigator::Options options(tgContext);
0269 
0270   Navigator::State state = navigator.makeState(options);
0271 
0272   // position and direction vector
0273   Vector3 position = Vector3::Zero();
0274   Vector3 direction = Vector3(1., 1., 0).normalized();
0275 
0276   // forward navigation ----------------------------------------------
0277   ACTS_INFO("<<<<<<<<<<<<<<<<<<<<< FORWARD NAVIGATION >>>>>>>>>>>>>>>>>>");
0278 
0279   // (1) Initialization navigation from start point
0280   // - this will call resolveLayers() as well
0281   // - and thus should call a return to the stepper
0282   BOOST_CHECK(
0283       navigator.initialize(state, position, direction, Direction::Forward())
0284           .ok());
0285   // Check that the currentVolume is set
0286   BOOST_CHECK_NE(state.currentVolume, nullptr);
0287   // Check that the currentVolume is the startVolume
0288   BOOST_CHECK_EQUAL(state.currentVolume, state.startVolume);
0289   // Check that the currentSurface is reset to:
0290   BOOST_CHECK_EQUAL(state.currentSurface, nullptr);
0291   // No layer has been found
0292   BOOST_CHECK_EQUAL(state.navLayers.size(), 0u);
0293 
0294   // Estimate the next target
0295   NavigationTarget target = navigator.nextTarget(state, position, direction);
0296   BOOST_CHECK(!target.isNone());
0297   // A layer has been found
0298   BOOST_CHECK_EQUAL(state.navLayers.size(), 1u);
0299   // The index should points to the begin
0300   BOOST_CHECK_EQUAL(state.navLayerIndex.value(), 0);
0301   // Check the target is correct
0302   BOOST_CHECK_EQUAL(&target.surface(), &state.navLayer().surface());
0303   // Intersect the target
0304   Intersection3D targetIntersection =
0305       target.surface()
0306           .intersect(tgContext, position, direction)
0307           .closestForward();
0308   // Cache the beam pipe radius
0309   double beamPipeR = perp(state.navLayer().position());
0310   // step size has been updated
0311   CHECK_CLOSE_ABS(targetIntersection.pathLength(), beamPipeR,
0312                   s_onSurfaceTolerance);
0313 
0314   ACTS_INFO("<<< Test 1a >>> initialize at " << toString(position));
0315 
0316   // Do the step towards the beam pipe
0317   step(position, direction, target);
0318 
0319   // (2) re-entering navigator:
0320   // POST STEP
0321   navigator.handleSurfaceReached(state, position, direction, target.surface());
0322   // Check that the currentVolume is the still startVolume
0323   BOOST_CHECK_EQUAL(state.currentVolume, state.startVolume);
0324   // The layer number has not changed
0325   BOOST_CHECK_EQUAL(state.navLayers.size(), 1u);
0326   // The index still points to the begin
0327   BOOST_CHECK_EQUAL(state.navLayerIndex.value(), 0);
0328 
0329   ACTS_INFO("<<< Test 1b >>> step to the BeamPipe at  " << toString(position));
0330 
0331   // Estimate the next target
0332   target = navigator.nextTarget(state, position, direction);
0333   BOOST_CHECK(!target.isNone());
0334 
0335   // Do the step towards the boundary
0336   step(position, direction, target);
0337 
0338   // (3) re-entering navigator:
0339   // POST STEP
0340   navigator.handleSurfaceReached(state, position, direction, target.surface());
0341 
0342   ACTS_INFO("<<< Test 1c >>> step to the Boundary at  " << toString(position));
0343 
0344   // Estimate the next target
0345   target = navigator.nextTarget(state, position, direction);
0346   BOOST_CHECK(!target.isNone());
0347   // Intersect the target
0348   targetIntersection = target.surface()
0349                            .intersect(tgContext, position, direction)
0350                            .closestForward();
0351 
0352   // positive return: do the step
0353   step(position, direction, target);
0354 
0355   // (4) re-entering navigator:
0356   // POST STEP
0357   navigator.handleSurfaceReached(state, position, direction, target.surface());
0358 
0359   ACTS_INFO("<<< Test 1d >>> step to 1st layer at  " << toString(position));
0360 
0361   // Estimate the next target
0362   target = navigator.nextTarget(state, position, direction);
0363   BOOST_CHECK(!target.isNone());
0364 
0365   // Step through the surfaces on first layer
0366   for (std::size_t isf = 0; isf < 5; ++isf) {
0367     step(position, direction, target);
0368     // (5-9) re-entering navigator:
0369     // POST STEP
0370     navigator.handleSurfaceReached(state, position, direction,
0371                                    target.surface());
0372     // ACTORS - ABORTERS - PRE STEP
0373     target = navigator.nextTarget(state, position, direction);
0374     BOOST_CHECK(!target.isNone());
0375 
0376     ACTS_INFO("<<< Test 1e-1i >>> step within 1st layer at  "
0377               << toString(position));
0378   }
0379 
0380   // positive return: do the step
0381   step(position, direction, target);
0382   // (10) re-entering navigator:
0383   // POST STEP
0384   navigator.handleSurfaceReached(state, position, direction, target.surface());
0385   // ACTORS - ABORTERS - PRE STEP
0386   target = navigator.nextTarget(state, position, direction);
0387   BOOST_CHECK(!target.isNone());
0388 
0389   ACTS_INFO("<<< Test 1j >>> step to 2nd layer at  " << toString(position));
0390 
0391   // Step through the surfaces on second layer
0392   for (std::size_t isf = 0; isf < 5; ++isf) {
0393     step(position, direction, target);
0394     // (11-15) re-entering navigator:
0395     // POST STEP
0396     navigator.handleSurfaceReached(state, position, direction,
0397                                    target.surface());
0398     // ACTORS - ABORTERS - PRE STEP
0399     target = navigator.nextTarget(state, position, direction);
0400     BOOST_CHECK(!target.isNone());
0401 
0402     ACTS_INFO("<<< Test 1k-1o >>> step within 2nd layer at  "
0403               << toString(position));
0404   }
0405 
0406   // positive return: do the step
0407   step(position, direction, target);
0408   // (16) re-entering navigator:
0409   // POST STEP
0410   navigator.handleSurfaceReached(state, position, direction, target.surface());
0411   // ACTORS - ABORTERS - PRE STEP
0412   target = navigator.nextTarget(state, position, direction);
0413   BOOST_CHECK(!target.isNone());
0414 
0415   ACTS_INFO("<<< Test 1p >>> step to 3rd layer at  " << toString(position));
0416 
0417   // Step through the surfaces on third layer
0418   for (std::size_t isf = 0; isf < 3; ++isf) {
0419     step(position, direction, target);
0420     // (17-19) re-entering navigator:
0421     // POST STEP
0422     navigator.handleSurfaceReached(state, position, direction,
0423                                    target.surface());
0424     // ACTORS - ABORTERS - PRE STEP
0425     target = navigator.nextTarget(state, position, direction);
0426     BOOST_CHECK(!target.isNone());
0427 
0428     ACTS_INFO("<<< Test 1q-1s >>> step within 3rd layer at  "
0429               << toString(position));
0430   }
0431 
0432   // positive return: do the step
0433   step(position, direction, target);
0434   // (20) re-entering navigator:
0435   // POST STEP
0436   navigator.handleSurfaceReached(state, position, direction, target.surface());
0437   // ACTORS - ABORTERS - PRE STEP
0438   target = navigator.nextTarget(state, position, direction);
0439   BOOST_CHECK(!target.isNone());
0440 
0441   ACTS_INFO("<<< Test 1t >>> step to 4th layer at  " << toString(position));
0442 
0443   // Step through the surfaces on second layer
0444   for (std::size_t isf = 0; isf < 3; ++isf) {
0445     step(position, direction, target);
0446     // (21-23) re-entering navigator:
0447     // POST STEP
0448     navigator.handleSurfaceReached(state, position, direction,
0449                                    target.surface());
0450     // ACTORS - ABORTERS - PRE STEP
0451     target = navigator.nextTarget(state, position, direction);
0452     BOOST_CHECK(!target.isNone());
0453 
0454     ACTS_INFO("<<< Test 1t-1v >>> step within 4th layer at  "
0455               << toString(position));
0456   }
0457 
0458   // positive return: do the step
0459   step(position, direction, target);
0460   // (24) re-entering navigator:
0461   // POST STEP
0462   navigator.handleSurfaceReached(state, position, direction, target.surface());
0463   // ACTORS - ABORTERS - PRE STEP
0464   target = navigator.nextTarget(state, position, direction);
0465   BOOST_CHECK(target.isNone());
0466 
0467   ACTS_INFO("<<< Test 1w >>> step to boundary at  " << toString(position));
0468 }
0469 
0470 inline std::tuple<std::shared_ptr<const TrackingGeometry>,
0471                   std::vector<const Surface*>>
0472 createDenseTelescope(const GeometryContext& geoCtx) {
0473   using namespace Acts;
0474   using namespace UnitLiterals;
0475 
0476   CuboidVolumeBuilder::Config conf;
0477   conf.position = {0., 0., 0.};
0478   conf.length = {2_m, 2_m, 2_m};
0479 
0480   {
0481     CuboidVolumeBuilder::SurfaceConfig surfaceTop;
0482     surfaceTop.position = {0, 0.5_m, 0.5_m};
0483     surfaceTop.rBounds = std::make_shared<RectangleBounds>(0.8_m, 0.2_m);
0484 
0485     CuboidVolumeBuilder::SurfaceConfig surfaceBottom;
0486     surfaceBottom.position = {0, -0.5_m, 0.5_m};
0487     surfaceBottom.rBounds = std::make_shared<RectangleBounds>(0.8_m, 0.2_m);
0488 
0489     CuboidVolumeBuilder::LayerConfig layer;
0490     layer.surfaceCfg.push_back(surfaceTop);
0491     layer.surfaceCfg.push_back(surfaceBottom);
0492 
0493     CuboidVolumeBuilder::VolumeConfig start;
0494     start.position = {0, 0, 0};
0495     start.length = {1.9_m, 1.9_m, 1.9_m};
0496     start.name = "start";
0497     start.layerCfg.push_back(layer);
0498 
0499     conf.volumeCfg.push_back(start);
0500   }
0501 
0502   CuboidVolumeBuilder cvb(conf);
0503 
0504   TrackingGeometryBuilder::Config tgbCfg;
0505   tgbCfg.trackingVolumeBuilders.push_back(
0506       [=](const auto& context, const auto& inner, const auto&) {
0507         return cvb.trackingVolume(context, inner, nullptr);
0508       });
0509   auto detector = TrackingGeometryBuilder(tgbCfg).trackingGeometry(geoCtx);
0510 
0511   std::vector<const Surface*> surfaces;
0512   detector->visitSurfaces(
0513       [&](const Surface* surface) { surfaces.push_back(surface); });
0514 
0515   return {std::move(detector), std::move(surfaces)};
0516 }
0517 
0518 BOOST_AUTO_TEST_CASE(Navigator_external_surfaces) {
0519   ACTS_LOCAL_LOGGER(getDefaultLogger("NavigatorTest", logLevel));
0520 
0521   auto [detector, surfaces] = createDenseTelescope(tgContext);
0522   BOOST_CHECK_EQUAL(surfaces.size(), 2ul);
0523   const Surface& surfaceTop = *surfaces.at(0);
0524   const Surface& surfaceBottom = *surfaces.at(1);
0525   CHECK_CLOSE_ABS(surfaceTop.center(tgContext).y(), 0.5_m, 1e-6);
0526   CHECK_CLOSE_ABS(surfaceBottom.center(tgContext).y(), -0.5_m, 1e-6);
0527 
0528   Navigator::Config navCfg;
0529   navCfg.trackingGeometry = detector;
0530   navCfg.resolveSensitive = true;
0531   navCfg.resolveMaterial = true;
0532   navCfg.resolvePassive = false;
0533   Navigator navigator(navCfg, logger().clone("Navigator"));
0534 
0535   // check if we find no sensitive target starting from the middle without
0536   // external surfaces
0537   {
0538     ACTS_INFO("Test 1: start in the middle without external surfaces");
0539 
0540     Navigator::Options options(tgContext);
0541     Navigator::State state = navigator.makeState(options);
0542 
0543     Vector3 position = Vector3::Zero();
0544     Vector3 direction = Vector3::UnitZ();
0545 
0546     Result<void> result =
0547         navigator.initialize(state, position, direction, Direction::Forward());
0548     BOOST_CHECK(result.ok());
0549 
0550     NavigationTarget target = navigator.nextTarget(state, position, direction);
0551 
0552     BOOST_CHECK_NE(&target.surface(), surfaces.at(0));
0553     BOOST_CHECK_NE(&target.surface(), surfaces.at(1));
0554   }
0555 
0556   // check if we find a target starting from the top without external surfaces
0557   {
0558     ACTS_INFO("Test 2: start from top without external surfaces");
0559 
0560     Navigator::Options options(tgContext);
0561     Navigator::State state = navigator.makeState(options);
0562 
0563     Vector3 position = {0, 0.5_m, 0};
0564     Vector3 direction = Vector3::UnitZ();
0565 
0566     Result<void> result =
0567         navigator.initialize(state, position, direction, Direction::Forward());
0568     BOOST_CHECK(result.ok());
0569 
0570     NavigationTarget target = navigator.nextTarget(state, position, direction);
0571 
0572     BOOST_CHECK(!target.isNone());
0573     BOOST_CHECK_EQUAL(&target.surface(), &surfaceTop);
0574   }
0575 
0576   // check if we find a target starting from the bottom without external
0577   // surfaces
0578   {
0579     ACTS_INFO("Test 2: start from bottom without external surfaces");
0580 
0581     Navigator::Options options(tgContext);
0582     Navigator::State state = navigator.makeState(options);
0583 
0584     Vector3 position = {0, -0.5_m, 0};
0585     Vector3 direction = Vector3::UnitZ();
0586 
0587     Result<void> result =
0588         navigator.initialize(state, position, direction, Direction::Forward());
0589     BOOST_CHECK(result.ok());
0590 
0591     NavigationTarget target = navigator.nextTarget(state, position, direction);
0592 
0593     BOOST_CHECK(!target.isNone());
0594     BOOST_CHECK_EQUAL(&target.surface(), &surfaceBottom);
0595   }
0596 
0597   // check if we find the top surface starting from the middle with external
0598   // surfaces
0599   {
0600     ACTS_INFO("Test 3: start in the middle with external surfaces");
0601 
0602     Navigator::Options options(tgContext);
0603     options.insertExternalSurface(surfaceTop.geometryId());
0604     Navigator::State state = navigator.makeState(options);
0605 
0606     Vector3 position = {0, 0, 0};
0607     Vector3 direction = Vector3::UnitZ();
0608 
0609     Result<void> result =
0610         navigator.initialize(state, position, direction, Direction::Forward());
0611     BOOST_CHECK(result.ok());
0612 
0613     NavigationTarget target = navigator.nextTarget(state, position, direction);
0614 
0615     BOOST_CHECK(!target.isNone());
0616     BOOST_CHECK_EQUAL(&target.surface(), &surfaceTop);
0617   }
0618 
0619   // check if we find the bottom surface starting from the top with external
0620   // surfaces
0621   {
0622     ACTS_INFO("Test 4: start from top with external surfaces");
0623 
0624     Navigator::Options options(tgContext);
0625     options.insertExternalSurface(surfaceBottom.geometryId());
0626     Navigator::State state = navigator.makeState(options);
0627 
0628     Vector3 position = {0, 0.5_m, 0};
0629     Vector3 direction = Vector3::UnitZ();
0630 
0631     Result<void> result =
0632         navigator.initialize(state, position, direction, Direction::Forward());
0633     BOOST_CHECK(result.ok());
0634 
0635     NavigationTarget target = navigator.nextTarget(state, position, direction);
0636 
0637     BOOST_CHECK(!target.isNone());
0638     BOOST_CHECK_EQUAL(&target.surface(), &surfaceBottom);
0639   }
0640 
0641   // check if we find the top surface starting from the bottom with external
0642   // surfaces
0643   {
0644     ACTS_INFO("Test 5: start from bottom with external surfaces");
0645 
0646     Navigator::Options options(tgContext);
0647     options.insertExternalSurface(surfaceTop.geometryId());
0648     Navigator::State state = navigator.makeState(options);
0649 
0650     Vector3 position = {0, -0.5_m, 0};
0651     Vector3 direction = Vector3::UnitZ();
0652 
0653     Result<void> result =
0654         navigator.initialize(state, position, direction, Direction::Forward());
0655     BOOST_CHECK(result.ok());
0656 
0657     NavigationTarget target = navigator.nextTarget(state, position, direction);
0658 
0659     BOOST_CHECK(!target.isNone());
0660     BOOST_CHECK_EQUAL(&target.surface(), &surfaceTop);
0661   }
0662 }
0663 
0664 BOOST_AUTO_TEST_CASE(TryAllNavigationPolicy_SurfaceInsideVolume) {
0665   auto logger = getDefaultLogger("UnitTests", Logging::VERBOSE);
0666 
0667   Experimental::Blueprint::Config cfg;
0668   cfg.envelope = ExtentEnvelope{{
0669       .z = {20_mm, 20_mm},
0670       .r = {0_mm, 20_mm},
0671   }};
0672 
0673   Experimental::Blueprint root{cfg};
0674 
0675   auto& cubcontainer =
0676       root.addCuboidContainer("CuboidContainer", AxisDirection::AxisZ);
0677 
0678   auto parentBounds = std::make_shared<CuboidVolumeBounds>(1_m, 1_m, 1_m);
0679 
0680   auto parentVol = std::make_unique<TrackingVolume>(Transform3::Identity(),
0681                                                     parentBounds, "parent");
0682 
0683   std::shared_ptr<const PlanarBounds> planarBounds =
0684       std::make_shared<const RectangleBounds>(5., 10.);
0685 
0686   auto surface = Surface::makeShared<PlaneSurface>(Transform3::Identity(),
0687                                                    std::move(planarBounds));
0688 
0689   auto detElement =
0690       std::make_unique<DetectorElementStub>(Transform3::Identity());
0691 
0692   surface->assignDetectorElement(*detElement);
0693 
0694   parentVol->assignGeometryId(GeometryIdentifier{}.withVolume(1));
0695   parentVol->addSurface(surface);
0696   auto parentNode =
0697       std::make_shared<Experimental::StaticBlueprintNode>(std::move(parentVol));
0698 
0699   // put two tracking volumes in the sides of the parent as children and a plane
0700   // surface in the middle of the parent volume
0701   double startZ1 = -1000. + 100. + 1.;
0702   double startZ2 = 1000. - 100. - 1.;
0703   Transform3 trf1 = Transform3(Translation3(0., 0., startZ1));
0704   Transform3 trf2 = Transform3(Translation3(0., 0., startZ2));
0705 
0706   auto childBounds = std::make_shared<CuboidVolumeBounds>(1_m, 1_m, 10_cm);
0707   auto childVol1 =
0708       std::make_unique<TrackingVolume>(trf1, childBounds, "child1");
0709   childVol1->assignGeometryId(GeometryIdentifier{}.withVolume(2));
0710 
0711   auto childNode1 =
0712       std::make_shared<Experimental::StaticBlueprintNode>(std::move(childVol1));
0713 
0714   auto childVol2 =
0715       std::make_unique<TrackingVolume>(trf2, childBounds, "child2");
0716   childVol2->assignGeometryId(GeometryIdentifier{}.withVolume(3));
0717 
0718   auto childNode2 =
0719       std::make_shared<Experimental::StaticBlueprintNode>(std::move(childVol2));
0720 
0721   parentNode->addChild(childNode1);
0722   parentNode->addChild(childNode2);
0723 
0724   cubcontainer.addChild(std::move(parentNode));
0725 
0726   auto trackingGeometry = root.construct({}, tgContext, *logger);
0727 
0728   Navigator::Config navCfg;
0729   navCfg.trackingGeometry =
0730       std::shared_ptr<const TrackingGeometry>(std::move(trackingGeometry));
0731   navCfg.resolveSensitive = true;
0732   navCfg.resolveMaterial = true;
0733   navCfg.resolvePassive = false;
0734   Navigator navigator(navCfg, logger->clone("Navigator"));
0735 
0736   Navigator::Options options(tgContext);
0737   Navigator::State state = navigator.makeState(options);
0738 
0739   Vector3 position{0., 0., -1000. + 0.5};
0740   Vector3 direction = Vector3::UnitZ();
0741 
0742   Result<void> result =
0743       navigator.initialize(state, position, direction, Direction::Forward());
0744   BOOST_CHECK(result.ok());
0745   BOOST_CHECK(state.currentVolume != nullptr);
0746   BOOST_CHECK(state.currentVolume->volumeName() == "parent");
0747   BOOST_CHECK_EQUAL(state.currentSurface, nullptr);
0748 
0749   // Do the chain simulating a straight line propagation
0750   // and check if we end up to the expected elements
0751 
0752   NavigationTarget target = navigator.nextTarget(state, position, direction);
0753 
0754   // it is supposed to find the boundary of the next child volume
0755   BOOST_CHECK(!target.isNone());
0756   auto targetGeoId = target.surface().geometryId();
0757   // portal of child1 volume as expected
0758   BOOST_CHECK(targetGeoId.volume() == 2 && targetGeoId.boundary() == 1);
0759 
0760   step(position, direction, target);
0761   navigator.handleSurfaceReached(state, position, direction, target.surface());
0762   // check that we end up in the expected volume (child1)
0763   BOOST_CHECK(state.currentVolume->volumeName() == "child1");
0764 
0765   target = navigator.nextTarget(state, position, direction);
0766   BOOST_CHECK(!target.isNone());
0767   targetGeoId = target.surface().geometryId();
0768   // portal of child1 volume as expected
0769   BOOST_CHECK(targetGeoId.volume() == 2 && targetGeoId.boundary() == 2);
0770 
0771   step(position, direction, target);
0772   navigator.handleSurfaceReached(state, position, direction, target.surface());
0773   // check that we end up in the expected volume (parent)
0774   BOOST_CHECK(state.currentVolume->volumeName() == "parent");
0775   // the next target should be the plane surface inside the parent volume
0776   target = navigator.nextTarget(state, position, direction);
0777   BOOST_CHECK(!target.isNone());
0778   BOOST_CHECK_EQUAL(&target.surface(), surface.get());
0779 
0780   step(position, direction, target);
0781   navigator.handleSurfaceReached(state, position, direction, target.surface());
0782   // check that we are still in the parent volume
0783   BOOST_CHECK(state.currentVolume->volumeName() == "parent");
0784 
0785   target = navigator.nextTarget(state, position, direction);
0786   BOOST_CHECK(!target.isNone());
0787   targetGeoId = target.surface().geometryId();
0788   // portal of child2 volume as expected
0789   BOOST_CHECK(targetGeoId.volume() == 3 && targetGeoId.boundary() == 1);
0790 
0791   step(position, direction, target);
0792   navigator.handleSurfaceReached(state, position, direction, target.surface());
0793   // check that we end up in the expected volume (child2)
0794   BOOST_CHECK(state.currentVolume->volumeName() == "child2");
0795   target = navigator.nextTarget(state, position, direction);
0796   BOOST_CHECK(!target.isNone());
0797   targetGeoId = target.surface().geometryId();
0798   // portal of child2 volume as expected
0799   BOOST_CHECK(targetGeoId.volume() == 3 && targetGeoId.boundary() == 2);
0800 
0801   step(position, direction, target);
0802   navigator.handleSurfaceReached(state, position, direction, target.surface());
0803   // check that we end up in the expected volume (parent)
0804   BOOST_CHECK(state.currentVolume->volumeName() == "parent");
0805 }
0806 
0807 BOOST_AUTO_TEST_SUITE_END()
0808 
0809 }  // namespace ActsTests