Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-05 08:55:29

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/Units.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/MagneticField/ConstantBField.hpp"
0018 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0019 #include "Acts/Propagator/ActorList.hpp"
0020 #include "Acts/Propagator/EigenStepper.hpp"
0021 #include "Acts/Propagator/Propagator.hpp"
0022 #include "Acts/Propagator/StandardAborters.hpp"
0023 #include "Acts/Propagator/detail/LoopProtection.hpp"
0024 #include "Acts/Utilities/Logger.hpp"
0025 #include "Acts/Utilities/Result.hpp"
0026 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0027 
0028 #include <cmath>
0029 #include <limits>
0030 #include <memory>
0031 #include <numbers>
0032 #include <random>
0033 #include <string>
0034 #include <utility>
0035 
0036 namespace bdata = boost::unit_test::data;
0037 
0038 using namespace Acts;
0039 using namespace Acts::UnitLiterals;
0040 using namespace Acts::detail;
0041 
0042 namespace ActsTests {
0043 
0044 // Create a test context
0045 GeometryContext tgContext = GeometryContext();
0046 MagneticFieldContext mfContext = MagneticFieldContext();
0047 
0048 /// @brief mockup of stepping state
0049 struct SteppingState {
0050   /// Parameters
0051   Vector3 pos = Vector3(0., 0., 0.);
0052   Vector3 dir = Vector3(0., 0., 1);
0053   double p = 100_MeV;
0054 };
0055 
0056 /// @brief mockup of stepping state
0057 struct Stepper {
0058   Vector3 field = Vector3(0., 0., 2_T);
0059 
0060   /// Get the field for the stepping, it checks first if the access is still
0061   /// within the Cell, and updates the cell if necessary.
0062   ///
0063   /// @param [in,out] state is the propagation state associated with the track
0064   ///                 the magnetic field cell is used (and potentially
0065   ///                 updated)
0066   /// @param [in] pos is the field position
0067   Result<Vector3> getField(SteppingState& /*state*/,
0068                            const Vector3& /*pos*/) const {
0069     // get the field from the cell
0070     return Result<Vector3>::success(field);
0071   }
0072 
0073   /// Access method - position
0074   Vector3 position(const SteppingState& state) const { return state.pos; }
0075 
0076   /// Access method - direction
0077   Vector3 direction(const SteppingState& state) const { return state.dir; }
0078 
0079   /// Access method - momentum
0080   double absoluteMomentum(const SteppingState& state) const { return state.p; }
0081 };
0082 
0083 /// @brief mockup of navigation state
0084 struct NavigationState {
0085   bool navigationBreak = false;
0086 };
0087 
0088 /// @brief mockup of the Propagator Options
0089 struct Options {
0090   /// Absolute maximum path length
0091   double pathLimit = std::numeric_limits<double>::max();
0092   bool loopProtection = true;
0093   double loopFraction = 0.5;
0094   Direction direction = Direction::Forward();
0095 
0096   bool debug = false;
0097   std::string debugString;
0098   int debugMsgWidth = 60;
0099   int debugPfxWidth = 30;
0100 
0101   /// Contains: target aborters
0102   ActorList<PathLimitReached> abortList;
0103 
0104   const Logger& logger = getDummyLogger();
0105 };
0106 
0107 /// @brief mockup of propagtor state
0108 struct PropagatorState {
0109   /// Contains: stepping state
0110   SteppingState stepping;
0111   /// Contains: navigation state
0112   NavigationState navigation;
0113   /// Contains: options
0114   Options options;
0115 };
0116 
0117 BOOST_AUTO_TEST_SUITE(PropagatorSuite)
0118 
0119 // This test case checks that no segmentation fault appears
0120 // - this tests the collection of surfaces
0121 BOOST_DATA_TEST_CASE(
0122     loop_aborter_test,
0123     bdata::random((bdata::engine = std::mt19937(), bdata::seed = 21,
0124                    bdata::distribution = std::uniform_real_distribution<double>(
0125                        -std::numbers::pi, std::numbers::pi))) ^
0126         bdata::random(
0127             (bdata::engine = std::mt19937(), bdata::seed = 22,
0128              bdata::distribution = std::uniform_real_distribution<double>(
0129                  -std::numbers::pi, std::numbers::pi))) ^
0130         bdata::xrange(1),
0131     phi, deltaPhi, index) {
0132   (void)index;
0133   (void)deltaPhi;
0134 
0135   PropagatorState pState;
0136   pState.stepping.dir = Vector3(cos(phi), sin(phi), 0.);
0137   pState.stepping.p = 100_MeV;
0138 
0139   Stepper pStepper;
0140 
0141   auto& pathLimit = pState.options.abortList.get<PathLimitReached>();
0142   auto initialLimit = pathLimit.internalLimit;
0143 
0144   detail::setupLoopProtection(pState, pStepper, pathLimit, false,
0145                               *getDefaultLogger("LoopProt", Logging::INFO));
0146 
0147   auto updatedLimit =
0148       pState.options.abortList.get<PathLimitReached>().internalLimit;
0149   BOOST_CHECK_LT(updatedLimit, initialLimit);
0150 }
0151 
0152 using BField = ConstantBField;
0153 using EigenStepper = EigenStepper<>;
0154 using EigenPropagator = Propagator<EigenStepper>;
0155 
0156 const int ntests = 100;
0157 const int skip = 0;
0158 
0159 // This test case checks that the propagator with loop LoopProtection
0160 // stops where expected
0161 BOOST_DATA_TEST_CASE(
0162     propagator_loop_protection_test,
0163     bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0164                    bdata::distribution = std::uniform_real_distribution<double>(
0165                        0.5_GeV, 10_GeV))) ^
0166         bdata::random(
0167             (bdata::engine = std::mt19937(), bdata::seed = 21,
0168              bdata::distribution = std::uniform_real_distribution<double>(
0169                  -std::numbers::pi, std::numbers::pi))) ^
0170         bdata::random(
0171             (bdata::engine = std::mt19937(), bdata::seed = 22,
0172              bdata::distribution = std::uniform_real_distribution<double>(
0173                  1., std::numbers::pi - 1.))) ^
0174         bdata::random((bdata::engine = std::mt19937(), bdata::seed = 23,
0175                        bdata::distribution =
0176                            std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0177         bdata::xrange(ntests),
0178     pT, phi, theta, charge, index) {
0179   if (index < skip) {
0180     return;
0181   }
0182 
0183   double px = pT * cos(phi);
0184   double py = pT * sin(phi);
0185   double pz = pT / tan(theta);
0186   double p = pT / sin(theta);
0187   double q = -1 + 2 * charge;
0188 
0189   const double Bz = 2_T;
0190   auto bField = std::make_shared<BField>(Vector3{0, 0, Bz});
0191   EigenStepper estepper(bField);
0192   EigenPropagator epropagator(std::move(estepper));
0193 
0194   // define start parameters
0195   BoundTrackParameters start = BoundTrackParameters::createCurvilinear(
0196       Vector4(0, 0, 0, 42), phi, theta, q / p, std::nullopt,
0197       ParticleHypothesis::pion());
0198 
0199   using PropagatorOptions = EigenPropagator::Options<ActorList<>>;
0200   PropagatorOptions options(tgContext, mfContext);
0201   options.maxSteps = 1e6;
0202   const auto& result = epropagator.propagate(start, options).value();
0203 
0204   // this test assumes state.options.loopFraction = 0.5
0205   CHECK_CLOSE_REL(px, -result.endParameters->momentum().x(), 1e-2);
0206   CHECK_CLOSE_REL(py, -result.endParameters->momentum().y(), 1e-2);
0207   CHECK_CLOSE_REL(pz, result.endParameters->momentum().z(), 1e-2);
0208 }
0209 
0210 BOOST_AUTO_TEST_SUITE_END()
0211 
0212 }  // namespace ActsTests