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