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