File indexing completed on 2025-09-17 08:01:45
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Direction.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/EventData/TrackParameters.hpp"
0015 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp"
0016 #include "Acts/MagneticField/NullBField.hpp"
0017 #include "Acts/Propagator/ConstrainedStep.hpp"
0018 #include "Acts/Propagator/PropagatorTraits.hpp"
0019 #include "Acts/Propagator/StepperOptions.hpp"
0020 #include "Acts/Propagator/StepperStatistics.hpp"
0021 #include "Acts/Propagator/detail/SteppingHelper.hpp"
0022 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0023 #include "Acts/Surfaces/Surface.hpp"
0024 #include "Acts/Utilities/Intersection.hpp"
0025 #include "Acts/Utilities/Logger.hpp"
0026 #include "Acts/Utilities/MathHelpers.hpp"
0027 #include "Acts/Utilities/Result.hpp"
0028
0029 #include <cmath>
0030 #include <string>
0031 #include <tuple>
0032
0033 namespace Acts {
0034
0035 class IVolumeMaterial;
0036
0037
0038
0039
0040
0041
0042 class StraightLineStepper {
0043 public:
0044 using Jacobian = BoundMatrix;
0045 using Covariance = BoundSquareMatrix;
0046 using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
0047 using BField = NullBField;
0048
0049 struct Config {};
0050
0051 struct Options : public StepperPlainOptions {
0052 Options(const GeometryContext& gctx, const MagneticFieldContext& mctx)
0053 : StepperPlainOptions(gctx, mctx) {}
0054
0055 void setPlainOptions(const StepperPlainOptions& options) {
0056 static_cast<StepperPlainOptions&>(*this) = options;
0057 }
0058 };
0059
0060
0061
0062 struct State {
0063
0064
0065
0066
0067
0068 explicit State(const Options& optionsIn) : options(optionsIn) {}
0069
0070 Options options;
0071
0072
0073 BoundToFreeMatrix jacToGlobal = BoundToFreeMatrix::Zero();
0074
0075
0076 FreeMatrix jacTransport = FreeMatrix::Identity();
0077
0078
0079 Jacobian jacobian = Jacobian::Identity();
0080
0081
0082 FreeVector derivative = FreeVector::Zero();
0083
0084
0085 FreeVector pars = FreeVector::Zero();
0086
0087
0088 ParticleHypothesis particleHypothesis = ParticleHypothesis::pion();
0089
0090
0091 bool covTransport = false;
0092 Covariance cov = Covariance::Zero();
0093 std::optional<FreeMatrix> additionalFreeCovariance = std::nullopt;
0094
0095
0096 double pathAccumulated = 0.;
0097
0098
0099 std::size_t nSteps = 0;
0100
0101
0102 std::size_t nStepTrials = 0;
0103
0104
0105 ConstrainedStep stepSize;
0106
0107
0108 double previousStepSize = 0.;
0109
0110
0111 StepperStatistics statistics;
0112 };
0113
0114 State makeState(const Options& options) const;
0115
0116 void initialize(State& state, const BoundTrackParameters& par) const;
0117
0118 void initialize(State& state, const BoundVector& boundParams,
0119 const std::optional<BoundMatrix>& cov,
0120 ParticleHypothesis particleHypothesis,
0121 const Surface& surface) const;
0122
0123
0124 Result<Vector3> getField(State& , const Vector3& ) const {
0125
0126 return Result<Vector3>::success({0., 0., 0.});
0127 }
0128
0129
0130
0131
0132 Vector3 position(const State& state) const {
0133 return state.pars.template segment<3>(eFreePos0);
0134 }
0135
0136
0137
0138
0139 Vector3 direction(const State& state) const {
0140 return state.pars.template segment<3>(eFreeDir0);
0141 }
0142
0143
0144
0145
0146 double qOverP(const State& state) const { return state.pars[eFreeQOverP]; }
0147
0148
0149
0150
0151 double absoluteMomentum(const State& state) const {
0152 return particleHypothesis(state).extractMomentum(qOverP(state));
0153 }
0154
0155
0156
0157
0158 Vector3 momentum(const State& state) const {
0159 return absoluteMomentum(state) * direction(state);
0160 }
0161
0162
0163
0164
0165 double charge(const State& state) const {
0166 return particleHypothesis(state).extractCharge(qOverP(state));
0167 }
0168
0169
0170
0171
0172 const ParticleHypothesis& particleHypothesis(const State& state) const {
0173 return state.particleHypothesis;
0174 }
0175
0176
0177
0178
0179 double time(const State& state) const { return state.pars[eFreeTime]; }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196 IntersectionStatus updateSurfaceStatus(
0197 State& state, const Surface& surface, std::uint8_t index,
0198 Direction navDir, const BoundaryTolerance& boundaryTolerance,
0199 double surfaceTolerance, ConstrainedStep::Type stype,
0200 const Logger& logger = getDummyLogger()) const {
0201 return detail::updateSingleSurfaceStatus<StraightLineStepper>(
0202 *this, state, surface, index, navDir, boundaryTolerance,
0203 surfaceTolerance, stype, logger);
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 template <typename object_intersection_t>
0216 void updateStepSize(State& state, const object_intersection_t& oIntersection,
0217 Direction direction, ConstrainedStep::Type stype) const {
0218 (void)direction;
0219 double stepSize = oIntersection.pathLength();
0220 updateStepSize(state, stepSize, stype);
0221 }
0222
0223
0224
0225
0226
0227
0228 void updateStepSize(State& state, double stepSize,
0229 ConstrainedStep::Type stype) const {
0230 state.previousStepSize = state.stepSize.value();
0231 state.stepSize.update(stepSize, stype);
0232 }
0233
0234
0235
0236
0237
0238 double getStepSize(const State& state, ConstrainedStep::Type stype) const {
0239 return state.stepSize.value(stype);
0240 }
0241
0242
0243
0244
0245
0246 void releaseStepSize(State& state, ConstrainedStep::Type stype) const {
0247 state.stepSize.release(stype);
0248 }
0249
0250
0251
0252
0253 std::string outputStepSize(const State& state) const {
0254 return state.stepSize.toString();
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 Result<BoundState> boundState(
0272 State& state, const Surface& surface, bool transportCov = true,
0273 const FreeToBoundCorrection& freeToBoundCorrection =
0274 FreeToBoundCorrection(false)) const;
0275
0276
0277
0278
0279
0280
0281
0282
0283 bool prepareCurvilinearState(State& state) const {
0284
0285 if (state.pathAccumulated != 0) {
0286 return true;
0287 }
0288
0289
0290 state.derivative.template head<3>() = direction(state);
0291
0292 state.derivative(eFreeTime) = fastHypot(
0293 1., state.particleHypothesis.mass() / absoluteMomentum(state));
0294
0295 state.derivative.template segment<3>(4) = Acts::Vector3::Zero().transpose();
0296
0297 state.derivative(eFreeQOverP) = 0.;
0298
0299 return true;
0300 }
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 BoundState curvilinearState(State& state, bool transportCov = true) const;
0314
0315
0316
0317
0318
0319
0320
0321
0322 void update(State& state, const FreeVector& freeParams,
0323 const BoundVector& boundParams, const Covariance& covariance,
0324 const Surface& surface) const;
0325
0326
0327
0328
0329
0330
0331
0332
0333 void update(State& state, const Vector3& uposition, const Vector3& udirection,
0334 double qop, double time) const;
0335
0336
0337
0338
0339
0340
0341 void transportCovarianceToCurvilinear(State& state) const;
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 void transportCovarianceToBound(
0356 State& state, const Surface& surface,
0357 const FreeToBoundCorrection& freeToBoundCorrection =
0358 FreeToBoundCorrection(false)) const;
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 Result<double> step(State& state, Direction propDir,
0371 const IVolumeMaterial* material) const {
0372 (void)material;
0373
0374
0375 const auto h = state.stepSize.value() * propDir;
0376 const auto m = state.particleHypothesis.mass();
0377 const auto p = absoluteMomentum(state);
0378
0379 const auto dtds = fastHypot(1., m / p);
0380
0381 Vector3 dir = direction(state);
0382 state.pars.template segment<3>(eFreePos0) += h * dir;
0383 state.pars[eFreeTime] += h * dtds;
0384
0385
0386 if (state.covTransport) {
0387
0388 FreeMatrix D = FreeMatrix::Identity();
0389 D.block<3, 3>(0, 4) = ActsSquareMatrix<3>::Identity() * h;
0390
0391
0392 D(3, 7) = h * m * m * state.pars[eFreeQOverP] / dtds;
0393
0394 state.derivative(3) = dtds;
0395
0396 state.jacTransport = D * state.jacTransport;
0397 state.derivative.template head<3>() = dir;
0398 }
0399
0400
0401 state.pathAccumulated += h;
0402 ++state.nSteps;
0403 ++state.nStepTrials;
0404
0405 ++state.statistics.nAttemptedSteps;
0406 ++state.statistics.nSuccessfulSteps;
0407 if (propDir != Direction::fromScalarZeroAsPositive(h)) {
0408 ++state.statistics.nReverseSteps;
0409 }
0410 state.statistics.pathLength += h;
0411 state.statistics.absolutePathLength += std::abs(h);
0412
0413 return h;
0414 }
0415 };
0416
0417 template <>
0418 struct SupportsBoundParameters<StraightLineStepper> : public std::true_type {};
0419
0420 }