From ecd6529c842751f5f7a737e61e50e519038c1e78 Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 16:20:35 +0100 Subject: [PATCH 1/8] draft --- .../Acts/Navigation/NavigationState.hpp | 52 +-- .../Navigation/NavigationStateFillers.hpp | 76 ++++ .../include/Acts/Navigation/NextNavigator.hpp | 373 ++++++++++++++++++ .../Navigation/SurfaceCandidatesUpdators.hpp | 2 +- Core/src/Detector/DetectorVolume.cpp | 14 - .../UnitTests/Core/Navigation/CMakeLists.txt | 1 + .../Core/Navigation/NavigationStateTests.cpp | 1 + .../NavigationStateUpdatorsTests.cpp | 1 + .../Core/Navigation/NextNavigatorTests.cpp | 87 ++++ 9 files changed, 544 insertions(+), 63 deletions(-) create mode 100644 Core/include/Acts/Navigation/NavigationStateFillers.hpp create mode 100644 Core/include/Acts/Navigation/NextNavigator.hpp create mode 100644 Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp diff --git a/Core/include/Acts/Navigation/NavigationState.hpp b/Core/include/Acts/Navigation/NavigationState.hpp index cc6c493b3ff..1e931fb9f59 100644 --- a/Core/include/Acts/Navigation/NavigationState.hpp +++ b/Core/include/Acts/Navigation/NavigationState.hpp @@ -44,7 +44,7 @@ struct NavigationState { const Portal* portal = nullptr; /// The boundary check used for the candidate, boundary checks /// can differ for sensitive surfaces and portals - BoundaryCheck bCheck = true; + BoundaryCheck boundaryCheck = true; }; /// Surface candidate vector alias, this allows to use e.g. boost_small vector @@ -75,6 +75,9 @@ struct NavigationState { /// The current surface, i.e the position is on surface const Surface* currentSurface = nullptr; + /// The current portal, i.e the position is on portal + const Portal* currentPortal = nullptr; + /// That are the candidate surfaces to process SurfaceCandidates surfaceCandidates = {}; SurfaceCandidates::iterator surfaceCandidate = surfaceCandidates.end(); @@ -89,52 +92,5 @@ struct NavigationState { std::any auxilliary; }; -/// Filler of the current volume -struct DetectorVolumeFiller { - /// Helper struct that allows to fill a volume into the - /// navigation state, it allows to use common navigation - /// structs for volume, portal, surfaces - /// - /// @param nState the navigation state - /// @param volume the volume that is filled - inline static void fill(NavigationState& nState, - const DetectorVolume* volume) { - nState.currentVolume = volume; - } -}; - -/// Fillers and attachers for surfaces to act on the navigation state -struct SurfacesFiller { - /// Helper struct that allows to fill surfaces into the candidate vector it - /// allows to use common navigation structs for volume, portal, surfaces - /// - /// @param nState the navigation state - /// @param surfaces the surfaces that are filled in - inline static void fill(NavigationState& nState, - const std::vector& surfaces) { - std::for_each(surfaces.begin(), surfaces.end(), [&](const auto& s) { - nState.surfaceCandidates.push_back(NavigationState::SurfaceCandidate{ - ObjectIntersection{}, s, nullptr, - nState.surfaceBoundaryCheck}); - }); - } -}; - -/// Fillers and attachers for portals to act on the navigation state -struct PortalsFiller { - /// Helper struct that allows to fill surfaces into the candidate vector it - /// allows to use common navigation structs for volume, portal, surfaces - /// - /// @param nState the navigation state - /// @param portals the portals that are filled in - inline static void fill(NavigationState& nState, - const std::vector& portals) { - std::for_each(portals.begin(), portals.end(), [&](const auto& p) { - nState.surfaceCandidates.push_back(NavigationState::SurfaceCandidate{ - ObjectIntersection{}, nullptr, p, true}); - }); - } -}; - } // namespace Experimental } // namespace Acts diff --git a/Core/include/Acts/Navigation/NavigationStateFillers.hpp b/Core/include/Acts/Navigation/NavigationStateFillers.hpp new file mode 100644 index 00000000000..e014b3c94bd --- /dev/null +++ b/Core/include/Acts/Navigation/NavigationStateFillers.hpp @@ -0,0 +1,76 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2021 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/Surfaces/BoundaryCheck.hpp" +#include "Acts/Utilities/Intersection.hpp" + +#include + +namespace Acts { + +class Surface; + +namespace Experimental { + +class Portal; +class Detector; +class DetectorVolume; + +/// Filler of the current volume +struct DetectorVolumeFiller { + /// Helper struct that allows to fill a volume into the + /// navigation state, it allows to use common navigation + /// structs for volume, portal, surfaces + /// + /// @param nState the navigation state + /// @param volume the volume that is filled + inline static void fill(NavigationState& nState, + const DetectorVolume* volume) { + nState.currentVolume = volume; + } +}; + +/// Fillers and attachers for surfaces to act on the navigation state +struct SurfacesFiller { + /// Helper struct that allows to fill surfaces into the candidate vector it + /// allows to use common navigation structs for volume, portal, surfaces + /// + /// @param nState the navigation state + /// @param surfaces the surfaces that are filled in + inline static void fill(NavigationState& nState, + const std::vector& surfaces) { + std::for_each(surfaces.begin(), surfaces.end(), [&](const auto& s) { + nState.surfaceCandidates.push_back(NavigationState::SurfaceCandidate{ + ObjectIntersection{}, s, nullptr, + nState.surfaceBoundaryCheck}); + }); + } +}; + +/// Fillers and attachers for portals to act on the navigation state +struct PortalsFiller { + /// Helper struct that allows to fill surfaces into the candidate vector it + /// allows to use common navigation structs for volume, portal, surfaces + /// + /// @param nState the navigation state + /// @param portals the portals that are filled in + inline static void fill(NavigationState& nState, + const std::vector& portals) { + std::for_each(portals.begin(), portals.end(), [&](const auto& p) { + nState.surfaceCandidates.push_back(NavigationState::SurfaceCandidate{ + ObjectIntersection{}, nullptr, p, true}); + }); + } +}; + +} // namespace Experimental +} // namespace Acts diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp new file mode 100644 index 00000000000..d82925c891a --- /dev/null +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -0,0 +1,373 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2023 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#pragma once + +#include "Acts/Definitions/Units.hpp" +#include "Acts/Detector/Detector.hpp" +#include "Acts/Detector/DetectorVolume.hpp" +#include "Acts/Detector/Portal.hpp" +#include "Acts/Geometry/BoundarySurfaceT.hpp" +#include "Acts/Geometry/GeometryIdentifier.hpp" +#include "Acts/Geometry/Layer.hpp" +#include "Acts/Navigation/NavigationState.hpp" +#include "Acts/Propagator/ConstrainedStep.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include +#include +#include +#include + +#include +#include + +namespace Acts { + +namespace Experimental { + +class NextNavigator { + public: + struct Config { + /// Detector for this Navigation + const Detector* detector = nullptr; + + /// Configuration for this Navigator + /// stop at every sensitive surface (whether it has material or not) + bool resolveSensitive = true; + /// stop at every material surface (whether it is passive or not) + bool resolveMaterial = true; + /// stop at every surface regardless what it is + bool resolvePassive = false; + + /// The tolerance used to defined "reached" + double tolerance = s_onSurfaceTolerance; + }; + + /// Nested State struct + /// + /// It acts as an internal state which is + /// created for every propagation/extrapolation step + /// and keep thread-local navigation information + struct State : public NavigationState { + /// Navigation state - external state: the start surface + const Surface* startSurface = nullptr; + /// Navigation state - external state: the current surface + const Surface* currentSurface = nullptr; + /// Navigation state - external state: the target surface + const Surface* targetSurface = nullptr; + /// Indicator if the target is reached + bool targetReached = false; + /// Navigation state : a break has been detected + bool navigationBreak = false; + + /// Reset state + /// + /// @param geoContext is the geometry context + /// @param pos is the global position + /// @param dir is the momentum direction + /// @param navDir is the navigation direction + /// @param ssurface is the new starting surface + /// @param tsurface is the target surface + void reset(const GeometryContext& /*geoContext*/, const Vector3& /*pos*/, + const Vector3& /*dir*/, NavigationDirection /*navDir*/, + const Surface* /*ssurface*/, const Surface* /*tsurface*/) { + // Reset everything first + *this = State(); + + // TODO do stuff? + } + }; + + /// Constructor with configuration object + /// + /// @param cfg The navigator configuration + /// @param _logger a logger instance + explicit NextNavigator(Config cfg, std::shared_ptr _logger = + getDefaultLogger("NextNavigator", + Logging::Level::INFO)) + : m_cfg{std::move(cfg)}, m_logger{std::move(_logger)} {} + + /// @brief Navigator status call + /// + /// @tparam propagator_state_t is the type of Propagatgor state + /// @tparam stepper_t is the used type of the Stepper by the Propagator + /// + /// @param [in,out] state is the mutable propagator state object + /// @param [in] stepper Stepper in use + template + void status(propagator_state_t& state, const stepper_t& stepper) const { + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "Entering navigator::status."); + + auto& nState = state.navigation; + fillNavigationState(state, stepper, nState); + + if (inactive(state, stepper)) { + ACTS_VERBOSE("navigator inactive"); + return; + } + + if (nState.currentDetector == nullptr) { + initialize(state, stepper); + return; + } + + if (nState.surfaceCandidate == nState.surfaceCandidates.end()) { + ACTS_VERBOSE("no surface candidates - waiting for target call"); + return; + } + + const Portal* nextPortal = nullptr; + const Surface* nextSurface = nullptr; + bool isPortal = false; + bool boundaryCheck = nState.surfaceCandidate->boundaryCheck; + + if (nState.surfaceCandidate->surface != nullptr) { + nextSurface = nState.surfaceCandidate->surface; + } else if (nState.surfaceCandidate->portal != nullptr) { + nextPortal = nState.surfaceCandidate->portal; + nextSurface = &nextPortal->surface(); + isPortal = true; + } else { + ACTS_ERROR("panic: not a surface not a portal - what is it?"); + return; + } + + // TODO not sure about the boundary check + auto surfaceStatus = stepper.updateSurfaceStatus( + state.stepping, *nextSurface, boundaryCheck, logger()); + + // Check if we are at a surface + if (surfaceStatus == Intersection3D::Status::onSurface) { + ACTS_VERBOSE("landed on surface"); + + if (isPortal) { + ACTS_VERBOSE("this is a portal, storing it."); + + nState.currentPortal = nextPortal; + + ACTS_VERBOSE("current portal set to " + << nState.currentPortal->surface().geometryId()); + } else { + ACTS_VERBOSE("this is a surface, storing it."); + + // If we are on the surface pointed at by the iterator, we can make + // it the current one to pass it to the other actors + nState.currentSurface = nextSurface; + ACTS_VERBOSE("current surface set to " + << nState.currentSurface->geometryId()); + ++nState.surfaceCandidate; + } + } + } + + /// @brief Navigator target call + /// + /// @tparam propagator_state_t is the type of Propagatgor state + /// @tparam stepper_t is the used type of the Stepper by the Propagator + /// + /// @param [in,out] state is the mutable propagator state object + /// @param [in] stepper Stepper in use + template + void target(propagator_state_t& state, const stepper_t& stepper) const { + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "Entering navigator::target."); + + auto& nState = state.navigation; + + if (inactive(state, stepper)) { + ACTS_VERBOSE("navigator inactive"); + return; + } + + if (nState.currentVolume == nullptr) { + initializeTarget(state, stepper); + } + + if (nState.currentSurface != nullptr) { + ACTS_VERBOSE("stepping through surface"); + } else if (nState.currentPortal != nullptr) { + ACTS_VERBOSE("stepping through portal"); + + nState.surfaceCandidates.clear(); + nState.surfaceCandidate = nState.surfaceCandidates.end(); + + nState.currentPortal->updateDetectorVolume(state.geoContext, nState); + + initializeTarget(state, stepper); + } + + for (; nState.surfaceCandidate != nState.surfaceCandidates.end(); + ++nState.surfaceCandidate) { + // Screen output how much is left to try + ACTS_VERBOSE(volInfo(state) + << std::distance(nState.surfaceCandidate, + nState.surfaceCandidates.end()) + << " out of " << nState.surfaceCandidates.size() + << " surfaces remain to try."); + // Take the surface + const auto& c = *(nState.surfaceCandidate); + const auto& surface = + (c.surface != nullptr) ? (*c.surface) : (c.portal->surface()); + // Screen output which surface you are on + ACTS_VERBOSE("Next surface candidate will be " << surface.geometryId()); + // Estimate the surface status + bool boundaryCheck = c.boundaryCheck; + auto surfaceStatus = stepper.updateSurfaceStatus(state.stepping, surface, + boundaryCheck, logger()); + if (surfaceStatus == Intersection3D::Status::reachable) { + ACTS_VERBOSE("Surface reachable, step size updated to " + << stepper.outputStepSize(state.stepping)); + break; + } + } + + nState.currentSurface = nullptr; + nState.currentPortal = nullptr; + } + + private: + Config m_cfg; + + std::shared_ptr m_logger; + + template + std::string volInfo(const propagator_state_t& state) const { + auto& nState = state.navigation; + + return (nState.currentVolume ? nState.currentVolume->name() : "No Volume") + + " | "; + } + + template + std::string posInfo(const propagator_state_t& state, + const stepper_t& stepper) const { + std::stringstream ss; + ss << stepper.position(state.stepping).transpose(); + ss << " | "; + return ss.str(); + } + + const Logger& logger() const { return *m_logger; } + + /// This checks if a navigation break had been triggered or navigator + /// is misconfigured + /// + /// @tparam propagator_state_t The state type of the propagagor + /// @tparam stepper_t The type of stepper used for the propagation + /// + /// @param [in,out] state is the propagation state object + /// @param [in] stepper Stepper in use + /// + /// boolean return triggers exit to stepper + template + bool inactive(propagator_state_t& /*state*/, + const stepper_t& /*stepper*/) const { + if (m_cfg.detector == nullptr) { + return true; + } + + if (!m_cfg.resolveSensitive && !m_cfg.resolveMaterial && + !m_cfg.resolvePassive) { + return true; + } + + return false; + } + + /// Initialize call - start of propagation + /// + /// @tparam propagator_state_t The state type of the propagagor + /// @tparam stepper_t The type of stepper used for the propagation + /// + /// @param [in,out] state is the propagation state object + /// @param [in] stepper Stepper in use + /// + /// @return boolean return triggers exit to stepper + template + void initialize(propagator_state_t& state, const stepper_t& stepper) const { + ACTS_VERBOSE(volInfo(state) << posInfo(state, stepper) << "initialize"); + + auto& nState = state.navigation; + + if (nState.currentDetector == nullptr) { + ACTS_VERBOSE("assigning detector from the config."); + nState.currentDetector = m_cfg.detector; + } + + if (nState.currentDetector == nullptr) { + ACTS_ERROR("panic: no detector"); + return; + } + } + + /// Navigation (re-)initialisation for the target + /// + /// This is only called a few times every propagation/extrapolation + /// + /// --------------------------------------------------------------------- + /// + /// As a straight line estimate can lead you to the wrong destination + /// Volume, this will be called at: + /// - initialization + /// - attempted volume switch + /// Target finding by association will not be done again + /// + /// @tparam propagator_state_t The state type of the propagagor + /// @tparam stepper_t The type of stepper used for the propagation + /// + /// @param [in,out] state is the propagation state object + /// @param [in] stepper Stepper in use + /// + /// boolean return triggers exit to stepper + template + void initializeTarget(propagator_state_t& state, + const stepper_t& stepper) const { + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "initialize target"); + + auto& nState = state.navigation; + + if (nState.currentVolume == nullptr) { + nState.currentVolume = nState.currentDetector->findDetectorVolume( + state.geoContext, nState.position); + + if (nState.currentVolume != nullptr) { + ACTS_VERBOSE(volInfo(state) << "switched detector volume"); + } + } + + if (nState.currentVolume == nullptr) { + ACTS_ERROR("panic: no current volume"); + return; + } + + nState.currentVolume->updateNavigationState(state.geoContext, nState); + } + + template + void fillNavigationState(propagator_state_t& state, const stepper_t& stepper, + NavigationState& nState) const { + nState.position = stepper.position(state.stepping); + nState.direction = stepper.direction(state.stepping); + nState.absMomentum = stepper.momentum(state.stepping); + nState.charge = stepper.charge(state.stepping); + auto fieldResult = stepper.getField(state.stepping, nState.position); + if (!fieldResult.ok()) { + ACTS_ERROR("could not read from the magnetic field"); + } + nState.magneticField = *fieldResult; + } +}; + +} // namespace Experimental + +} // namespace Acts diff --git a/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp b/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp index 3477e623fe9..ba1814d4ab7 100644 --- a/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp +++ b/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp @@ -43,7 +43,7 @@ inline static void updateCandidates(const GeometryContext& gctx, (c.surface != nullptr) ? (*c.surface) : (c.portal->surface()); // Get the intersection @todo make a templated intersector - auto sIntersection = sRep.intersect(gctx, position, direction, c.bCheck); + auto sIntersection = sRep.intersect(gctx, position, direction, c.boundaryCheck); // Re-order and swap if necessary if (sIntersection.intersection.pathLength + s_onSurfaceTolerance < nState.overstepTolerance and diff --git a/Core/src/Detector/DetectorVolume.cpp b/Core/src/Detector/DetectorVolume.cpp index 56497006182..b185c776b75 100644 --- a/Core/src/Detector/DetectorVolume.cpp +++ b/Core/src/Detector/DetectorVolume.cpp @@ -114,23 +114,9 @@ bool Acts::Experimental::DetectorVolume::inside(const GeometryContext& gctx, void Acts::Experimental::DetectorVolume::updateNavigationState( const GeometryContext& gctx, NavigationState& nState) const { - // This volume still has sub volumes, it needs a double-check - // if the internal volumes can be excluded. - // - // This can be avoided by a precise volume finder - if (not m_volumes.external.empty()) { - for (const auto v : volumes()) { - if (v->inside(gctx, nState.position)) { - v->updateNavigationState(gctx, nState); - return; - } - } - } - // The state updator of the volume itself nState.currentVolume = this; m_surfaceCandidatesUpdator(gctx, nState); nState.surfaceCandidate = nState.surfaceCandidates.begin(); - return; } void Acts::Experimental::DetectorVolume::assignSurfaceCandidatesUpdator( diff --git a/Tests/UnitTests/Core/Navigation/CMakeLists.txt b/Tests/UnitTests/Core/Navigation/CMakeLists.txt index 4c4155bbd62..d9dec6ebe1a 100644 --- a/Tests/UnitTests/Core/Navigation/CMakeLists.txt +++ b/Tests/UnitTests/Core/Navigation/CMakeLists.txt @@ -2,3 +2,4 @@ add_unittest(DetectorVolumeUpdators DetectorVolumeUpdatorsTests.cpp) add_unittest(DetectorVolumeFinders DetectorVolumeFindersTests.cpp) add_unittest(NavigationState NavigationStateTests.cpp) add_unittest(NavigationStateUpdators NavigationStateUpdatorsTests.cpp) +add_unittest(NextNavigator NextNavigatorTests.cpp) diff --git a/Tests/UnitTests/Core/Navigation/NavigationStateTests.cpp b/Tests/UnitTests/Core/Navigation/NavigationStateTests.cpp index 88b7d8d4fa0..06ba95921c0 100644 --- a/Tests/UnitTests/Core/Navigation/NavigationStateTests.cpp +++ b/Tests/UnitTests/Core/Navigation/NavigationStateTests.cpp @@ -11,6 +11,7 @@ #include "Acts/Detector/Portal.hpp" #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Navigation/NavigationState.hpp" +#include "Acts/Navigation/NavigationStateFillers.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" #include "Acts/Surfaces/Surface.hpp" diff --git a/Tests/UnitTests/Core/Navigation/NavigationStateUpdatorsTests.cpp b/Tests/UnitTests/Core/Navigation/NavigationStateUpdatorsTests.cpp index d994dcfb831..22dbebe3e42 100644 --- a/Tests/UnitTests/Core/Navigation/NavigationStateUpdatorsTests.cpp +++ b/Tests/UnitTests/Core/Navigation/NavigationStateUpdatorsTests.cpp @@ -10,6 +10,7 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Navigation/NavigationState.hpp" +#include "Acts/Navigation/NavigationStateFillers.hpp" #include "Acts/Navigation/NavigationStateUpdators.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" diff --git a/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp new file mode 100644 index 00000000000..faa060d7a91 --- /dev/null +++ b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp @@ -0,0 +1,87 @@ +// This file is part of the Acts project. +// +// Copyright (C) 2022 CERN for the benefit of the Acts project +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include "Acts/Detector/Portal.hpp" +#include "Acts/Detector/PortalHelper.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/GeometryContext.hpp" +#include "Acts/MagneticField/ConstantBField.hpp" +#include "Acts/MagneticField/MagneticFieldContext.hpp" +#include "Acts/Navigation/DetectorVolumeFinders.hpp" +#include "Acts/Navigation/NavigationState.hpp" +#include "Acts/Navigation/NextNavigator.hpp" +#include "Acts/Navigation/SurfaceCandidatesUpdators.hpp" +#include "Acts/Propagator/EigenStepper.hpp" +#include "Acts/Propagator/Propagator.hpp" +#include "Acts/Surfaces/PlaneSurface.hpp" +#include "Acts/Surfaces/RectangleBounds.hpp" +#include "Acts/Surfaces/Surface.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" + +#include + +Acts::GeometryContext tgContext; +Acts::MagneticFieldContext mfContext; + +BOOST_AUTO_TEST_SUITE(Experimental) + +BOOST_AUTO_TEST_CASE(NextNavigator) { + auto innerVolume = Acts::Experimental::DetectorVolumeFactory::construct( + Acts::Experimental::defaultPortalAndSubPortalGenerator(), tgContext, + "Inner Volume", Acts::Transform3::Identity(), + std::make_unique(3, 3, 3), + std::vector>(), + std::vector>(), + Acts::Experimental::allPortalsAndSurfaces()); + + auto detectorVolume = Acts::Experimental::DetectorVolumeFactory::construct( + Acts::Experimental::defaultPortalAndSubPortalGenerator(), tgContext, + "Detector Volume", Acts::Transform3::Identity(), + std::make_unique(10, 10, 10), + std::vector>(), + std::vector>( + {innerVolume}), + Acts::Experimental::allPortalsAndSurfaces()); + + auto detector = Acts::Experimental::Detector::makeShared( + "Detector", + std::vector>( + {detectorVolume}), + Acts::Experimental::tryAllVolumes()); + + using ActionListType = Acts::ActionList<>; + using AbortListType = Acts::AbortList<>; + + auto bField = std::make_shared( + Acts::Vector3(0, 0, 2 * Acts::UnitConstants::T)); + + Acts::Experimental::NextNavigator::Config navCfg; + navCfg.detector = detector.get(); + + auto stepper = Acts::EigenStepper<>(bField); + auto navigator = Acts::Experimental::NextNavigator( + navCfg, + Acts::getDefaultLogger("NextNavigator", Acts::Logging::Level::VERBOSE)); + auto options = Acts::PropagatorOptions( + tgContext, mfContext); + auto propagator = + Acts::Propagator, Acts::Experimental::NextNavigator>( + stepper, navigator, + Acts::getDefaultLogger("Propagator", Acts::Logging::Level::VERBOSE)); + + // define start parameters + Acts::Vector4 pos(0, 0, -5, 0); + Acts::Vector3 mom(0, 0, 10); + Acts::CurvilinearTrackParameters start(pos, mom, mom.norm(), +1); + // propagate to the cylinder surface + const auto& result = propagator.propagate(start, options).value(); +} + +BOOST_AUTO_TEST_SUITE_END() From 03dd571c835d00a90d9cfa82fe91d6d7f97cd360 Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 16:26:07 +0100 Subject: [PATCH 2/8] add missing files --- Core/include/Acts/Detector/ProtoDetector.hpp | 1 + Core/include/Acts/Navigation/DetectorVolumeUpdators.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Core/include/Acts/Detector/ProtoDetector.hpp b/Core/include/Acts/Detector/ProtoDetector.hpp index 1f75766d2be..6ca0e24efc3 100644 --- a/Core/include/Acts/Detector/ProtoDetector.hpp +++ b/Core/include/Acts/Detector/ProtoDetector.hpp @@ -24,6 +24,7 @@ namespace Acts { struct ProtoVolume; namespace Experimental { + class DetectorVolume; class Portal; diff --git a/Core/include/Acts/Navigation/DetectorVolumeUpdators.hpp b/Core/include/Acts/Navigation/DetectorVolumeUpdators.hpp index 795d313470d..b4e6ae46404 100644 --- a/Core/include/Acts/Navigation/DetectorVolumeUpdators.hpp +++ b/Core/include/Acts/Navigation/DetectorVolumeUpdators.hpp @@ -11,6 +11,7 @@ #include "Acts/Geometry/GeometryContext.hpp" #include "Acts/Navigation/NavigationDelegates.hpp" #include "Acts/Navigation/NavigationState.hpp" +#include "Acts/Navigation/NavigationStateFillers.hpp" #include "Acts/Navigation/NavigationStateUpdators.hpp" #include "Acts/Utilities/detail/Axis.hpp" #include "Acts/Utilities/detail/Grid.hpp" From 2cc18563c53da014c5a6e100f05fb7404afb0717 Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 17:02:08 +0100 Subject: [PATCH 3/8] fix format and docs --- Core/include/Acts/Navigation/NextNavigator.hpp | 18 +----------------- .../Navigation/SurfaceCandidatesUpdators.hpp | 3 ++- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp index d82925c891a..30fb5c84a60 100644 --- a/Core/include/Acts/Navigation/NextNavigator.hpp +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -68,14 +68,6 @@ class NextNavigator { /// Navigation state : a break has been detected bool navigationBreak = false; - /// Reset state - /// - /// @param geoContext is the geometry context - /// @param pos is the global position - /// @param dir is the momentum direction - /// @param navDir is the navigation direction - /// @param ssurface is the new starting surface - /// @param tsurface is the target surface void reset(const GeometryContext& /*geoContext*/, const Vector3& /*pos*/, const Vector3& /*dir*/, NavigationDirection /*navDir*/, const Surface* /*ssurface*/, const Surface* /*tsurface*/) { @@ -261,16 +253,8 @@ class NextNavigator { /// This checks if a navigation break had been triggered or navigator /// is misconfigured /// - /// @tparam propagator_state_t The state type of the propagagor - /// @tparam stepper_t The type of stepper used for the propagation - /// - /// @param [in,out] state is the propagation state object - /// @param [in] stepper Stepper in use - /// /// boolean return triggers exit to stepper - template - bool inactive(propagator_state_t& /*state*/, - const stepper_t& /*stepper*/) const { + bool inactive() const { if (m_cfg.detector == nullptr) { return true; } diff --git a/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp b/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp index ba1814d4ab7..baac0656a17 100644 --- a/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp +++ b/Core/include/Acts/Navigation/SurfaceCandidatesUpdators.hpp @@ -43,7 +43,8 @@ inline static void updateCandidates(const GeometryContext& gctx, (c.surface != nullptr) ? (*c.surface) : (c.portal->surface()); // Get the intersection @todo make a templated intersector - auto sIntersection = sRep.intersect(gctx, position, direction, c.boundaryCheck); + auto sIntersection = + sRep.intersect(gctx, position, direction, c.boundaryCheck); // Re-order and swap if necessary if (sIntersection.intersection.pathLength + s_onSurfaceTolerance < nState.overstepTolerance and From be3f952919543c48458d4b13f32084f29691305e Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 17:28:33 +0100 Subject: [PATCH 4/8] fix --- Core/include/Acts/Navigation/NextNavigator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp index 30fb5c84a60..c9c48681c36 100644 --- a/Core/include/Acts/Navigation/NextNavigator.hpp +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -102,7 +102,7 @@ class NextNavigator { auto& nState = state.navigation; fillNavigationState(state, stepper, nState); - if (inactive(state, stepper)) { + if (inactive()) { ACTS_VERBOSE("navigator inactive"); return; } @@ -175,7 +175,7 @@ class NextNavigator { auto& nState = state.navigation; - if (inactive(state, stepper)) { + if (inactive()) { ACTS_VERBOSE("navigator inactive"); return; } From 58d95cc3816edb64ef6cd3cc75b86ccb72cb1086 Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 19:38:26 +0100 Subject: [PATCH 5/8] fix --- Core/include/Acts/Navigation/NextNavigator.hpp | 2 +- Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp index c9c48681c36..7be372e5957 100644 --- a/Core/include/Acts/Navigation/NextNavigator.hpp +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -85,7 +85,7 @@ class NextNavigator { explicit NextNavigator(Config cfg, std::shared_ptr _logger = getDefaultLogger("NextNavigator", Logging::Level::INFO)) - : m_cfg{std::move(cfg)}, m_logger{std::move(_logger)} {} + : m_cfg{cfg}, m_logger{std::move(_logger)} {} /// @brief Navigator status call /// diff --git a/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp index faa060d7a91..66c933b5aee 100644 --- a/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp +++ b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(NextNavigator) { Acts::Vector3 mom(0, 0, 10); Acts::CurvilinearTrackParameters start(pos, mom, mom.norm(), +1); // propagate to the cylinder surface - const auto& result = propagator.propagate(start, options).value(); + propagator.propagate(start, options).value(); } BOOST_AUTO_TEST_SUITE_END() From 3a389494e5634c9784d9bd5c1b1f042c079eb6d5 Mon Sep 17 00:00:00 2001 From: andiwand Date: Thu, 9 Mar 2023 19:40:04 +0100 Subject: [PATCH 6/8] minor --- Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp index 66c933b5aee..6c7a2db64ba 100644 --- a/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp +++ b/Tests/UnitTests/Core/Navigation/NextNavigatorTests.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(NextNavigator) { Acts::Vector3 mom(0, 0, 10); Acts::CurvilinearTrackParameters start(pos, mom, mom.norm(), +1); // propagate to the cylinder surface - propagator.propagate(start, options).value(); + propagator.propagate(start, options); } BOOST_AUTO_TEST_SUITE_END() From 97e80b5fc55c5a9b88a5bb5ece2f266f87b5ceca Mon Sep 17 00:00:00 2001 From: andiwand Date: Wed, 15 Mar 2023 11:09:12 +0100 Subject: [PATCH 7/8] add some target doc --- Core/include/Acts/Navigation/NextNavigator.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp index 7be372e5957..9a4a00ae2cf 100644 --- a/Core/include/Acts/Navigation/NextNavigator.hpp +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -163,6 +163,9 @@ class NextNavigator { /// @brief Navigator target call /// + /// This will invalide the current surface and current portal in order + /// to navigate to the next ones. + /// /// @tparam propagator_state_t is the type of Propagatgor state /// @tparam stepper_t is the used type of the Stepper by the Propagator /// From 2ed12dae6398fb31e87deeda9b0c3d7c6ab449e5 Mon Sep 17 00:00:00 2001 From: andiwand Date: Wed, 15 Mar 2023 11:19:57 +0100 Subject: [PATCH 8/8] improve logging --- .../include/Acts/Navigation/NextNavigator.hpp | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/Core/include/Acts/Navigation/NextNavigator.hpp b/Core/include/Acts/Navigation/NextNavigator.hpp index 9a4a00ae2cf..c1f829cc9df 100644 --- a/Core/include/Acts/Navigation/NextNavigator.hpp +++ b/Core/include/Acts/Navigation/NextNavigator.hpp @@ -103,7 +103,8 @@ class NextNavigator { fillNavigationState(state, stepper, nState); if (inactive()) { - ACTS_VERBOSE("navigator inactive"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "navigator inactive"); return; } @@ -113,7 +114,9 @@ class NextNavigator { } if (nState.surfaceCandidate == nState.surfaceCandidates.end()) { - ACTS_VERBOSE("no surface candidates - waiting for target call"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) + << "no surface candidates - waiting for target call"); return; } @@ -129,7 +132,9 @@ class NextNavigator { nextSurface = &nextPortal->surface(); isPortal = true; } else { - ACTS_ERROR("panic: not a surface not a portal - what is it?"); + ACTS_ERROR(volInfo(state) + << posInfo(state, stepper) + << "panic: not a surface not a portal - what is it?"); return; } @@ -139,22 +144,27 @@ class NextNavigator { // Check if we are at a surface if (surfaceStatus == Intersection3D::Status::onSurface) { - ACTS_VERBOSE("landed on surface"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "landed on surface"); if (isPortal) { - ACTS_VERBOSE("this is a portal, storing it."); + ACTS_VERBOSE(volInfo(state) << posInfo(state, stepper) + << "this is a portal, storing it."); nState.currentPortal = nextPortal; - ACTS_VERBOSE("current portal set to " + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "current portal set to " << nState.currentPortal->surface().geometryId()); } else { - ACTS_VERBOSE("this is a surface, storing it."); + ACTS_VERBOSE(volInfo(state) << posInfo(state, stepper) + << "this is a surface, storing it."); // If we are on the surface pointed at by the iterator, we can make // it the current one to pass it to the other actors nState.currentSurface = nextSurface; - ACTS_VERBOSE("current surface set to " + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "current surface set to " << nState.currentSurface->geometryId()); ++nState.surfaceCandidate; } @@ -179,7 +189,8 @@ class NextNavigator { auto& nState = state.navigation; if (inactive()) { - ACTS_VERBOSE("navigator inactive"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "navigator inactive"); return; } @@ -188,9 +199,11 @@ class NextNavigator { } if (nState.currentSurface != nullptr) { - ACTS_VERBOSE("stepping through surface"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "stepping through surface"); } else if (nState.currentPortal != nullptr) { - ACTS_VERBOSE("stepping through portal"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "stepping through portal"); nState.surfaceCandidates.clear(); nState.surfaceCandidate = nState.surfaceCandidates.end(); @@ -204,6 +217,7 @@ class NextNavigator { ++nState.surfaceCandidate) { // Screen output how much is left to try ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << std::distance(nState.surfaceCandidate, nState.surfaceCandidates.end()) << " out of " << nState.surfaceCandidates.size() @@ -213,13 +227,17 @@ class NextNavigator { const auto& surface = (c.surface != nullptr) ? (*c.surface) : (c.portal->surface()); // Screen output which surface you are on - ACTS_VERBOSE("Next surface candidate will be " << surface.geometryId()); + ACTS_VERBOSE(volInfo(state) << posInfo(state, stepper) + << "next surface candidate will be " + << surface.geometryId()); // Estimate the surface status bool boundaryCheck = c.boundaryCheck; auto surfaceStatus = stepper.updateSurfaceStatus(state.stepping, surface, boundaryCheck, logger()); if (surfaceStatus == Intersection3D::Status::reachable) { - ACTS_VERBOSE("Surface reachable, step size updated to " + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) + << "surface reachable, step size updated to " << stepper.outputStepSize(state.stepping)); break; } @@ -328,12 +346,14 @@ class NextNavigator { state.geoContext, nState.position); if (nState.currentVolume != nullptr) { - ACTS_VERBOSE(volInfo(state) << "switched detector volume"); + ACTS_VERBOSE(volInfo(state) + << posInfo(state, stepper) << "switched detector volume"); } } if (nState.currentVolume == nullptr) { - ACTS_ERROR("panic: no current volume"); + ACTS_ERROR(volInfo(state) + << posInfo(state, stepper) << "panic: no current volume"); return; } @@ -349,7 +369,8 @@ class NextNavigator { nState.charge = stepper.charge(state.stepping); auto fieldResult = stepper.getField(state.stepping, nState.position); if (!fieldResult.ok()) { - ACTS_ERROR("could not read from the magnetic field"); + ACTS_ERROR(volInfo(state) << posInfo(state, stepper) + << "could not read from the magnetic field"); } nState.magneticField = *fieldResult; }