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