File indexing completed on 2026-05-24 07:35:38
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/EventData/ParticleHypothesis.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/MagneticField/ConstantBField.hpp"
0015 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0016 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0017 #include "Acts/Propagator/Propagator.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include "ActsTests/CommonHelpers/BenchmarkTools.hpp"
0020
0021 #include <iostream>
0022
0023 #include <boost/program_options.hpp>
0024
0025 namespace ActsTests {
0026
0027 namespace po = boost::program_options;
0028 using namespace Acts;
0029 using namespace Acts::UnitLiterals;
0030
0031 struct BenchmarkStepper {
0032 unsigned int toys{};
0033 double ptInGeV{};
0034 double BzInT{};
0035 double maxPathInM{};
0036 unsigned int lvl{};
0037 bool withCov{};
0038
0039 std::optional<int> parseOptions(int argc, char* argv[]) {
0040 try {
0041 po::options_description desc("Allowed options");
0042
0043 desc.add_options()
0044 ("help", "produce help message")
0045 ("toys",po::value<unsigned int>(&toys)->default_value(20000),"number of tracks to propagate")
0046 ("pT",po::value<double>(&ptInGeV)->default_value(1),"transverse momentum in GeV")
0047 ("B",po::value<double>(&BzInT)->default_value(2),"z-component of B-field in T")
0048 ("path",po::value<double>(&maxPathInM)->default_value(5),"maximum path length in m")
0049 ("cov",po::value<bool>(&withCov)->default_value(true),"propagation with covariance matrix")
0050 ("verbose",po::value<unsigned int>(&lvl)->default_value(Logging::INFO),"logging level");
0051
0052 po::variables_map vm;
0053 po::store(po::parse_command_line(argc, argv, desc), vm);
0054 po::notify(vm);
0055
0056 if (vm.contains("help")) {
0057 std::cout << desc << std::endl;
0058 return 0;
0059 }
0060 } catch (std::exception& e) {
0061 std::cerr << "error: " << e.what() << std::endl;
0062 return 1;
0063 }
0064
0065 return std::nullopt;
0066 }
0067
0068 std::unique_ptr<MagneticFieldProvider> makeField() const {
0069 return std::make_unique<ConstantBField>(
0070 Vector3{0, 0, BzInT * UnitConstants::T});
0071 }
0072
0073 template <typename Stepper>
0074 void run(Stepper stepper, const std::string& name) const {
0075 using Propagator = Propagator<Stepper>;
0076 using PropagatorOptions = typename Propagator::template Options<>;
0077 using Covariance = BoundMatrix;
0078
0079
0080 GeometryContext tgContext = GeometryContext::dangerouslyDefaultConstruct();
0081 MagneticFieldContext mfContext = MagneticFieldContext();
0082
0083 ACTS_LOCAL_LOGGER(getDefaultLogger(name, Logging::Level(lvl)));
0084
0085
0086 ACTS_INFO("propagating " << toys << " tracks with pT = " << ptInGeV
0087 << "GeV in a " << BzInT << "T B-field");
0088
0089 Propagator propagator(std::move(stepper));
0090
0091 PropagatorOptions options(tgContext, mfContext);
0092 options.pathLimit = maxPathInM * UnitConstants::m;
0093
0094 Vector4 pos4(0, 0, 0, 0);
0095 Vector3 dir(1, 0, 0);
0096 Covariance cov;
0097
0098 cov << 10_mm, 0, 0, 0, 0, 0,
0099 0, 10_mm, 0, 0, 0, 0,
0100 0, 0, 1, 0, 0, 0,
0101 0, 0, 0, 1, 0, 0,
0102 0, 0, 0, 0, 1_e / 10_GeV, 0,
0103 0, 0, 0, 0, 0, 0;
0104
0105
0106 std::optional<Covariance> covOpt = std::nullopt;
0107 if (withCov) {
0108 covOpt = cov;
0109 }
0110 BoundTrackParameters pars = BoundTrackParameters::createCurvilinear(
0111 pos4, dir, +1 / ptInGeV, covOpt, ParticleHypothesis::pion());
0112
0113 double totalPathLength = 0;
0114 std::size_t numSteps = 0;
0115 std::size_t numStepTrials = 0;
0116 std::size_t numIters = 0;
0117 const auto propagationBenchResult = microBenchmark(
0118 [&] {
0119 auto state = propagator.makeState(options);
0120 auto initRes = propagator.initialize(state, pars);
0121 if (!initRes.ok()) {
0122 ACTS_ERROR("initialization failed: " << initRes.error());
0123 return;
0124 }
0125 auto tmp = propagator.propagate(state);
0126 auto r = propagator.makeResult(state, tmp, options, true).value();
0127 if (totalPathLength == 0.) {
0128 ACTS_DEBUG("reached position "
0129 << r.endParameters->position(tgContext).transpose()
0130 << " in " << r.steps << " steps");
0131 }
0132 totalPathLength += r.pathLength;
0133 numSteps += r.steps;
0134 numStepTrials += state.stepping.nStepTrials;
0135 ++numIters;
0136 },
0137 1, toys);
0138
0139 ACTS_INFO("Execution stats: " << propagationBenchResult);
0140 ACTS_INFO("average path length = " << totalPathLength / numIters / 1_mm
0141 << "mm");
0142 ACTS_INFO("average number of steps = " << 1.0 * numSteps / numIters);
0143 ACTS_INFO("step efficiency = " << 1.0 * numSteps / numStepTrials);
0144 }
0145 };
0146
0147 }