File indexing completed on 2025-11-18 08:54:43
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/EventData/TransformationHelpers.hpp"
0017 #include "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/MagneticField/MagneticFieldProvider.hpp"
0020 #include "Acts/Propagator/ConstrainedStep.hpp"
0021 #include "Acts/Propagator/NavigationTarget.hpp"
0022 #include "Acts/Propagator/StepperOptions.hpp"
0023 #include "Acts/Propagator/StepperStatistics.hpp"
0024 #include "Acts/Propagator/detail/SteppingHelper.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Utilities/Intersection.hpp"
0027 #include "Acts/Utilities/Result.hpp"
0028
0029 #include <cmath>
0030
0031 namespace Acts {
0032
0033 class IVolumeMaterial;
0034
0035
0036
0037
0038 class AtlasStepper {
0039 public:
0040
0041 using Jacobian = BoundMatrix;
0042
0043 using Covariance = BoundSquareMatrix;
0044
0045 using BoundState = std::tuple<BoundTrackParameters, Jacobian, double>;
0046
0047 struct Config {
0048 std::shared_ptr<const MagneticFieldProvider> bField;
0049 };
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 struct State {
0062
0063
0064
0065
0066
0067
0068 State(const Options& optionsIn, MagneticFieldProvider::Cache fieldCacheIn)
0069 : options(optionsIn), fieldCache(std::move(fieldCacheIn)) {}
0070
0071
0072 Options options;
0073
0074
0075 ParticleHypothesis particleHypothesis = ParticleHypothesis::pion();
0076
0077
0078
0079 bool state_ready = false;
0080
0081
0082 bool useJacobian = false;
0083
0084 double step = 0;
0085
0086 double maxPathLength = 0;
0087
0088 bool mcondition = false;
0089
0090 bool needgradient = false;
0091
0092 bool newfield = true;
0093
0094
0095 Vector3 field = Vector3::Zero();
0096
0097 std::array<double, 60> pVector{};
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 double parameters[eBoundSize] = {0., 0., 0., 0., 0., 0.};
0113
0114 const Covariance* covariance = nullptr;
0115
0116 Covariance cov = Covariance::Zero();
0117
0118 bool covTransport = false;
0119
0120 double jacobian[eBoundSize * eBoundSize] = {};
0121
0122
0123
0124 double pathAccumulated = 0.;
0125
0126
0127 std::size_t nSteps = 0;
0128
0129
0130 std::size_t nStepTrials = 0;
0131
0132
0133
0134 ConstrainedStep stepSize;
0135
0136
0137
0138 double previousStepSize = 0.;
0139
0140
0141
0142 MagneticFieldProvider::Cache fieldCache;
0143
0144
0145
0146 bool debug = false;
0147
0148 std::string debugString = "";
0149
0150 std::size_t debugPfxWidth = 30;
0151
0152 std::size_t debugMsgWidth = 50;
0153
0154
0155 StepperStatistics statistics;
0156 };
0157
0158
0159
0160 explicit AtlasStepper(std::shared_ptr<const MagneticFieldProvider> bField)
0161 : m_bField(std::move(bField)) {}
0162
0163
0164
0165 explicit AtlasStepper(const Config& config) : m_bField(config.bField) {}
0166
0167
0168
0169
0170 State makeState(const Options& options) const {
0171 State state{options, m_bField->makeCache(options.magFieldContext)};
0172 return state;
0173 }
0174
0175
0176
0177
0178 void initialize(State& state, const BoundTrackParameters& par) const {
0179 initialize(state, par.parameters(), par.covariance(),
0180 par.particleHypothesis(), par.referenceSurface());
0181 }
0182
0183
0184
0185
0186
0187
0188
0189 void initialize(State& state, const BoundVector& boundParams,
0190 const std::optional<BoundMatrix>& cov,
0191 ParticleHypothesis particleHypothesis,
0192 const Surface& surface) const {
0193 state.particleHypothesis = particleHypothesis;
0194
0195 state.pathAccumulated = 0;
0196 state.nSteps = 0;
0197 state.nStepTrials = 0;
0198 state.stepSize = ConstrainedStep();
0199 state.stepSize.setAccuracy(state.options.initialStepSize);
0200 state.stepSize.setUser(state.options.maxStepSize);
0201 state.previousStepSize = 0;
0202 state.statistics = StepperStatistics();
0203
0204
0205
0206
0207
0208 const auto& Vp = boundParams;
0209
0210 double Sf = std::sin(Vp[eBoundPhi]);
0211 double Cf = std::cos(Vp[eBoundPhi]);
0212 double Se = std::sin(Vp[eBoundTheta]);
0213 double Ce = std::cos(Vp[eBoundTheta]);
0214
0215 const Vector3 dir = {Cf * Se, Sf * Se, Ce};
0216 const auto pos = surface.localToGlobal(
0217 state.options.geoContext, boundParams.segment<2>(eBoundLoc0), dir);
0218
0219 double* pVector = state.pVector.data();
0220
0221 pVector[0] = pos[ePos0];
0222 pVector[1] = pos[ePos1];
0223 pVector[2] = pos[ePos2];
0224 pVector[3] = boundParams[eBoundTime];
0225 pVector[4] = dir[ePos0];
0226 pVector[5] = dir[ePos1];
0227 pVector[6] = dir[ePos2];
0228 pVector[7] = Vp[eBoundQOverP];
0229
0230
0231 if (std::abs(pVector[7]) < .000000000000001) {
0232 pVector[7] < 0. ? pVector[7] = -.000000000000001
0233 : pVector[7] = .000000000000001;
0234 }
0235
0236
0237 state.covTransport = cov.has_value();
0238 if (state.covTransport) {
0239
0240 state.covariance = new BoundSquareMatrix(*cov);
0241 state.useJacobian = true;
0242 const auto transform =
0243 surface.referenceFrame(state.options.geoContext, pos, dir);
0244
0245 pVector[8] = transform(0, eBoundLoc0);
0246 pVector[16] = transform(0, eBoundLoc1);
0247 pVector[24] = 0.;
0248 pVector[32] = 0.;
0249 pVector[40] = 0.;
0250 pVector[48] = 0.;
0251
0252 pVector[9] = transform(1, eBoundLoc0);
0253 pVector[17] = transform(1, eBoundLoc1);
0254 pVector[25] = 0.;
0255 pVector[33] = 0.;
0256 pVector[41] = 0.;
0257 pVector[49] = 0.;
0258
0259 pVector[10] = transform(2, eBoundLoc0);
0260 pVector[18] = transform(2, eBoundLoc1);
0261 pVector[26] = 0.;
0262 pVector[34] = 0.;
0263 pVector[42] = 0.;
0264 pVector[50] = 0.;
0265
0266 pVector[11] = 0.;
0267 pVector[19] = 0.;
0268 pVector[27] = 0.;
0269 pVector[35] = 0.;
0270 pVector[43] = 0.;
0271 pVector[51] = 1.;
0272
0273 pVector[12] = 0.;
0274 pVector[20] = 0.;
0275 pVector[28] = -Sf * Se;
0276 pVector[36] = Cf * Ce;
0277 pVector[44] = 0.;
0278 pVector[52] = 0.;
0279
0280 pVector[13] = 0.;
0281 pVector[21] = 0.;
0282 pVector[29] = Cf * Se;
0283 pVector[37] = Sf * Ce;
0284 pVector[45] = 0.;
0285 pVector[53] = 0.;
0286
0287 pVector[14] = 0.;
0288 pVector[22] = 0.;
0289 pVector[30] = 0.;
0290 pVector[38] = -Se;
0291 pVector[46] = 0.;
0292 pVector[54] = 0.;
0293
0294 pVector[15] = 0.;
0295 pVector[23] = 0.;
0296 pVector[31] = 0.;
0297 pVector[39] = 0.;
0298 pVector[47] = 1.;
0299 pVector[55] = 0.;
0300
0301 pVector[56] = 0.;
0302 pVector[57] = 0.;
0303 pVector[58] = 0.;
0304 pVector[59] = 0.;
0305
0306
0307
0308 if (surface.type() == Surface::Disc) {
0309 double lCf = std::cos(Vp[1]);
0310 double lSf = std::sin(Vp[1]);
0311 double Ax[3] = {transform(0, 0), transform(1, 0), transform(2, 0)};
0312 double Ay[3] = {transform(0, 1), transform(1, 1), transform(2, 1)};
0313 double d0 = lCf * Ax[0] + lSf * Ay[0];
0314 double d1 = lCf * Ax[1] + lSf * Ay[1];
0315 double d2 = lCf * Ax[2] + lSf * Ay[2];
0316 pVector[8] = d0;
0317 pVector[9] = d1;
0318 pVector[10] = d2;
0319 pVector[16] = Vp[0] * (lCf * Ay[0] - lSf * Ax[0]);
0320 pVector[17] = Vp[0] * (lCf * Ay[1] - lSf * Ax[1]);
0321 pVector[18] = Vp[0] * (lCf * Ay[2] - lSf * Ax[2]);
0322 }
0323
0324
0325 if (surface.type() == Surface::Perigee ||
0326 surface.type() == Surface::Straw) {
0327
0328
0329 double B[3] = {transform(0, 0), transform(1, 0), transform(2, 0)};
0330
0331 double A[3] = {transform(0, 1), transform(1, 1), transform(2, 1)};
0332
0333 double C[3] = {transform(0, 2), transform(1, 2), transform(2, 2)};
0334
0335
0336 double PC = pVector[4] * C[0] + pVector[5] * C[1] + pVector[6] * C[2];
0337 double Bn = 1. / PC;
0338
0339 double Bx2 = -A[2] * pVector[29];
0340 double Bx3 = A[1] * pVector[38] - A[2] * pVector[37];
0341
0342 double By2 = A[2] * pVector[28];
0343 double By3 = A[2] * pVector[36] - A[0] * pVector[38];
0344
0345 double Bz2 = A[0] * pVector[29] - A[1] * pVector[28];
0346 double Bz3 = A[0] * pVector[37] - A[1] * pVector[36];
0347
0348 double B2 = B[0] * Bx2 + B[1] * By2 + B[2] * Bz2;
0349 double B3 = B[0] * Bx3 + B[1] * By3 + B[2] * Bz3;
0350
0351 Bx2 = (Bx2 - B[0] * B2) * Bn;
0352 Bx3 = (Bx3 - B[0] * B3) * Bn;
0353 By2 = (By2 - B[1] * B2) * Bn;
0354 By3 = (By3 - B[1] * B3) * Bn;
0355 Bz2 = (Bz2 - B[2] * B2) * Bn;
0356 Bz3 = (Bz3 - B[2] * B3) * Bn;
0357
0358
0359 pVector[24] = Bx2 * Vp[0];
0360 pVector[32] = Bx3 * Vp[0];
0361 pVector[25] = By2 * Vp[0];
0362 pVector[33] = By3 * Vp[0];
0363 pVector[26] = Bz2 * Vp[0];
0364 pVector[34] = Bz3 * Vp[0];
0365 }
0366 }
0367
0368
0369 state.state_ready = true;
0370 }
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 Result<Vector3> getField(State& state, const Vector3& pos) const {
0381
0382 auto res = m_bField->getField(pos, state.fieldCache);
0383 if (res.ok()) {
0384 state.field = *res;
0385 }
0386 return res;
0387 }
0388
0389
0390
0391
0392 Vector3 position(const State& state) const {
0393 return Vector3(state.pVector[0], state.pVector[1], state.pVector[2]);
0394 }
0395
0396
0397
0398
0399 Vector3 direction(const State& state) const {
0400 return Vector3(state.pVector[4], state.pVector[5], state.pVector[6]);
0401 }
0402
0403
0404
0405
0406 double qOverP(const State& state) const { return state.pVector[7]; }
0407
0408
0409
0410
0411
0412 double absoluteMomentum(const State& state) const {
0413 return particleHypothesis(state).extractMomentum(qOverP(state));
0414 }
0415
0416
0417
0418
0419 Vector3 momentum(const State& state) const {
0420 return absoluteMomentum(state) * direction(state);
0421 }
0422
0423
0424
0425
0426
0427 double charge(const State& state) const {
0428 return particleHypothesis(state).extractCharge(qOverP(state));
0429 }
0430
0431
0432
0433
0434
0435 const ParticleHypothesis& particleHypothesis(const State& state) const {
0436 return state.particleHypothesis;
0437 }
0438
0439
0440
0441 double overstepLimit(const State& ) const {
0442 return -m_overstepLimit;
0443 }
0444
0445
0446
0447
0448 double time(const State& state) const { return state.pVector[3]; }
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466 IntersectionStatus updateSurfaceStatus(
0467 State& state, const Surface& surface, std::uint8_t index,
0468 Direction navDir, const BoundaryTolerance& boundaryTolerance,
0469 double surfaceTolerance, ConstrainedStep::Type stype,
0470 const Logger& logger = getDummyLogger()) const {
0471 return detail::updateSingleSurfaceStatus<AtlasStepper>(
0472 *this, state, surface, index, navDir, boundaryTolerance,
0473 surfaceTolerance, stype, logger);
0474 }
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 void updateStepSize(State& state, const NavigationTarget& target,
0486 Direction direction, ConstrainedStep::Type stype) const {
0487 (void)direction;
0488 double stepSize = target.pathLength();
0489 updateStepSize(state, stepSize, stype);
0490 }
0491
0492
0493
0494
0495
0496
0497 void updateStepSize(State& state, double stepSize,
0498 ConstrainedStep::Type stype) const {
0499 state.previousStepSize = state.stepSize.value();
0500 state.stepSize.update(stepSize, stype);
0501 }
0502
0503
0504
0505
0506
0507 void releaseStepSize(State& state, ConstrainedStep::Type stype) const {
0508 state.stepSize.release(stype);
0509 }
0510
0511
0512
0513
0514
0515
0516 double getStepSize(const State& state, ConstrainedStep::Type stype) const {
0517 return state.stepSize.value(stype);
0518 }
0519
0520
0521
0522
0523
0524 std::string outputStepSize(const State& state) const {
0525 return state.stepSize.toString();
0526 }
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540 Result<BoundState> boundState(
0541 State& state, const Surface& surface, bool transportCov = true,
0542 const FreeToBoundCorrection& freeToBoundCorrection =
0543 FreeToBoundCorrection(false)) const {
0544
0545 state.state_ready = false;
0546
0547 Acts::Vector4 pos4;
0548 pos4[ePos0] = state.pVector[0];
0549 pos4[ePos1] = state.pVector[1];
0550 pos4[ePos2] = state.pVector[2];
0551 pos4[eTime] = state.pVector[3];
0552 Acts::Vector3 dir;
0553 dir[eMom0] = state.pVector[4];
0554 dir[eMom1] = state.pVector[5];
0555 dir[eMom2] = state.pVector[6];
0556 const auto qOverP = state.pVector[7];
0557
0558
0559 std::optional<Covariance> covOpt = std::nullopt;
0560 if (state.covTransport && transportCov) {
0561 transportCovarianceToBound(state, surface, freeToBoundCorrection);
0562 }
0563 if (state.cov != Covariance::Zero()) {
0564 covOpt = state.cov;
0565 }
0566
0567
0568 auto parameters = BoundTrackParameters::create(
0569 state.options.geoContext, surface.getSharedPtr(), pos4, dir, qOverP,
0570 std::move(covOpt), state.particleHypothesis);
0571 if (!parameters.ok()) {
0572 return parameters.error();
0573 }
0574
0575 Jacobian jacobian(state.jacobian);
0576
0577 return BoundState(std::move(*parameters), jacobian.transpose(),
0578 state.pathAccumulated);
0579 }
0580
0581
0582
0583
0584
0585
0586
0587
0588 bool prepareCurvilinearState(State& state) const {
0589 (void)state;
0590 return true;
0591 }
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603 BoundState curvilinearState(State& state, bool transportCov = true) const {
0604
0605 state.state_ready = false;
0606
0607 Acts::Vector4 pos4;
0608 pos4[ePos0] = state.pVector[0];
0609 pos4[ePos1] = state.pVector[1];
0610 pos4[ePos2] = state.pVector[2];
0611 pos4[eTime] = state.pVector[3];
0612 Acts::Vector3 dir;
0613 dir[eMom0] = state.pVector[4];
0614 dir[eMom1] = state.pVector[5];
0615 dir[eMom2] = state.pVector[6];
0616 const auto qOverP = state.pVector[7];
0617
0618 std::optional<Covariance> covOpt = std::nullopt;
0619 if (state.covTransport && transportCov) {
0620 transportCovarianceToCurvilinear(state);
0621 }
0622 if (state.cov != Covariance::Zero()) {
0623 covOpt = state.cov;
0624 }
0625
0626 BoundTrackParameters parameters = BoundTrackParameters::createCurvilinear(
0627 pos4, dir, qOverP, std::move(covOpt), state.particleHypothesis);
0628
0629 Jacobian jacobian(state.jacobian);
0630
0631 return BoundState(std::move(parameters), jacobian.transpose(),
0632 state.pathAccumulated);
0633 }
0634
0635
0636
0637
0638
0639
0640
0641
0642 void update(State& state, const FreeVector& parameters,
0643 const BoundVector& boundParams, const Covariance& covariance,
0644 const Surface& surface) const {
0645 Vector3 direction = parameters.template segment<3>(eFreeDir0).normalized();
0646 state.pVector[0] = parameters[eFreePos0];
0647 state.pVector[1] = parameters[eFreePos1];
0648 state.pVector[2] = parameters[eFreePos2];
0649 state.pVector[3] = parameters[eFreeTime];
0650 state.pVector[4] = direction.x();
0651 state.pVector[5] = direction.y();
0652 state.pVector[6] = direction.z();
0653 state.pVector[7] = std::copysign(parameters[eFreeQOverP], state.pVector[7]);
0654
0655
0656 if (std::abs(state.pVector[7]) < .000000000000001) {
0657 state.pVector[7] < 0. ? state.pVector[7] = -.000000000000001
0658 : state.pVector[7] = .000000000000001;
0659 }
0660
0661
0662
0663
0664 Vector3 pos(state.pVector[0], state.pVector[1], state.pVector[2]);
0665 Vector3 mom(state.pVector[4], state.pVector[5], state.pVector[6]);
0666
0667 double Sf = std::sin(boundParams[eBoundPhi]);
0668 double Cf = std::cos(boundParams[eBoundPhi]);
0669 double Se = std::sin(boundParams[eBoundTheta]);
0670 double Ce = std::cos(boundParams[eBoundTheta]);
0671
0672 const auto transform =
0673 surface.referenceFrame(state.options.geoContext, pos, mom);
0674
0675 state.pVector[8] = transform(0, eBoundLoc0);
0676 state.pVector[16] = transform(0, eBoundLoc1);
0677 state.pVector[24] = 0.;
0678 state.pVector[32] = 0.;
0679 state.pVector[40] = 0.;
0680 state.pVector[48] = 0.;
0681
0682 state.pVector[9] = transform(1, eBoundLoc0);
0683 state.pVector[17] = transform(1, eBoundLoc1);
0684 state.pVector[25] = 0.;
0685 state.pVector[33] = 0.;
0686 state.pVector[41] = 0.;
0687 state.pVector[49] = 0.;
0688
0689 state.pVector[10] = transform(2, eBoundLoc0);
0690 state.pVector[18] = transform(2, eBoundLoc1);
0691 state.pVector[26] = 0.;
0692 state.pVector[34] = 0.;
0693 state.pVector[42] = 0.;
0694 state.pVector[50] = 0.;
0695
0696 state.pVector[11] = 0.;
0697 state.pVector[19] = 0.;
0698 state.pVector[27] = 0.;
0699 state.pVector[35] = 0.;
0700 state.pVector[43] = 0.;
0701 state.pVector[51] = 1.;
0702
0703 state.pVector[12] = 0.;
0704 state.pVector[20] = 0.;
0705 state.pVector[28] = -Sf * Se;
0706 state.pVector[36] = Cf * Ce;
0707 state.pVector[44] = 0.;
0708 state.pVector[52] = 0.;
0709
0710 state.pVector[13] = 0.;
0711 state.pVector[21] = 0.;
0712 state.pVector[29] = Cf * Se;
0713 state.pVector[37] = Sf * Ce;
0714 state.pVector[45] = 0.;
0715 state.pVector[53] = 0.;
0716
0717 state.pVector[14] = 0.;
0718 state.pVector[22] = 0.;
0719 state.pVector[30] = 0.;
0720 state.pVector[38] = -Se;
0721 state.pVector[46] = 0.;
0722 state.pVector[54] = 0.;
0723
0724 state.pVector[15] = 0.;
0725 state.pVector[23] = 0.;
0726 state.pVector[31] = 0.;
0727 state.pVector[39] = 0.;
0728 state.pVector[47] = 1.;
0729 state.pVector[55] = 0.;
0730
0731 state.pVector[56] = 0.;
0732 state.pVector[57] = 0.;
0733 state.pVector[58] = 0.;
0734 state.pVector[59] = 0.;
0735
0736
0737
0738 if (surface.type() == Surface::Disc) {
0739 double lCf = std::cos(boundParams[eBoundLoc1]);
0740 double lSf = std::sin(boundParams[eBoundLoc1]);
0741 double Ax[3] = {transform(0, 0), transform(1, 0), transform(2, 0)};
0742 double Ay[3] = {transform(0, 1), transform(1, 1), transform(2, 1)};
0743 double d0 = lCf * Ax[0] + lSf * Ay[0];
0744 double d1 = lCf * Ax[1] + lSf * Ay[1];
0745 double d2 = lCf * Ax[2] + lSf * Ay[2];
0746 state.pVector[8] = d0;
0747 state.pVector[9] = d1;
0748 state.pVector[10] = d2;
0749 state.pVector[16] = boundParams[eBoundLoc0] * (lCf * Ay[0] - lSf * Ax[0]);
0750 state.pVector[17] = boundParams[eBoundLoc0] * (lCf * Ay[1] - lSf * Ax[1]);
0751 state.pVector[18] = boundParams[eBoundLoc0] * (lCf * Ay[2] - lSf * Ax[2]);
0752 }
0753
0754
0755 if (surface.type() == Surface::Perigee ||
0756 surface.type() == Surface::Straw) {
0757
0758
0759 double B[3] = {transform(0, 0), transform(1, 0), transform(2, 0)};
0760
0761 double A[3] = {transform(0, 1), transform(1, 1), transform(2, 1)};
0762
0763 double C[3] = {transform(0, 2), transform(1, 2), transform(2, 2)};
0764
0765
0766 double PC = state.pVector[4] * C[0] + state.pVector[5] * C[1] +
0767 state.pVector[6] * C[2];
0768 double Bn = 1. / PC;
0769
0770 double Bx2 = -A[2] * state.pVector[29];
0771 double Bx3 = A[1] * state.pVector[38] - A[2] * state.pVector[37];
0772
0773 double By2 = A[2] * state.pVector[28];
0774 double By3 = A[2] * state.pVector[36] - A[0] * state.pVector[38];
0775
0776 double Bz2 = A[0] * state.pVector[29] - A[1] * state.pVector[28];
0777 double Bz3 = A[0] * state.pVector[37] - A[1] * state.pVector[36];
0778
0779 double B2 = B[0] * Bx2 + B[1] * By2 + B[2] * Bz2;
0780 double B3 = B[0] * Bx3 + B[1] * By3 + B[2] * Bz3;
0781
0782 Bx2 = (Bx2 - B[0] * B2) * Bn;
0783 Bx3 = (Bx3 - B[0] * B3) * Bn;
0784 By2 = (By2 - B[1] * B2) * Bn;
0785 By3 = (By3 - B[1] * B3) * Bn;
0786 Bz2 = (Bz2 - B[2] * B2) * Bn;
0787 Bz3 = (Bz3 - B[2] * B3) * Bn;
0788
0789
0790 state.pVector[24] = Bx2 * boundParams[eBoundLoc0];
0791 state.pVector[32] = Bx3 * boundParams[eBoundLoc0];
0792 state.pVector[25] = By2 * boundParams[eBoundLoc0];
0793 state.pVector[33] = By3 * boundParams[eBoundLoc0];
0794 state.pVector[26] = Bz2 * boundParams[eBoundLoc0];
0795 state.pVector[34] = Bz3 * boundParams[eBoundLoc0];
0796 }
0797
0798 state.covariance = new BoundSquareMatrix(covariance);
0799 state.covTransport = true;
0800 state.useJacobian = true;
0801
0802
0803 state.state_ready = true;
0804 }
0805
0806
0807
0808
0809
0810
0811
0812
0813 void update(State& state, const Vector3& uposition, const Vector3& udirection,
0814 double qop, double time) const {
0815
0816 state.pVector[0] = uposition[0];
0817 state.pVector[1] = uposition[1];
0818 state.pVector[2] = uposition[2];
0819 state.pVector[3] = time;
0820 state.pVector[4] = udirection[0];
0821 state.pVector[5] = udirection[1];
0822 state.pVector[6] = udirection[2];
0823 state.pVector[7] = qop;
0824 }
0825
0826
0827
0828
0829
0830
0831 void transportCovarianceToCurvilinear(State& state) const {
0832 double P[60];
0833 for (unsigned int i = 0; i < 60; ++i) {
0834 P[i] = state.pVector[i];
0835 }
0836
0837 double p = 1. / P[7];
0838 P[40] *= p;
0839 P[41] *= p;
0840 P[42] *= p;
0841 P[44] *= p;
0842 P[45] *= p;
0843 P[46] *= p;
0844
0845 double An = std::sqrt(P[4] * P[4] + P[5] * P[5]);
0846 double Ax[3];
0847 if (An != 0.) {
0848 Ax[0] = -P[5] / An;
0849 Ax[1] = P[4] / An;
0850 Ax[2] = 0.;
0851 } else {
0852 Ax[0] = 1.;
0853 Ax[1] = 0.;
0854 Ax[2] = 0.;
0855 }
0856
0857 double Ay[3] = {-Ax[1] * P[6], Ax[0] * P[6], An};
0858 double S[3] = {P[4], P[5], P[6]};
0859
0860 double A = P[4] * S[0] + P[5] * S[1] + P[6] * S[2];
0861 if (A != 0.) {
0862 A = 1. / A;
0863 }
0864 S[0] *= A;
0865 S[1] *= A;
0866 S[2] *= A;
0867
0868 double s0 = P[8] * S[0] + P[9] * S[1] + P[10] * S[2];
0869 double s1 = P[16] * S[0] + P[17] * S[1] + P[18] * S[2];
0870 double s2 = P[24] * S[0] + P[25] * S[1] + P[26] * S[2];
0871 double s3 = P[32] * S[0] + P[33] * S[1] + P[34] * S[2];
0872 double s4 = P[40] * S[0] + P[41] * S[1] + P[42] * S[2];
0873
0874 P[8] -= (s0 * P[4]);
0875 P[9] -= (s0 * P[5]);
0876 P[10] -= (s0 * P[6]);
0877 P[11] -= (s0 * P[59]);
0878 P[12] -= (s0 * P[56]);
0879 P[13] -= (s0 * P[57]);
0880 P[14] -= (s0 * P[58]);
0881 P[16] -= (s1 * P[4]);
0882 P[17] -= (s1 * P[5]);
0883 P[18] -= (s1 * P[6]);
0884 P[19] -= (s1 * P[59]);
0885 P[20] -= (s1 * P[56]);
0886 P[21] -= (s1 * P[57]);
0887 P[22] -= (s1 * P[58]);
0888 P[24] -= (s2 * P[4]);
0889 P[25] -= (s2 * P[5]);
0890 P[26] -= (s2 * P[6]);
0891 P[27] -= (s2 * P[59]);
0892 P[28] -= (s2 * P[56]);
0893 P[29] -= (s2 * P[57]);
0894 P[30] -= (s2 * P[58]);
0895 P[32] -= (s3 * P[4]);
0896 P[33] -= (s3 * P[5]);
0897 P[34] -= (s3 * P[6]);
0898 P[35] -= (s3 * P[59]);
0899 P[36] -= (s3 * P[56]);
0900 P[37] -= (s3 * P[57]);
0901 P[38] -= (s3 * P[58]);
0902 P[40] -= (s4 * P[4]);
0903 P[41] -= (s4 * P[5]);
0904 P[42] -= (s4 * P[6]);
0905 P[43] -= (s4 * P[59]);
0906 P[44] -= (s4 * P[56]);
0907 P[45] -= (s4 * P[57]);
0908 P[46] -= (s4 * P[58]);
0909
0910 double P3 = 0, P4 = 0, C = P[4] * P[4] + P[5] * P[5];
0911 if (C > 1.e-20) {
0912 C = 1. / C;
0913 P3 = P[4] * C;
0914 P4 = P[5] * C;
0915 C = -sqrt(C);
0916 } else {
0917 C = -1.e10;
0918 P3 = 1.;
0919 P4 = 0.;
0920 }
0921
0922
0923
0924 state.jacobian[0] = Ax[0] * P[8] + Ax[1] * P[9];
0925 state.jacobian[1] = Ax[0] * P[16] + Ax[1] * P[17];
0926 state.jacobian[2] = Ax[0] * P[24] + Ax[1] * P[25];
0927 state.jacobian[3] = Ax[0] * P[32] + Ax[1] * P[33];
0928 state.jacobian[4] = Ax[0] * P[40] + Ax[1] * P[41];
0929 state.jacobian[5] = 0.;
0930
0931 state.jacobian[6] = Ay[0] * P[8] + Ay[1] * P[9] + Ay[2] * P[10];
0932 state.jacobian[7] =
0933 Ay[0] * P[16] + Ay[1] * P[17] + Ay[2] * P[18];
0934 state.jacobian[8] =
0935 Ay[0] * P[24] + Ay[1] * P[25] + Ay[2] * P[26];
0936 state.jacobian[9] =
0937 Ay[0] * P[32] + Ay[1] * P[33] + Ay[2] * P[34];
0938 state.jacobian[10] =
0939 Ay[0] * P[40] + Ay[1] * P[41] + Ay[2] * P[42];
0940 state.jacobian[11] = 0.;
0941
0942 state.jacobian[12] = P3 * P[13] - P4 * P[12];
0943 state.jacobian[13] = P3 * P[21] - P4 * P[20];
0944 state.jacobian[14] = P3 * P[29] - P4 * P[28];
0945 state.jacobian[15] = P3 * P[37] - P4 * P[36];
0946 state.jacobian[16] = P3 * P[45] - P4 * P[44];
0947 state.jacobian[17] = 0.;
0948
0949 state.jacobian[18] = C * P[14];
0950 state.jacobian[19] = C * P[22];
0951 state.jacobian[20] = C * P[30];
0952 state.jacobian[21] = C * P[38];
0953 state.jacobian[22] = C * P[46];
0954 state.jacobian[23] = 0.;
0955
0956 state.jacobian[24] = 0.;
0957 state.jacobian[25] = 0.;
0958 state.jacobian[26] = 0.;
0959 state.jacobian[27] = 0.;
0960 state.jacobian[28] = P[47];
0961 state.jacobian[29] = 0.;
0962
0963 state.jacobian[30] = P[11];
0964 state.jacobian[31] = P[19];
0965 state.jacobian[32] = P[27];
0966 state.jacobian[33] = P[35];
0967 state.jacobian[34] = P[43];
0968 state.jacobian[35] = P[51];
0969
0970 Eigen::Map<Eigen::Matrix<double, eBoundSize, eBoundSize, Eigen::RowMajor>>
0971 J(state.jacobian);
0972 state.cov = J * (*state.covariance) * J.transpose();
0973 }
0974
0975
0976
0977
0978
0979
0980
0981 void transportCovarianceToBound(
0982 State& state, const Surface& surface,
0983 const FreeToBoundCorrection& =
0984 FreeToBoundCorrection(false)) const {
0985 Acts::Vector3 gp(state.pVector[0], state.pVector[1], state.pVector[2]);
0986 Acts::Vector3 mom(state.pVector[4], state.pVector[5], state.pVector[6]);
0987
0988 double P[60];
0989 for (unsigned int i = 0; i < 60; ++i) {
0990 P[i] = state.pVector[i];
0991 }
0992
0993 mom /= std::abs(state.pVector[7]);
0994
0995 double p = 1. / state.pVector[7];
0996 P[40] *= p;
0997 P[41] *= p;
0998 P[42] *= p;
0999 P[44] *= p;
1000 P[45] *= p;
1001 P[46] *= p;
1002
1003 const auto fFrame =
1004 surface.referenceFrame(state.options.geoContext, gp, mom);
1005
1006 double Ax[3] = {fFrame(0, 0), fFrame(1, 0), fFrame(2, 0)};
1007 double Ay[3] = {fFrame(0, 1), fFrame(1, 1), fFrame(2, 1)};
1008 double S[3] = {fFrame(0, 2), fFrame(1, 2), fFrame(2, 2)};
1009
1010
1011 double A = P[4] * S[0] + P[5] * S[1] + P[6] * S[2];
1012
1013 if (A != 0.) {
1014 A = 1. / A;
1015 }
1016
1017 S[0] *= A;
1018 S[1] *= A;
1019 S[2] *= A;
1020
1021 double s0 = P[8] * S[0] + P[9] * S[1] + P[10] * S[2];
1022 double s1 = P[16] * S[0] + P[17] * S[1] + P[18] * S[2];
1023 double s2 = P[24] * S[0] + P[25] * S[1] + P[26] * S[2];
1024 double s3 = P[32] * S[0] + P[33] * S[1] + P[34] * S[2];
1025 double s4 = P[40] * S[0] + P[41] * S[1] + P[42] * S[2];
1026
1027
1028
1029
1030 if (surface.type() == Surface::Straw ||
1031 surface.type() == Surface::Perigee) {
1032
1033 double x = P[0] - surface.center(state.options.geoContext).x();
1034 double y = P[1] - surface.center(state.options.geoContext).y();
1035 double z = P[2] - surface.center(state.options.geoContext).z();
1036
1037
1038 double d = P[4] * Ay[0] + P[5] * Ay[1] + P[6] * Ay[2];
1039
1040
1041 double a = (1. - d) * (1. + d);
1042 if (a != 0.) {
1043 a = 1. / a;
1044 }
1045
1046
1047 double X = d * Ay[0] - P[4];
1048 double Y = d * Ay[1] - P[5];
1049 double Z = d * Ay[2] - P[6];
1050
1051
1052 double d0 = P[12] * Ay[0] + P[13] * Ay[1] + P[14] * Ay[2];
1053 double d1 = P[20] * Ay[0] + P[21] * Ay[1] + P[22] * Ay[2];
1054 double d2 = P[28] * Ay[0] + P[29] * Ay[1] + P[30] * Ay[2];
1055 double d3 = P[36] * Ay[0] + P[37] * Ay[1] + P[38] * Ay[2];
1056 double d4 = P[44] * Ay[0] + P[45] * Ay[1] + P[46] * Ay[2];
1057
1058 s0 = (((P[8] * X + P[9] * Y + P[10] * Z) + x * (d0 * Ay[0] - P[12])) +
1059 (y * (d0 * Ay[1] - P[13]) + z * (d0 * Ay[2] - P[14]))) *
1060 (-a);
1061
1062 s1 = (((P[16] * X + P[17] * Y + P[18] * Z) + x * (d1 * Ay[0] - P[20])) +
1063 (y * (d1 * Ay[1] - P[21]) + z * (d1 * Ay[2] - P[22]))) *
1064 (-a);
1065 s2 = (((P[24] * X + P[25] * Y + P[26] * Z) + x * (d2 * Ay[0] - P[28])) +
1066 (y * (d2 * Ay[1] - P[29]) + z * (d2 * Ay[2] - P[30]))) *
1067 (-a);
1068 s3 = (((P[32] * X + P[33] * Y + P[34] * Z) + x * (d3 * Ay[0] - P[36])) +
1069 (y * (d3 * Ay[1] - P[37]) + z * (d3 * Ay[2] - P[38]))) *
1070 (-a);
1071 s4 = (((P[40] * X + P[41] * Y + P[42] * Z) + x * (d4 * Ay[0] - P[44])) +
1072 (y * (d4 * Ay[1] - P[45]) + z * (d4 * Ay[2] - P[46]))) *
1073 (-a);
1074 }
1075
1076 P[8] -= (s0 * P[4]);
1077 P[9] -= (s0 * P[5]);
1078 P[10] -= (s0 * P[6]);
1079 P[11] -= (s0 * P[59]);
1080 P[12] -= (s0 * P[56]);
1081 P[13] -= (s0 * P[57]);
1082 P[14] -= (s0 * P[58]);
1083
1084 P[16] -= (s1 * P[4]);
1085 P[17] -= (s1 * P[5]);
1086 P[18] -= (s1 * P[6]);
1087 P[19] -= (s1 * P[59]);
1088 P[20] -= (s1 * P[56]);
1089 P[21] -= (s1 * P[57]);
1090 P[22] -= (s1 * P[58]);
1091
1092 P[24] -= (s2 * P[4]);
1093 P[25] -= (s2 * P[5]);
1094 P[26] -= (s2 * P[6]);
1095 P[27] -= (s2 * P[59]);
1096 P[28] -= (s2 * P[56]);
1097 P[29] -= (s2 * P[57]);
1098 P[30] -= (s2 * P[58]);
1099
1100 P[32] -= (s3 * P[4]);
1101 P[33] -= (s3 * P[5]);
1102 P[34] -= (s3 * P[6]);
1103 P[35] -= (s3 * P[59]);
1104 P[36] -= (s3 * P[56]);
1105 P[37] -= (s3 * P[57]);
1106 P[38] -= (s3 * P[58]);
1107
1108 P[40] -= (s4 * P[4]);
1109 P[41] -= (s4 * P[5]);
1110 P[42] -= (s4 * P[6]);
1111 P[43] -= (s4 * P[59]);
1112 P[44] -= (s4 * P[56]);
1113 P[45] -= (s4 * P[57]);
1114 P[46] -= (s4 * P[58]);
1115
1116 double P3 = 0, P4 = 0, C = P[4] * P[4] + P[5] * P[5];
1117 if (C > 1.e-20) {
1118 C = 1. / C;
1119 P3 = P[4] * C;
1120 P4 = P[5] * C;
1121 C = -sqrt(C);
1122 } else {
1123 C = -1.e10;
1124 P3 = 1.;
1125 P4 = 0.;
1126 }
1127
1128 double MA[3] = {Ax[0], Ax[1], Ax[2]};
1129 double MB[3] = {Ay[0], Ay[1], Ay[2]};
1130
1131 if (surface.type() == Surface::Disc) {
1132
1133 const auto& sfc = surface.center(state.options.geoContext);
1134 double d[3] = {P[0] - sfc(0), P[1] - sfc(1), P[2] - sfc(2)};
1135
1136 double RC = d[0] * Ax[0] + d[1] * Ax[1] + d[2] * Ax[2];
1137 double RS = d[0] * Ay[0] + d[1] * Ay[1] + d[2] * Ay[2];
1138 double R2 = RC * RC + RS * RS;
1139
1140
1141 double Ri = 1. / sqrt(R2);
1142 MA[0] = (RC * Ax[0] + RS * Ay[0]) * Ri;
1143 MA[1] = (RC * Ax[1] + RS * Ay[1]) * Ri;
1144 MA[2] = (RC * Ax[2] + RS * Ay[2]) * Ri;
1145 MB[0] = (RC * Ay[0] - RS * Ax[0]) * (Ri = 1. / R2);
1146 MB[1] = (RC * Ay[1] - RS * Ax[1]) * Ri;
1147 MB[2] = (RC * Ay[2] - RS * Ax[2]) * Ri;
1148 }
1149
1150 state.jacobian[0] = MA[0] * P[8] + MA[1] * P[9] + MA[2] * P[10];
1151 state.jacobian[1] =
1152 MA[0] * P[16] + MA[1] * P[17] + MA[2] * P[18];
1153 state.jacobian[2] =
1154 MA[0] * P[24] + MA[1] * P[25] + MA[2] * P[26];
1155 state.jacobian[3] =
1156 MA[0] * P[32] + MA[1] * P[33] + MA[2] * P[34];
1157 state.jacobian[4] =
1158 MA[0] * P[40] + MA[1] * P[41] + MA[2] * P[42];
1159 state.jacobian[5] = 0.;
1160
1161 state.jacobian[6] = MB[0] * P[8] + MB[1] * P[9] + MB[2] * P[10];
1162 state.jacobian[7] =
1163 MB[0] * P[16] + MB[1] * P[17] + MB[2] * P[18];
1164 state.jacobian[8] =
1165 MB[0] * P[24] + MB[1] * P[25] + MB[2] * P[26];
1166 state.jacobian[9] =
1167 MB[0] * P[32] + MB[1] * P[33] + MB[2] * P[34];
1168 state.jacobian[10] =
1169 MB[0] * P[40] + MB[1] * P[41] + MB[2] * P[42];
1170 state.jacobian[11] = 0.;
1171
1172 state.jacobian[12] = P3 * P[13] - P4 * P[12];
1173 state.jacobian[13] = P3 * P[21] - P4 * P[20];
1174 state.jacobian[14] = P3 * P[29] - P4 * P[28];
1175 state.jacobian[15] = P3 * P[37] - P4 * P[36];
1176 state.jacobian[16] = P3 * P[45] - P4 * P[44];
1177 state.jacobian[17] = 0.;
1178
1179 state.jacobian[18] = C * P[14];
1180 state.jacobian[19] = C * P[22];
1181 state.jacobian[20] = C * P[30];
1182 state.jacobian[21] = C * P[38];
1183 state.jacobian[22] = C * P[46];
1184 state.jacobian[23] = 0.;
1185
1186 state.jacobian[24] = 0.;
1187 state.jacobian[25] = 0.;
1188 state.jacobian[26] = 0.;
1189 state.jacobian[27] = 0.;
1190 state.jacobian[28] = P[47];
1191 state.jacobian[29] = 0.;
1192
1193 state.jacobian[30] = P[11];
1194 state.jacobian[31] = P[19];
1195 state.jacobian[32] = P[27];
1196 state.jacobian[33] = P[35];
1197 state.jacobian[34] = P[43];
1198 state.jacobian[35] = P[51];
1199
1200 Eigen::Map<Eigen::Matrix<double, eBoundSize, eBoundSize, Eigen::RowMajor>>
1201 J(state.jacobian);
1202 state.cov = J * (*state.covariance) * J.transpose();
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 Result<double> step(State& state, Direction propDir,
1218 const IVolumeMaterial* material) const {
1219 (void)material;
1220
1221
1222 auto h = state.stepSize.value() * propDir;
1223 bool Jac = state.useJacobian;
1224
1225 double* R = &(state.pVector[0]);
1226 double* A = &(state.pVector[4]);
1227 double* sA = &(state.pVector[56]);
1228
1229 double Pi = 0.5 * state.pVector[7];
1230
1231 Vector3 f0, f;
1232
1233
1234 if (state.newfield) {
1235 const Vector3 pos(R[0], R[1], R[2]);
1236
1237 auto fRes = getField(state, pos);
1238 if (!fRes.ok()) {
1239 return fRes.error();
1240 }
1241 f0 = *fRes;
1242 } else {
1243 f0 = state.field;
1244 }
1245
1246 bool Helix = false;
1247
1248
1249 const auto calcStepSizeScaling =
1250 [&](const double errorEstimate_) -> double {
1251
1252 constexpr double lower = 0.25;
1253 constexpr double upper = 4.0;
1254
1255 constexpr double exponent = 0.25;
1256
1257 double x = state.options.stepTolerance / errorEstimate_;
1258
1259 if constexpr (exponent == 0.25) {
1260
1261 x = std::sqrt(std::sqrt(x));
1262 } else {
1263 x = std::pow(x, exponent);
1264 }
1265
1266 return std::clamp(x, lower, upper);
1267 };
1268
1269 const auto isErrorTolerable = [&](const double errorEstimate_) {
1270
1271 constexpr double marginFactor = 4.0;
1272
1273 return errorEstimate_ <= marginFactor * state.options.stepTolerance;
1274 };
1275
1276 double EST = 0;
1277 double initialH = h;
1278
1279 std::size_t nStepTrials = 0;
1280 while (h != 0.) {
1281 nStepTrials++;
1282
1283
1284 double S3 = (1. / 3.) * h, S4 = .25 * h, PS2 = Pi * h;
1285
1286
1287
1288
1289 double H0[3] = {f0[0] * PS2, f0[1] * PS2, f0[2] * PS2};
1290
1291 double A0 = A[1] * H0[2] - A[2] * H0[1];
1292 double B0 = A[2] * H0[0] - A[0] * H0[2];
1293 double C0 = A[0] * H0[1] - A[1] * H0[0];
1294
1295 double A2 = A0 + A[0];
1296 double B2 = B0 + A[1];
1297 double C2 = C0 + A[2];
1298
1299 double A1 = A2 + A[0];
1300 double B1 = B2 + A[1];
1301 double C1 = C2 + A[2];
1302
1303
1304
1305 if (!Helix) {
1306
1307 const Vector3 pos(R[0] + A1 * S4, R[1] + B1 * S4, R[2] + C1 * S4);
1308
1309 auto fRes = getField(state, pos);
1310 if (!fRes.ok()) {
1311 return fRes.error();
1312 }
1313 f = *fRes;
1314 } else {
1315 f = f0;
1316 }
1317
1318
1319 double H1[3] = {f[0] * PS2, f[1] * PS2, f[2] * PS2};
1320
1321 double A3 = (A[0] + B2 * H1[2]) - C2 * H1[1];
1322 double B3 = (A[1] + C2 * H1[0]) - A2 * H1[2];
1323 double C3 = (A[2] + A2 * H1[1]) - B2 * H1[0];
1324
1325 double A4 = (A[0] + B3 * H1[2]) - C3 * H1[1];
1326 double B4 = (A[1] + C3 * H1[0]) - A3 * H1[2];
1327 double C4 = (A[2] + A3 * H1[1]) - B3 * H1[0];
1328
1329 double A5 = 2. * A4 - A[0];
1330 double B5 = 2. * B4 - A[1];
1331 double C5 = 2. * C4 - A[2];
1332
1333
1334
1335 if (!Helix) {
1336
1337 const Vector3 pos(R[0] + h * A4, R[1] + h * B4, R[2] + h * C4);
1338
1339 auto fRes = getField(state, pos);
1340 if (!fRes.ok()) {
1341 return fRes.error();
1342 }
1343 f = *fRes;
1344 } else {
1345 f = f0;
1346 }
1347
1348
1349 double H2[3] = {f[0] * PS2, f[1] * PS2, f[2] * PS2};
1350
1351 double A6 = B5 * H2[2] - C5 * H2[1];
1352 double B6 = C5 * H2[0] - A5 * H2[2];
1353 double C6 = A5 * H2[1] - B5 * H2[0];
1354
1355
1356
1357
1358
1359 EST = 2. * std::abs(h) *
1360 (std::abs((A1 + A6) - (A3 + A4)) + std::abs((B1 + B6) - (B3 + B4)) +
1361 std::abs((C1 + C6) - (C3 + C4)));
1362 EST = std::max(1e-20, EST);
1363 if (!isErrorTolerable(EST)) {
1364 const double stepSizeScaling = calcStepSizeScaling(EST);
1365 h *= stepSizeScaling;
1366
1367 state.stepSize.setAccuracy(h * propDir);
1368
1369 continue;
1370 }
1371
1372
1373
1374
1375
1376 double A00 = A[0], A11 = A[1], A22 = A[2];
1377
1378 A[0] = 2. * A3 + (A0 + A5 + A6);
1379 A[1] = 2. * B3 + (B0 + B5 + B6);
1380 A[2] = 2. * C3 + (C0 + C5 + C6);
1381
1382 double D = (A[0] * A[0] + A[1] * A[1]) + (A[2] * A[2] - 9.);
1383 double Sl = 2. / h;
1384 D = (1. / 3.) - ((1. / 648.) * D) * (12. - D);
1385
1386 R[0] += (A2 + A3 + A4) * S3;
1387 R[1] += (B2 + B3 + B4) * S3;
1388 R[2] += (C2 + C3 + C4) * S3;
1389 A[0] *= D;
1390 A[1] *= D;
1391 A[2] *= D;
1392 sA[0] = A6 * Sl;
1393 sA[1] = B6 * Sl;
1394 sA[2] = C6 * Sl;
1395
1396 double mass = particleHypothesis(state).mass();
1397 double momentum = absoluteMomentum(state);
1398
1399
1400 double dtds = std::sqrt(1 + mass * mass / (momentum * momentum));
1401 state.pVector[3] += h * dtds;
1402 state.pVector[59] = dtds;
1403 state.field = f;
1404 state.newfield = false;
1405
1406 if (Jac) {
1407 double dtdl = h * mass * mass * qOverP(state) / dtds;
1408 state.pVector[43] += dtdl;
1409
1410
1411
1412 double* d2A = &state.pVector[28];
1413 double* d3A = &state.pVector[36];
1414 double* d4A = &state.pVector[44];
1415 double d2A0 = H0[2] * d2A[1] - H0[1] * d2A[2];
1416 double d2B0 = H0[0] * d2A[2] - H0[2] * d2A[0];
1417 double d2C0 = H0[1] * d2A[0] - H0[0] * d2A[1];
1418 double d3A0 = H0[2] * d3A[1] - H0[1] * d3A[2];
1419 double d3B0 = H0[0] * d3A[2] - H0[2] * d3A[0];
1420 double d3C0 = H0[1] * d3A[0] - H0[0] * d3A[1];
1421 double d4A0 = (A0 + H0[2] * d4A[1]) - H0[1] * d4A[2];
1422 double d4B0 = (B0 + H0[0] * d4A[2]) - H0[2] * d4A[0];
1423 double d4C0 = (C0 + H0[1] * d4A[0]) - H0[0] * d4A[1];
1424 double d2A2 = d2A0 + d2A[0];
1425 double d2B2 = d2B0 + d2A[1];
1426 double d2C2 = d2C0 + d2A[2];
1427 double d3A2 = d3A0 + d3A[0];
1428 double d3B2 = d3B0 + d3A[1];
1429 double d3C2 = d3C0 + d3A[2];
1430 double d4A2 = d4A0 + d4A[0];
1431 double d4B2 = d4B0 + d4A[1];
1432 double d4C2 = d4C0 + d4A[2];
1433 double d0 = d4A[0] - A00;
1434 double d1 = d4A[1] - A11;
1435 double d2 = d4A[2] - A22;
1436 double d2A3 = (d2A[0] + d2B2 * H1[2]) - d2C2 * H1[1];
1437 double d2B3 = (d2A[1] + d2C2 * H1[0]) - d2A2 * H1[2];
1438 double d2C3 = (d2A[2] + d2A2 * H1[1]) - d2B2 * H1[0];
1439 double d3A3 = (d3A[0] + d3B2 * H1[2]) - d3C2 * H1[1];
1440 double d3B3 = (d3A[1] + d3C2 * H1[0]) - d3A2 * H1[2];
1441 double d3C3 = (d3A[2] + d3A2 * H1[1]) - d3B2 * H1[0];
1442 double d4A3 = ((A3 + d0) + d4B2 * H1[2]) - d4C2 * H1[1];
1443 double d4B3 = ((B3 + d1) + d4C2 * H1[0]) - d4A2 * H1[2];
1444 double d4C3 = ((C3 + d2) + d4A2 * H1[1]) - d4B2 * H1[0];
1445 double d2A4 = (d2A[0] + d2B3 * H1[2]) - d2C3 * H1[1];
1446 double d2B4 = (d2A[1] + d2C3 * H1[0]) - d2A3 * H1[2];
1447 double d2C4 = (d2A[2] + d2A3 * H1[1]) - d2B3 * H1[0];
1448 double d3A4 = (d3A[0] + d3B3 * H1[2]) - d3C3 * H1[1];
1449 double d3B4 = (d3A[1] + d3C3 * H1[0]) - d3A3 * H1[2];
1450 double d3C4 = (d3A[2] + d3A3 * H1[1]) - d3B3 * H1[0];
1451 double d4A4 = ((A4 + d0) + d4B3 * H1[2]) - d4C3 * H1[1];
1452 double d4B4 = ((B4 + d1) + d4C3 * H1[0]) - d4A3 * H1[2];
1453 double d4C4 = ((C4 + d2) + d4A3 * H1[1]) - d4B3 * H1[0];
1454 double d2A5 = 2. * d2A4 - d2A[0];
1455 double d2B5 = 2. * d2B4 - d2A[1];
1456 double d2C5 = 2. * d2C4 - d2A[2];
1457 double d3A5 = 2. * d3A4 - d3A[0];
1458 double d3B5 = 2. * d3B4 - d3A[1];
1459 double d3C5 = 2. * d3C4 - d3A[2];
1460 double d4A5 = 2. * d4A4 - d4A[0];
1461 double d4B5 = 2. * d4B4 - d4A[1];
1462 double d4C5 = 2. * d4C4 - d4A[2];
1463 double d2A6 = d2B5 * H2[2] - d2C5 * H2[1];
1464 double d2B6 = d2C5 * H2[0] - d2A5 * H2[2];
1465 double d2C6 = d2A5 * H2[1] - d2B5 * H2[0];
1466 double d3A6 = d3B5 * H2[2] - d3C5 * H2[1];
1467 double d3B6 = d3C5 * H2[0] - d3A5 * H2[2];
1468 double d3C6 = d3A5 * H2[1] - d3B5 * H2[0];
1469 double d4A6 = d4B5 * H2[2] - d4C5 * H2[1];
1470 double d4B6 = d4C5 * H2[0] - d4A5 * H2[2];
1471 double d4C6 = d4A5 * H2[1] - d4B5 * H2[0];
1472
1473 double* dR = &state.pVector[24];
1474 dR[0] += (d2A2 + d2A3 + d2A4) * S3;
1475 dR[1] += (d2B2 + d2B3 + d2B4) * S3;
1476 dR[2] += (d2C2 + d2C3 + d2C4) * S3;
1477 d2A[0] = ((d2A0 + 2. * d2A3) + (d2A5 + d2A6)) * (1. / 3.);
1478 d2A[1] = ((d2B0 + 2. * d2B3) + (d2B5 + d2B6)) * (1. / 3.);
1479 d2A[2] = ((d2C0 + 2. * d2C3) + (d2C5 + d2C6)) * (1. / 3.);
1480
1481 dR = &state.pVector[32];
1482 dR[0] += (d3A2 + d3A3 + d3A4) * S3;
1483 dR[1] += (d3B2 + d3B3 + d3B4) * S3;
1484 dR[2] += (d3C2 + d3C3 + d3C4) * S3;
1485 d3A[0] = ((d3A0 + 2. * d3A3) + (d3A5 + d3A6)) * (1. / 3.);
1486 d3A[1] = ((d3B0 + 2. * d3B3) + (d3B5 + d3B6)) * (1. / 3.);
1487 d3A[2] = ((d3C0 + 2. * d3C3) + (d3C5 + d3C6)) * (1. / 3.);
1488
1489 dR = &state.pVector[40];
1490 dR[0] += (d4A2 + d4A3 + d4A4) * S3;
1491 dR[1] += (d4B2 + d4B3 + d4B4) * S3;
1492 dR[2] += (d4C2 + d4C3 + d4C4) * S3;
1493 d4A[0] = ((d4A0 + 2. * d4A3) + (d4A5 + d4A6 + A6)) * (1. / 3.);
1494 d4A[1] = ((d4B0 + 2. * d4B3) + (d4B5 + d4B6 + B6)) * (1. / 3.);
1495 d4A[2] = ((d4C0 + 2. * d4C3) + (d4C5 + d4C6 + C6)) * (1. / 3.);
1496 }
1497
1498 break;
1499 }
1500
1501 state.pathAccumulated += h;
1502 ++state.nSteps;
1503 state.nStepTrials += nStepTrials;
1504
1505 const double stepSizeScaling = calcStepSizeScaling(EST);
1506 const double nextAccuracy = std::abs(h * stepSizeScaling);
1507 const double previousAccuracy = std::abs(state.stepSize.accuracy());
1508 const double initialStepLength = std::abs(initialH);
1509 if (nextAccuracy < initialStepLength || nextAccuracy > previousAccuracy) {
1510 state.stepSize.setAccuracy(nextAccuracy);
1511 }
1512
1513 return h;
1514 }
1515
1516
1517
1518
1519
1520 void setIdentityJacobian(State& state) const {
1521 state.jacobian[0] = 1.;
1522 state.jacobian[1] = 0.;
1523 state.jacobian[2] = 0.;
1524 state.jacobian[3] = 0.;
1525 state.jacobian[4] = 0.;
1526 state.jacobian[5] = 0.;
1527
1528 state.jacobian[6] = 0.;
1529 state.jacobian[7] = 1.;
1530 state.jacobian[8] = 0.;
1531 state.jacobian[9] = 0.;
1532 state.jacobian[10] = 0.;
1533 state.jacobian[11] = 0.;
1534
1535 state.jacobian[12] = 0.;
1536 state.jacobian[13] = 0.;
1537 state.jacobian[14] = 1.;
1538 state.jacobian[15] = 0.;
1539 state.jacobian[16] = 0.;
1540 state.jacobian[17] = 0.;
1541
1542 state.jacobian[18] = 0.;
1543 state.jacobian[19] = 0.;
1544 state.jacobian[20] = 0.;
1545 state.jacobian[21] = 1.;
1546 state.jacobian[22] = 0.;
1547 state.jacobian[23] = 0.;
1548
1549 state.jacobian[24] = 0.;
1550 state.jacobian[25] = 0.;
1551 state.jacobian[26] = 0.;
1552 state.jacobian[27] = 0.;
1553 state.jacobian[28] = 1.;
1554 state.jacobian[29] = 0.;
1555
1556 state.jacobian[30] = 0.;
1557 state.jacobian[31] = 0.;
1558 state.jacobian[32] = 0.;
1559 state.jacobian[33] = 0.;
1560 state.jacobian[34] = 0.;
1561 state.jacobian[35] = 1.;
1562 }
1563
1564 private:
1565 std::shared_ptr<const MagneticFieldProvider> m_bField;
1566
1567
1568 double m_overstepLimit = 100 * UnitConstants::um;
1569 };
1570
1571 }