Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:46

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/Units.hpp"
0014 #include "Acts/EventData/TrackParameters.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/MagneticField/ConstantBField.hpp"
0017 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0018 #include "Acts/Propagator/ActorList.hpp"
0019 #include "Acts/Propagator/DirectNavigator.hpp"
0020 #include "Acts/Propagator/EigenStepper.hpp"
0021 #include "Acts/Propagator/MaterialInteractor.hpp"
0022 #include "Acts/Propagator/Navigator.hpp"
0023 #include "Acts/Propagator/Propagator.hpp"
0024 #include "Acts/Propagator/StandardAborters.hpp"
0025 #include "Acts/Propagator/SurfaceCollector.hpp"
0026 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0027 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0028 
0029 #include <cmath>
0030 #include <iostream>
0031 #include <memory>
0032 #include <numbers>
0033 #include <random>
0034 #include <utility>
0035 #include <vector>
0036 
0037 namespace Acts {
0038 class Surface;
0039 }  // namespace Acts
0040 
0041 namespace bdata = boost::unit_test::data;
0042 using namespace Acts::UnitLiterals;
0043 
0044 namespace Acts::Test {
0045 
0046 // Create a test context
0047 GeometryContext tgContext = GeometryContext();
0048 MagneticFieldContext mfContext = MagneticFieldContext();
0049 
0050 CylindricalTrackingGeometry cGeometry(tgContext);
0051 auto tGeometry = cGeometry();
0052 
0053 // Create a navigator for this tracking geometry
0054 Navigator navigator({tGeometry});
0055 DirectNavigator dnavigator;
0056 
0057 using BField = ConstantBField;
0058 using Stepper = EigenStepper<>;
0059 using ReferencePropagator = Propagator<Stepper, Navigator>;
0060 using DirectPropagator = Propagator<Stepper, DirectNavigator>;
0061 
0062 const double Bz = 2_T;
0063 auto bField = std::make_shared<BField>(Vector3{0, 0, Bz});
0064 Stepper estepper(bField);
0065 Stepper dstepper(bField);
0066 
0067 ReferencePropagator rpropagator(std::move(estepper), std::move(navigator));
0068 DirectPropagator dpropagator(std::move(dstepper), std::move(dnavigator));
0069 
0070 const int ntests = 1000;
0071 const int skip = 0;
0072 bool referenceTiming = false;
0073 bool oversteppingTest = false;
0074 double oversteppingMaxStepSize = 1_mm;
0075 
0076 /// The actual test method that runs the test
0077 /// can be used with several propagator types
0078 ///
0079 /// @tparam rpropagator_t is the reference propagator type
0080 /// @tparam dpropagator_t is the direct propagator type
0081 ///
0082 /// @param rprop is the reference propagator instance
0083 /// @param dprop is the direct propagator instance
0084 /// @param pT the transverse momentum
0085 /// @param phi the azimuthal angle of the track at creation
0086 /// @param theta the polar angle of the track at creation
0087 /// @param charge is the charge of the particle
0088 /// @param index is the run index from the test
0089 template <typename rpropagator_t, typename dpropagator_t>
0090 void runTest(const rpropagator_t& rprop, const dpropagator_t& dprop, double pT,
0091              double phi, double theta, int charge, int index) {
0092   double dcharge = -1 + 2 * charge;
0093 
0094   if (index < skip) {
0095     return;
0096   }
0097 
0098   // Define start parameters from ranom input
0099   double p = pT / sin(theta);
0100   CurvilinearTrackParameters start(Vector4(0, 0, 0, 0), phi, theta, dcharge / p,
0101                                    std::nullopt, ParticleHypothesis::pion());
0102 
0103   using EndOfWorld = EndOfWorldReached;
0104 
0105   // Action list and abort list
0106   using ReferenceActorList =
0107       ActorList<MaterialInteractor, SurfaceCollector<>, EndOfWorld>;
0108 
0109   // Options definition
0110   using Options = typename rpropagator_t::template Options<ReferenceActorList>;
0111   Options pOptions(tgContext, mfContext);
0112   if (oversteppingTest) {
0113     pOptions.stepping.maxStepSize = oversteppingMaxStepSize;
0114   }
0115 
0116   // Surface collector configuration
0117   auto& sCollector = pOptions.actorList.template get<SurfaceCollector<>>();
0118   sCollector.selector.selectSensitive = true;
0119   sCollector.selector.selectMaterial = true;
0120 
0121   // Result is immediately used, non-valid result would indicate failure
0122   const auto& pResult = rprop.propagate(start, pOptions).value();
0123   auto& cSurfaces = pResult.template get<SurfaceCollector<>::result_type>();
0124   auto& cMaterial = pResult.template get<MaterialInteractor::result_type>();
0125   const Surface& destination = pResult.endParameters->referenceSurface();
0126 
0127   std::cout << " - the standard navigator yielded "
0128             << cSurfaces.collected.size() << " collected surfaces" << std::endl;
0129 
0130   if (!referenceTiming) {
0131     // Create the surface sequence
0132     std::vector<const Surface*> surfaceSequence;
0133     surfaceSequence.reserve(cSurfaces.collected.size());
0134     for (auto& cs : cSurfaces.collected) {
0135       surfaceSequence.push_back(cs.surface);
0136     }
0137 
0138     // Action list for direct navigator with its initializer
0139     using DirectActorList = ActorList<MaterialInteractor, SurfaceCollector<>>;
0140 
0141     // Direct options definition
0142     using DirectOptions =
0143         typename dpropagator_t::template Options<DirectActorList>;
0144     DirectOptions dOptions(tgContext, mfContext);
0145     // Set the surface sequence
0146     dOptions.navigation.surfaces = surfaceSequence;
0147     // Surface collector configuration
0148     auto& dCollector = dOptions.actorList.template get<SurfaceCollector<>>();
0149     dCollector.selector.selectSensitive = true;
0150     dCollector.selector.selectMaterial = true;
0151 
0152     // Now redo the propagation with the direct propagator
0153     const auto& ddResult =
0154         dprop.propagate(start, destination, dOptions).value();
0155     auto& ddSurfaces = ddResult.template get<SurfaceCollector<>::result_type>();
0156     auto& ddMaterial = ddResult.template get<MaterialInteractor::result_type>();
0157 
0158     // CHECK if you have as many surfaces collected as the default navigator
0159     BOOST_CHECK_EQUAL(cSurfaces.collected.size(), ddSurfaces.collected.size());
0160     CHECK_CLOSE_REL(cMaterial.materialInX0, ddMaterial.materialInX0, 1e-3);
0161 
0162     // Now redo the propagation with the direct propagator - without destination
0163     const auto& dwResult = dprop.propagate(start, dOptions).value();
0164     auto& dwSurfaces = dwResult.template get<SurfaceCollector<>::result_type>();
0165 
0166     // CHECK if you have as many surfaces collected as the default navigator
0167     BOOST_CHECK_EQUAL(cSurfaces.collected.size(), dwSurfaces.collected.size());
0168   }
0169 }
0170 
0171 // This test case checks that no segmentation fault appears
0172 // - this tests the collection of surfaces
0173 BOOST_DATA_TEST_CASE(
0174     test_direct_navigator,
0175     bdata::random((bdata::engine = std::mt19937(), bdata::seed = 20,
0176                    bdata::distribution = std::uniform_real_distribution<double>(
0177                        0.15_GeV, 10_GeV))) ^
0178         bdata::random(
0179             (bdata::engine = std::mt19937(), bdata::seed = 21,
0180              bdata::distribution = std::uniform_real_distribution<double>(
0181                  -std::numbers::pi, std::numbers::pi))) ^
0182         bdata::random(
0183             (bdata::engine = std::mt19937(), bdata::seed = 22,
0184              bdata::distribution = std::uniform_real_distribution<double>(
0185                  1., std::numbers::pi - 1.))) ^
0186         bdata::random((bdata::engine = std::mt19937(), bdata::seed = 23,
0187                        bdata::distribution =
0188                            std::uniform_int_distribution<std::uint8_t>(0, 1))) ^
0189         bdata::xrange(ntests),
0190     pT, phi, theta, charge, index) {
0191   // Run the test
0192   runTest(rpropagator, dpropagator, pT, phi, theta, charge, index);
0193 }
0194 
0195 }  // namespace Acts::Test