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