48 if (cache.m_solenoid) {
49 cache.m_fieldCache.getFieldZR(R,
H);
51 cache.m_fieldCache.getField(R,
H);
56getFieldGradient(Cache& cache,
61 if (cache.m_solenoid) {
62 cache.m_fieldCache.getFieldZR(R,
H, dH);
64 cache.m_fieldCache.getField(R,
H, dH);
74rungeKuttaStep(Cache& cache,
bool Jac,
double S,
double*
ATH_RESTRICT P,
bool& InS)
79 const double Pi = 149.89626 *
P[6];
80 double dltm = cache.m_dlt * .03;
85 getField(cache, R, f0);
87 f0[0] = cache.m_field[0];
88 f0[1] = cache.m_field[1];
89 f0[2] = cache.m_field[2];
93 if (std::abs(S) < cache.m_helixStep)
97 const double S3 = (1. / 3.) * S;
98 const double S4 = .25 *
S;
99 const double PS2 =
Pi *
S;
103 const double H0[3] = { f0[0] * PS2, f0[1] * PS2, f0[2] * PS2 };
104 const double A0 =
A[1] * H0[2] -
A[2] * H0[1];
105 const double B0 =
A[2] * H0[0] -
A[0] * H0[2];
106 const double C0 =
A[0] * H0[1] -
A[1] * H0[0];
107 const double A2 = A0 +
A[0];
108 const double B2 =
B0 +
A[1];
109 const double C2 = C0 +
A[2];
110 const double A1 = A2 +
A[0];
111 const double B1 = B2 +
A[1];
112 const double C1 = C2 +
A[2];
117 const double gP[3] = { R[0] + A1 * S4, R[1] + B1 * S4, R[2] + C1 * S4 };
118 getField(cache, gP, f);
125 const double H1[3] = {
f[0] * PS2,
f[1] * PS2,
f[2] * PS2 };
126 const double A3 = (
A[0] + B2 * H1[2]) - C2 * H1[1];
127 const double B3 = (
A[1] + C2 * H1[0]) - A2 * H1[2];
128 const double C3 = (
A[2] + A2 * H1[1]) - B2 * H1[0];
129 const double A4 = (
A[0] + B3 * H1[2]) - C3 * H1[1];
130 const double B4 = (
A[1] + C3 * H1[0]) - A3 * H1[2];
131 const double C4 = (
A[2] + A3 * H1[1]) - B3 * H1[0];
132 const double A5 = 2. * A4 -
A[0];
133 const double B5 = 2. * B4 -
A[1];
134 const double C5 = 2. * C4 -
A[2];
139 const double gP[3] = { R[0] +
S * A4, R[1] +
S * B4, R[2] +
S * C4 };
140 getField(cache, gP, f);
147 const double H2[3] = {
f[0] * PS2,
f[1] * PS2,
f[2] * PS2 };
148 const double A6 = B5 *
H2[2] - C5 *
H2[1];
149 const double B6 = C5 *
H2[0] - A5 *
H2[2];
150 const double C6 = A5 *
H2[1] - B5 *
H2[0];
154 const double EST = std::abs((A1 + A6) - (A3 + A4)) +
155 std::abs((B1 + B6) - (B3 + B4)) +
156 std::abs((C1 + C6) - (C3 + C4));
157 if (EST > cache.m_dlt) {
162 EST < dltm ? InS = true : InS =
false;
166 const double A00 =
A[0];
167 const double A11 =
A[1];
168 const double A22 =
A[2];
170 const double Aarr[3]{ A00, A11, A22 };
171 const double A0arr[3]{ A0,
B0, C0 };
172 const double A3arr[3]{ A3, B3, C3 };
173 const double A4arr[3]{ A4, B4, C4 };
174 const double A6arr[3]{ A6, B6, C6 };
176 A[0] = 2. * A3 + (A0 + A5 + A6);
177 A[1] = 2. * B3 + (
B0 + B5 + B6);
178 A[2] = 2. * C3 + (C0 + C5 + C6);
180 double D = (
A[0] *
A[0] +
A[1] *
A[1]) + (
A[2] *
A[2] - 9.);
181 const double Sl = 2. /
S;
182 D = (1. / 3.) - ((1. / 648.) * D) * (12. - D);
184 R[0] += (A2 + A3 + A4) *
S3;
185 R[1] += (B2 + B3 + B4) *
S3;
186 R[2] += (C2 + C3 + C4) *
S3;
194 cache.m_field[0] =
f[0];
195 cache.m_field[1] =
f[1];
196 cache.m_field[2] =
f[2];
197 cache.m_newfield =
false;
217 const double*
A = &
P[3];
230 for (
int i = 7;
i < 42;
i += 7) {
233 const double* dA = &
P[
i + 3];
234 dR[0] += (dA[0] *
S);
235 dR[1] += (dA[1] *
S);
236 dR[2] += (dA[2] *
S);
238 sA[0] = sA[1] = sA[2] = 0.;
253rungeKuttaStepWithGradient(Cache& cache,
double S,
double*
ATH_RESTRICT P,
bool& InS)
255 const double C33 = 1. / 3.;
259 const double Pi = 149.89626 *
P[6];
260 double dltm = cache.m_dlt * .03;
271 getFieldGradient(cache, R, f0, g0);
275 const double S3 = C33 *
S;
276 const double S4 = .25 *
S;
277 const double PS2 =
Pi *
S;
284 const double A0 =
A[1] * H0[2] -
A[2] * H0[1];
285 const double B0 =
A[2] * H0[0] -
A[0] * H0[2];
286 const double C0 =
A[0] * H0[1] -
A[1] * H0[0];
287 const double A2 =
A[0] + A0;
288 const double B2 =
A[1] +
B0;
289 const double C2 =
A[2] + C0;
290 const double A1 = A2 +
A[0];
291 const double B1 = B2 +
A[1];
292 const double C1 = C2 +
A[2];
296 const double gP1[3] = { R[0] + A1 * S4, R[1] + B1 * S4, R[2] + C1 * S4 };
297 getFieldGradient(cache, gP1, f1, g1);
302 const double A3 = B2 * H1[2] - C2 * H1[1] +
A[0];
303 const double B3 = C2 * H1[0] - A2 * H1[2] +
A[1];
304 const double C3 = A2 * H1[1] - B2 * H1[0] +
A[2];
305 const double A4 = B3 * H1[2] - C3 * H1[1] +
A[0];
306 const double B4 = C3 * H1[0] - A3 * H1[2] +
A[1];
307 const double C4 = A3 * H1[1] - B3 * H1[0] +
A[2];
308 const double A5 = A4 -
A[0] + A4;
309 const double B5 = B4 -
A[1] + B4;
310 const double C5 = C4 -
A[2] + C4;
314 const double gP2[3] = { R[0] +
S * A4, R[1] +
S * B4, R[2] +
S * C4 };
315 getFieldGradient(cache, gP2, f2, g2);
320 const double A6 = B5 *
H2[2] - C5 *
H2[1];
321 const double B6 = C5 *
H2[0] - A5 *
H2[2];
322 const double C6 = A5 *
H2[1] - B5 *
H2[0];
326 const double EST = std::abs((A1 + A6) - (A3 + A4)) + std::abs((B1 + B6) - (B3 + B4)) +
327 std::abs((C1 + C6) - (C3 + C4));
328 if (EST > cache.m_dlt) {
333 EST < dltm ? InS = true : InS =
false;
337 const double A00 =
A[0];
338 const double A11 =
A[1];
339 const double A22 =
A[2];
340 R[0] += (A2 + A3 + A4) *
S3;
341 A[0] = ((A0 + 2. * A3) + (A5 + A6)) * C33;
342 R[1] += (B2 + B3 + B4) *
S3;
343 A[1] = ((
B0 + 2. * B3) + (B5 + B6)) * C33;
344 R[2] += (C2 + C3 + C4) *
S3;
345 A[2] = ((C0 + 2. * C3) + (C5 + C6)) * C33;
346 const double CBA = 1. / std::sqrt(
A[0] *
A[0] +
A[1] *
A[1] +
A[2] *
A[2]);
351 const double Sl = 2. /
S;
358 for (
int i = 3;
i != 12; ++
i) {
359 H0[
i] = g0[
i - 3] * PS2;
360 H1[
i] =
g1[
i - 3] * PS2;
364 for (
int i = 7;
i < 35;
i += 7) {
367 double* dA = &
P[
i + 3];
368 double dH0 = H0[3] * dR[0] + H0[4] * dR[1] + H0[5] * dR[2];
369 double dH1 = H0[6] * dR[0] + H0[7] * dR[1] + H0[8] * dR[2];
370 double dH2 = H0[9] * dR[0] + H0[10] * dR[1] + H0[11] * dR[2];
372 const double dA0 = (H0[2] * dA[1] - H0[1] * dA[2]) + (
A[1] * dH2 -
A[2] * dH1);
373 const double dB0 = (H0[0] * dA[2] - H0[2] * dA[0]) + (
A[2] * dH0 -
A[0] * dH2);
374 const double dC0 = (H0[1] * dA[0] - H0[0] * dA[1]) + (
A[0] * dH1 -
A[1] * dH0);
375 const double dA2 = dA0 + dA[0];
376 double dX = dR[0] + (dA2 + dA[0]) * S4;
377 const double dB2 = dB0 + dA[1];
378 double dY = dR[1] + (dB2 + dA[1]) * S4;
379 const double dC2 = dC0 + dA[2];
380 double dZ = dR[2] + (dC2 + dA[2]) * S4;
381 dH0 = H1[3] * dX + H1[4] * dY + H1[5] * dZ;
382 dH1 = H1[6] * dX + H1[7] * dY + H1[8] * dZ;
383 dH2 = H1[9] * dX + H1[10] * dY + H1[11] * dZ;
385 const double dA3 = (dA[0] + dB2 * H1[2] - dC2 * H1[1]) + (B2 * dH2 - C2 * dH1);
386 const double dB3 = (dA[1] + dC2 * H1[0] - dA2 * H1[2]) + (C2 * dH0 - A2 * dH2);
387 const double dC3 = (dA[2] + dA2 * H1[1] - dB2 * H1[0]) + (A2 * dH1 - B2 * dH0);
388 const double dA4 = (dA[0] + dB3 * H1[2] - dC3 * H1[1]) + (B3 * dH2 - C3 * dH1);
389 const double dB4 = (dA[1] + dC3 * H1[0] - dA3 * H1[2]) + (C3 * dH0 - A3 * dH2);
390 const double dC4 = (dA[2] + dA3 * H1[1] - dB3 * H1[0]) + (A3 * dH1 - B3 * dH0);
391 const double dA5 = dA4 + dA4 - dA[0];
392 dX = dR[0] + dA4 *
S;
393 const double dB5 = dB4 + dB4 - dA[1];
394 dY = dR[1] + dB4 *
S;
395 const double dC5 = dC4 + dC4 - dA[2];
396 dZ = dR[2] + dC4 *
S;
397 dH0 =
H2[3] * dX +
H2[4] * dY +
H2[5] * dZ;
398 dH1 =
H2[6] * dX +
H2[7] * dY +
H2[8] * dZ;
399 dH2 =
H2[9] * dX +
H2[10] * dY +
H2[11] * dZ;
401 const double dA6 = (dB5 *
H2[2] - dC5 *
H2[1]) + (B5 * dH2 - C5 * dH1);
402 const double dB6 = (dC5 *
H2[0] - dA5 *
H2[2]) + (C5 * dH0 - A5 * dH2);
403 const double dC6 = (dA5 *
H2[1] - dB5 *
H2[0]) + (A5 * dH1 - B5 * dH0);
404 dR[0] += (dA2 + dA3 + dA4) *
S3;
405 dA[0] = ((dA0 + 2. * dA3) + (dA5 + dA6)) * C33;
406 dR[1] += (dB2 + dB3 + dB4) *
S3;
407 dA[1] = ((dB0 + 2. * dB3) + (dB5 + dB6)) * C33;
408 dR[2] += (dC2 + dC3 + dC4) *
S3;
409 dA[2] = ((dC0 + 2. * dC3) + (dC5 + dC6)) * C33;
415 double dH0 = H0[3] * dR[0] + H0[4] * dR[1] + H0[5] * dR[2];
416 double dH1 = H0[6] * dR[0] + H0[7] * dR[1] + H0[8] * dR[2];
417 double dH2 = H0[9] * dR[0] + H0[10] * dR[1] + H0[11] * dR[2];
418 const double dA0 = (H0[2] * dA[1] - H0[1] * dA[2]) + (
A[1] * dH2 -
A[2] * dH1 + A0);
419 const double dB0 = (H0[0] * dA[2] - H0[2] * dA[0]) + (
A[2] * dH0 -
A[0] * dH2 +
B0);
420 const double dC0 = (H0[1] * dA[0] - H0[0] * dA[1]) + (
A[0] * dH1 -
A[1] * dH0 + C0);
421 const double dA2 = dA0 + dA[0];
422 double dX = dR[0] + (dA2 + dA[0]) * S4;
423 const double dB2 = dB0 + dA[1];
424 double dY = dR[1] + (dB2 + dA[1]) * S4;
425 const double dC2 = dC0 + dA[2];
426 double dZ = dR[2] + (dC2 + dA[2]) * S4;
427 dH0 = H1[3] * dX + H1[4] * dY + H1[5] * dZ;
428 dH1 = H1[6] * dX + H1[7] * dY + H1[8] * dZ;
429 dH2 = H1[9] * dX + H1[10] * dY + H1[11] * dZ;
432 (dA[0] + dB2 * H1[2] - dC2 * H1[1]) + ((B2 * dH2 - C2 * dH1) + (A3 - A00));
434 (dA[1] + dC2 * H1[0] - dA2 * H1[2]) + ((C2 * dH0 - A2 * dH2) + (B3 - A11));
436 (dA[2] + dA2 * H1[1] - dB2 * H1[0]) + ((A2 * dH1 - B2 * dH0) + (C3 - A22));
438 (dA[0] + dB3 * H1[2] - dC3 * H1[1]) + ((B3 * dH2 - C3 * dH1) + (A4 - A00));
440 (dA[1] + dC3 * H1[0] - dA3 * H1[2]) + ((C3 * dH0 - A3 * dH2) + (B4 - A11));
442 (dA[2] + dA3 * H1[1] - dB3 * H1[0]) + ((A3 * dH1 - B3 * dH0) + (C4 - A22));
443 const double dA5 = dA4 + dA4 - dA[0];
444 dX = dR[0] + dA4 *
S;
445 const double dB5 = dB4 + dB4 - dA[1];
446 dY = dR[1] + dB4 *
S;
447 const double dC5 = dC4 + dC4 - dA[2];
448 dZ = dR[2] + dC4 *
S;
449 dH0 =
H2[3] * dX +
H2[4] * dY +
H2[5] * dZ;
450 dH1 =
H2[6] * dX +
H2[7] * dY +
H2[8] * dZ;
451 dH2 =
H2[9] * dX +
H2[10] * dY +
H2[11] * dZ;
453 const double dA6 = (dB5 *
H2[2] - dC5 *
H2[1]) + (B5 * dH2 - C5 * dH1 + A6);
454 const double dB6 = (dC5 *
H2[0] - dA5 *
H2[2]) + (C5 * dH0 - A5 * dH2 + B6);
455 const double dC6 = (dA5 *
H2[1] - dB5 *
H2[0]) + (A5 * dH1 - B5 * dH0 + C6);
457 dR[0] += (dA2 + dA3 + dA4) *
S3;
458 dA[0] = ((dA0 + 2. * dA3) + (dA5 + dA6)) * C33;
459 dR[1] += (dB2 + dB3 + dB4) *
S3;
460 dA[1] = ((dB0 + 2. * dB3) + (dB5 + dB6)) * C33;
461 dR[2] += (dC2 + dC3 + dC4) *
S3;
462 dA[2] = ((dC0 + 2. * dC3) + (dC5 + dC6)) * C33;
476 const double pi = 3.1415927;
477 const double pi2 = 2. *
pi;
479 const double Ax[3] = { T(0, 0), T(1, 0), T(2, 0) };
480 const double Ay[3] = { T(0, 1), T(1, 1), T(2, 1) };
482 const double R = Su.
bounds().
r();
483 double x =
Ro[0] - T(0, 3);
484 double y =
Ro[1] - T(1, 3);
485 double z =
Ro[2] - T(2, 3);
487 double RC =
x * Ax[0] +
y * Ax[1] +
z * Ax[2];
488 double RS =
x * Ay[0] +
y * Ay[1] +
z * Ay[2];
490 if ((RC * RC + RS * RS) <= (R * R))
496 RC =
x * Ax[0] +
y * Ax[1] +
z * Ax[2];
497 RS =
x * Ay[0] +
y * Ay[1] +
z * Ay[2];
507std::unique_ptr<Trk::TrackParameters>
511 Jac[0] = Jac[6] = Jac[12] = Jac[18] = Jac[20] = 1.;
512 Jac[1] = Jac[2] = Jac[3] = Jac[4] = Jac[5] = Jac[7] = Jac[8] = Jac[9] =
513 Jac[10] = Jac[11] = Jac[13] = Jac[14] = Jac[15] = Jac[16] = Jac[17] = Jac[19] = 0.;
514 return std::unique_ptr<Trk::TrackParameters>(
Tp.clone());
520std::unique_ptr<Trk::NeutralParameters>
524 Jac[0] = Jac[6] = Jac[12] = Jac[18] = Jac[20] = 1.;
525 Jac[1] = Jac[2] = Jac[3] = Jac[4] = Jac[5] = Jac[7] = Jac[8] = Jac[9] =
526 Jac[10] = Jac[11] = Jac[13] = Jac[14] = Jac[15] = Jac[16] = Jac[17] = Jac[19] = 0.;
527 return std::unique_ptr<Trk::NeutralParameters>(
Tp.clone());
533std::unique_ptr<Trk::TrackParameters>
535 std::vector<Trk::DestSurf>& SU,
536 std::vector<unsigned int>& So,
538 std::pair<double, int>& SN)
542 const double* SA = &
P[42];
543 const double Step = SN.first;
549 As[0] =
A[0] + SA[0] * Step;
550 As[1] =
A[1] + SA[1] * Step;
551 As[2] =
A[2] + SA[2] * Step;
552 const double CBA = 1. / std::sqrt(As[0] * As[0] + As[1] * As[1] + As[2] * As[2]);
554 Rs[0] = R[0] + Step * (As[0] - .5 * Step * SA[0]);
556 Rs[1] = R[1] + Step * (As[1] - .5 * Step * SA[1]);
558 Rs[2] = R[2] + Step * (As[2] - .5 * Step * SA[2]);
565 if (
ds.currentDistance(
false) > .010)
580 Tp.covariance() ? useJac = true : useJac =
false;
583 const double d = 1. /
P[6];
596 return SU[
N].first->createUniqueTrackParameters(p[0], p[1], p[2], p[3], p[4], std::nullopt);
600 if (!
Amg::hasPositiveOrZeroDiagElems(e)) {
603 return SU[
N].first->createUniqueTrackParameters(p[0], p[1], p[2], p[3], p[4],
611stepEstimatorWithCurvature(Cache& cache,
621 const double AStep = std::abs(Step);
622 if (kind || AStep < cache.m_straightStep || !cache.m_mcondition)
625 const double* SA = &
P[42];
626 const double S = .5 * Step;
628 const double Ax =
P[3] +
S * SA[0];
629 const double Ay =
P[4] +
S * SA[1];
630 const double Az =
P[5] +
S * SA[2];
631 const double As = 1. / std::sqrt(Ax * Ax + Ay * Ay + Az * Az);
633 const double PN[6] = {
P[0],
P[1],
P[2], Ax * As, Ay * As, Az * As };
639 if (std::abs(StepN) < AStep)
648propagateWithJacobian(Cache& cache,
655 const double Smax = 1000.;
656 const double Wmax = cache.m_maxPath;
657 const double Wwrong = 500.;
661 SA[0] = SA[1] = SA[2] = 0.;
662 cache.m_maxPathLimit =
false;
664 if (cache.m_mcondition && std::abs(
P[6]) > .1)
676 if (cache.m_mcondition && cache.m_direction && cache.m_direction * Step < 0.) {
681 Step > Smax ?
S = Smax : Step < -Smax ?
S = -Smax :
S = Step;
682 double So = std::abs(S);
690 cache.m_newfield =
true;
691 while (std::abs(Step) > cache.m_straightStep) {
696 if (cache.m_mcondition) {
698 if (!cache.m_needgradient)
699 W += (
S = rungeKuttaStep(cache, Jac, S,
P, InS));
701 W += (
S = rungeKuttaStepWithGradient(cache, S,
P, InS));
703 W += (
S = straightLineStep(Jac, S,
P));
706 Step = stepEstimatorWithCurvature(cache, kind, Su,
P, Q);
711 if (cache.m_direction && cache.m_direction * Step < 0.)
722 const double aS = std::abs(S);
723 const double aStep = std::abs(Step);
726 else if (!iS && InS && aS * 2. < aStep)
728 if (!dir && std::abs(W) > Wwrong)
731 if (iS > 10 || (iS > 3 && std::abs(S) >= So)) {
736 const double dW = Wmax - std::abs(W);
737 if (std::abs(S) > dW) {
738 S > 0. ?
S = dW :
S = -dW;
740 cache.m_maxPathLimit =
true;
749 if (std::abs(Step) < .001)
752 A[0] += (SA[0] * Step);
753 A[1] += (SA[1] * Step);
754 A[2] += (SA[2] * Step);
755 const double CBA = 1. / std::sqrt(
A[0] *
A[0] +
A[1] *
A[1] +
A[2] *
A[2]);
757 R[0] += Step * (
A[0] - .5 * Step * SA[0]);
759 R[1] += Step * (
A[1] - .5 * Step * SA[1]);
761 R[2] += Step * (
A[2] - .5 * Step * SA[2]);
766bool propagateWithJacobianSwitch(Cache& cache,
778 double s[6] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2), T(2, 2)};
779 return propagateWithJacobian(cache, useJac, 0, s,
P, Step);
785 T(0, 3) * T(0, 2) + T(1, 3) * T(1, 2) + T(2, 3) * T(2, 2);
798 return propagateWithJacobian(cache, useJac, 1, s,
P, Step);
804 const double r0[3] = {
P[0],
P[1],
P[2]};
805 double s[9] = {T(0, 3), T(1, 3), T(2, 3),
806 T(0, 2), T(1, 2), T(2, 2),
807 cyl->
bounds().
r(), cache.m_direction, 0.};
809 const bool status = propagateWithJacobian(cache, useJac, 2, s,
P, Step);
812 newCrossPoint(*cyl, r0,
P)) {
814 return propagateWithJacobian(cache, useJac, 2, s,
P, Step);
821 double s[9] = {T(0, 3), T(1, 3), T(2, 3), T(0, 2), T(1, 2),
822 T(2, 2),
k, cache.m_direction, 0.};
823 return propagateWithJacobian(cache, useJac, 3, s,
P, Step);
834std::unique_ptr<Trk::NeutralParameters>
835propagateStraightLine(Cache& cache,
845 if (su == &
Tp.associatedSurface()){
846 return buildTrackParametersWithoutPropagation(
Tp, Jac);
849 cache.m_direction = D;
850 cache.m_mcondition =
false;
858 if (!propagateWithJacobianSwitch(cache,Su,useJac,
P,Step)){
862 if (cache.m_direction != 0. && (cache.m_direction * Step) < 0.) {
869 const double p = 1. /
P[6];
878 if (cache.m_maxPathLimit)
900 if (!useJac || !
Tp.covariance()) {
906 return std::make_unique<Trk::NeutralCurvilinearParameters>(gp, p[2], p[3], p[4]);
912 if (!
Amg::hasPositiveOrZeroDiagElems(e)) {
920 return std::make_unique<Trk::NeutralCurvilinearParameters>(gp, p[2], p[3], p[4], std::move(e));
930globalOneSidePositions(Cache& cache,
931 std::deque<Amg::Vector3D>& GP,
937 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid =
false;
938 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true : cache.m_mcondition =
false;
941 for (
int i = 0;
i != 7; ++
i)
945 const double R2max =
CB.r() *
CB.r();
946 const double Zmax =
CB.halflengthZ();
947 double R2 =
P[0] *
P[0] +
P[1] *
P[1];
948 const double Dir =
P[0] *
P[3] +
P[1] *
P[4];
952 if (cache.m_mcondition && std::abs(
P[6]) > .1)
957 if (std::abs(
P[2]) > Zmax || R2 > R2max)
964 if (std::abs(Dir) < .00001)
970 for (
int s = 0;
s != 2; ++
s) {
972 cache.m_newfield =
true;
980 for (
int i = 0;
i != 7; ++
i)
982 p[42] =
p[43] =
p[44] = 0.;
984 while (W < 100000. && ++niter < 1000) {
986 if (cache.m_mcondition) {
987 W += (
S = rungeKuttaStep(cache, 0, S, p, InS));
989 W += (
S = straightLineStep(0, S, p));
991 if (InS && std::abs(2. * S) < mS)
1002 R2 =
p[0] *
p[0] +
p[1] *
p[1];
1014 if (std::abs(p[2]) > Zmax || R2 > R2max)
1016 if (!s &&
P[3] * p[3] +
P[4] * p[4] < 0.)
1021 if ((p[0] * p[3] + p[1] * p[4]) * Dir < 0.) {
1034 Pm[42] = Pm[43] = Pm[44] = 0.;
1037 for (
int s = 0;
s != 3; ++
s) {
1039 cache.m_newfield =
true;
1041 const double A = (1. - Pm[5]) * (1. + Pm[5]);
1044 S = -(Pm[0] * Pm[3] + Pm[1] * Pm[4]) /
A;
1045 if (std::abs(S) < 1. || ++niter > 1000)
1048 if (cache.m_mcondition) {
1049 W += rungeKuttaStep(cache, 0, S, Pm, InS);
1051 W += straightLineStep(0, S, Pm);
1065 const double x = GP.front().x();
1066 const double y = GP.front().y();
1067 if ((
x *
x +
y *
y) > (Pm[0] * Pm[0] + Pm[1] * Pm[1])) {
1082globalTwoSidePositions(Cache& cache,
1083 std::deque<Amg::Vector3D>& GP,
1089 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid =
false;
1090 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true : cache.m_mcondition =
false;
1093 const double R2max =
CB.r() *
CB.r();
1094 const double Zmax =
CB.halflengthZ();
1095 double R2 =
P[0] *
P[0] +
P[1] *
P[1];
1098 if (cache.m_mcondition && std::abs(
P[6]) > .1)
1103 if (std::abs(
P[2]) > Zmax || R2 > R2max)
1112 for (
int s = 0;
s != 2; ++
s) {
1114 cache.m_newfield =
true;
1120 for (
int i = 0;
i != 7; ++
i)
1122 p[42] =
p[43] =
p[44] = 0.;
1124 while (W < 100000. && ++niter < 1000) {
1126 if (cache.m_mcondition) {
1127 W += (
S = rungeKuttaStep(cache, 0, S, p, InS));
1129 W += (
S = straightLineStep(0, S, p));
1131 if (InS && std::abs(2. * S) < mS)
1142 R2 =
p[0] *
p[0] +
p[1] *
p[1];
1143 if (std::abs(p[2]) > Zmax || R2 > R2max)
1152std::unique_ptr<Trk::TrackParameters>
1153propagateRungeKutta(Cache& cache,
1165 cache.m_direction = D;
1167 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true
1168 : cache.m_solenoid =
false;
1169 (useJac && cache.m_usegradient) ? cache.m_needgradient =
true
1170 : cache.m_needgradient = false;
1171 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true
1172 : cache.m_mcondition =
false;
1174 if (su == &
Tp.associatedSurface())
1175 return buildTrackParametersWithoutPropagation(
Tp, Jac);
1183 if (!propagateWithJacobianSwitch(cache,Su,useJac,
P,Step)){
1187 if (cache.m_direction && (cache.m_direction * Step) < 0.) {
1190 cache.m_step = Step;
1195 const double p = 1. /
P[6];
1204 if (cache.m_maxPathLimit)
1224 if (!useJac || !
Tp.covariance()) {
1228 p[0], p[1], p[2], p[3], p[4], std::nullopt);
1231 return std::make_unique<Trk::CurvilinearParameters>(gp, p[2], p[3], p[4]);
1238 if (!
Amg::hasPositiveOrZeroDiagElems(e)) {
1244 p[0], p[1], p[2], p[3], p[4], std::move(e));
1247 return std::make_unique<Trk::CurvilinearParameters>(
1248 gp, p[2], p[3], p[4], std::move(e));
1257propagateRungeKutta(Cache& cache,
1274 cache.m_direction = D;
1279 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true
1280 : cache.m_solenoid =
false;
1281 (useJac && cache.m_usegradient) ? cache.m_needgradient =
true
1282 : cache.m_needgradient = false;
1283 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true
1284 : cache.m_mcondition =
false;
1292 if (!propagateWithJacobianSwitch(cache,Su,useJac,
P,Step)){
1296 if (cache.m_maxPathLimit ||
1297 (cache.m_direction && (cache.m_direction * Step) < 0.)){
1304 const double p = 1. /
P[6];
1322 Tb.setParametersWithCovariance(&Su, p, newCov);
1324 if (!
Amg::hasPositiveOrZeroDiagElems(cv))
1339 std::vector<const Trk::Surface*>& SU,
1340 std::vector<std::pair<Amg::Vector3D, double>>& GP,
1343 cache.m_direction = 0.;
1344 cache.m_mcondition =
false;
1345 cache.m_maxPath = 10000.;
1346 cache.m_needgradient =
false;
1347 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid =
false;
1348 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true : cache.m_mcondition =
false;
1356 auto su = SU.begin();
1357 auto sue = SU.end();
1359 for (; su != sue; ++su) {
1361 if (!propagateWithJacobianSwitch(cache, **su,
false,
P, Step)) {
1365 if (cache.m_maxPathLimit) {
1370 GP.emplace_back(gp, Step);
1381 const std::string& n,
1382 const IInterface* t)
1385 declareInterface<Trk::IPropagator>(
this);
1386 declareInterface<Trk::IPatternParametersPropagator>(
this);
1395 return StatusCode::SUCCESS;
1401std::unique_ptr<Trk::NeutralParameters>
1406 bool returnCurv)
const
1414 return propagateStraightLine(cache,
true,
Tp, Su, D, B, J, returnCurv);
1421std::unique_ptr<Trk::TrackParameters>
1433 Cache cache = getInitializedCache(ctx);
1434 return propagateRungeKutta(cache,
true,
Tp, Su, D, B, M, J, returnCurv);
1442 const ::EventContext& ctx,
1453 propagatedState.reserve(multiComponentState.size());
1456 Trk::MultiComponentState::const_iterator component =
1457 multiComponentState.begin();
1458 for (; component != multiComponentState.end(); ++component) {
1460 if (!currentParameters) {
1463 auto propagatedParameters =
1464 propagateRungeKutta(cache,
true, *currentParameters, surface, direction,
1465 boundaryCheck, fieldProperties, J,
false);
1467 if (!propagatedParameters) {
1470 sumw += component->weight;
1472 propagatedState.push_back({std::move(propagatedParameters),
1473 component->weight});
1476 constexpr double minPropWeight = (1./12.);
1477 if (sumw < minPropWeight) {
1478 propagatedState.clear();
1480 return propagatedState;
1487std::unique_ptr<Trk::TrackParameters>
1494 std::optional<TransportJacobian>& Jac,
1501 Cache cache = getInitializedCache(ctx);
1502 pathLength < 0. ? cache.m_maxPath = 10000. : cache.m_maxPath = pathLength;
1503 auto Tpn = propagateRungeKutta(cache,
true,
Tp, Su, D, B, M, J, returnCurv);
1504 pathLength = cache.m_step;
1512 Jac = std::make_optional<Trk::TransportJacobian>(J);
1521std::unique_ptr<Trk::TrackParameters>
1524 std::vector<DestSurf>& DS,
1528 std::vector<unsigned int>& Sol,
1535 Cache cache = getInitializedCache(ctx);
1536 Sol.erase(Sol.begin(), Sol.end());
1540 cache.m_direction = D;
1545 Tp.covariance() ? useJac = true : useJac =
false;
1549 M.magneticFieldMode() ==
Trk::FastField ? cache.m_solenoid = true : cache.m_solenoid =
false;
1550 (useJac && m_usegradient) ? cache.m_needgradient =
true : cache.m_needgradient = false;
1551 M.magneticFieldMode() !=
Trk::NoField ? cache.m_mcondition = true : cache.m_mcondition =
false;
1560 Po[42] = Po[43] = Po[44] = 0.;
1565 double S = cache.m_straightStep;
1568 S = straightLineStep(useJac, S, Po);
1570 double Wmax = 50000.;
1576 Wmax = std::abs(Path);
1578 std::multimap<double, int> DN;
1587 if (D == 0 && std::abs(Scut[0]) < std::abs(Scut[1]))
1590 if (Smax < 0. && Scut[0] > Smax)
1592 if (Smax > 0. && Scut[1] < Smax)
1594 if (Wmax > 3. * Scut[2])
1595 Wmax = 3. * Scut[2];
1601 for (
int i = 0;
i != 45; ++
i)
1605 double last_St = 0.;
1606 bool last_InS = !InS;
1607 bool reverted_P =
false;
1610 cache.m_newfield =
true;
1619 constexpr unsigned int max_back_forth_flips{ 100 };
1620 unsigned int flips{0};
1621 int last_surface{-1};
1623 while (std::abs(W) < Wmax) {
1625 std::pair<double, int> SN;
1628 if (cache.m_mcondition) {
1631 if (reverted_P && std::abs(St - last_St) <= DBL_EPSILON &&
1640 if (!cache.m_needgradient)
1641 S = rungeKuttaStep(cache, useJac, St, Pn, InS);
1643 S = rungeKuttaStepWithGradient(cache, St, Pn, InS);
1647 if (reverted_P && std::abs(St - last_St) <= DBL_EPSILON) {
1655 S = straightLineStep(useJac, St, Pn);
1664 for (
int i = 0;
i != 45; ++
i)
1669 for (
int i = 0;
i != 45; ++
i)
1672 cache.m_newfield =
true;
1675 if (std::abs(S) + 1. < std::abs(St))
1677 InS ? St = 2. *
S : St =
S;
1679 if (SN.second >= 0) {
1681 const double Sa = std::abs(SN.first);
1686 flips += last_surface == SN.second ? std::abs(last_St + SN.first) < 1.e-6
1688 last_surface = SN.second;
1691 if (Sa > cache.m_straightStep) {
1692 if (std::abs(St) > Sa)
1695 Path =
W + SN.first;
1696 if (
auto To{ crossPoint(
Tp, DS, Sol, Pn, SN) }; To){
1702 }
else if (std::abs(S) < DBL_EPSILON){
1706 if (flips > max_back_forth_flips) {
1717std::unique_ptr<Trk::TrackParameters>
1720 const Trk::Surface& Su,
1722 const Trk::BoundaryCheck& B,
1729 Cache cache = getInitializedCache(ctx);
1730 return propagateRungeKutta(cache,
false,
Tp, Su, D, B, M, J, returnCurv);
1737std::unique_ptr<Trk::TrackParameters>
1740 const Trk::Surface& Su,
1742 const Trk::BoundaryCheck& B,
1744 std::optional<TransportJacobian>& Jac,
1750 Cache cache = getInitializedCache(ctx);
1751 auto Tpn{ propagateRungeKutta(cache,
true,
Tp, Su, D, B, M, J, returnCurv) };
1759 Jac = std::make_optional<Trk::TransportJacobian>(J);
1772 std::deque<Amg::Vector3D>& GP,
1783 Cache cache = getInitializedCache(ctx);
1785 cache.m_direction = std::abs(mS);
1787 globalOneSidePositions(cache, GP,
P, M, CB, mS);
1789 globalTwoSidePositions(cache, GP,
P, M, CB, -mS);
1795std::optional<Trk::TrackSurfaceIntersection>
1803 bool const nJ =
false;
1814 return std::nullopt;
1817 if (!propagateWithJacobianSwitch(cache, (*su), nJ,
P, Step)) {
1818 return std::nullopt;
1823 return std::make_optional<Trk::TrackSurfaceIntersection>(Glo, Dir, Step);
1840 Cache cache = getInitializedCache(ctx);
1841 return propagateRungeKutta(cache,
true, Ta, Su, Tb, D, M, S);
1854 const MagneticFieldProperties& M,
1858 Cache cache = getInitializedCache(ctx);
1859 return propagateRungeKutta(cache,
true, Ta, Su, Tb, D, M, S);
1868 Trk::PatternTrackParameters& Ta,
1869 const Trk::Surface& Su,
1870 Trk::PatternTrackParameters& Tb,
1876 Cache cache = getInitializedCache(ctx);
1877 return propagateRungeKutta(cache,
false, Ta, Su, Tb, D, M, S);
1886 Trk::PatternTrackParameters& Ta,
1887 const Trk::Surface& Su,
1888 Trk::PatternTrackParameters& Tb,
1894 Cache cache = getInitializedCache(ctx);
1895 return propagateRungeKutta(cache,
false, Ta, Su, Tb, D, M, S);
1904 std::vector<const Trk::Surface*>& SU,
1905 std::vector<std::pair<Amg::Vector3D, double>>& GP,
1906 const Trk::MagneticFieldProperties& M,
1909 Cache cache = getInitializedCache(ctx);
1910 globalPositionsImpl(cache,
Tp, SU, GP, M);
#define ATH_CHECK
Evaluate an expression and check for errors.
#define AmgSymMatrix(dim)
struct TBPatternUnitContext S3
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
The BoundaryCheck class allows to steer the way surface boundaries are used for inside/outside checks...
Class for a conical surface in the ATLAS detector.
Bounds for a cylindrical Surface.
virtual double r() const override final
This method returns the radius.
double halfPhiSector() const
This method returns the halfPhiSector angle.
double averagePhi() const
This method returns the average phi.
Class for a CylinderSurface in the ATLAS detector.
virtual const CylinderBounds & bounds() const override final
This method returns the CylinderBounds by reference (NoBounds is not possible for cylinder)
Access to distance solutions.
magnetic field properties to steer the behavior of the extrapolation
virtual const Surface & associatedSurface() const override final
Access to the Surface associated to the Parameters.
void setParameters(const Surface *, const double *)
bool iscovariance() const
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
virtual StatusCode initialize() override final
RungeKuttaPropagator(const std::string &, const std::string &, const IInterface *)
virtual Trk::MultiComponentState multiStatePropagate(const EventContext &ctx, const MultiComponentState &multiComponentState, const Surface &surface, const MagneticFieldProperties &fieldProperties, const PropDirection direction=Trk::anyDirection, const BoundaryCheck &boundaryCheck=true, const ParticleHypothesis particleHypothesis=nonInteracting) const override final
Main propagation method for Multi Component state.
DoubleProperty m_helixStep
virtual std::unique_ptr< TrackParameters > propagateParameters(const EventContext &ctx, const TrackParameters &, const Surface &, const PropDirection, const BoundaryCheck &, const MagneticFieldProperties &, ParticleHypothesis, bool, const TrackingVolume *) const override final
Main propagation method for parameters only.
DoubleProperty m_straightStep
virtual std::unique_ptr< NeutralParameters > propagate(const NeutralParameters &, const Surface &, PropDirection, const BoundaryCheck &, bool) const override final
Main propagation method for NeutralParameters.
Cache getInitializedCache(const EventContext &ctx) const
BooleanProperty m_usegradient
virtual std::optional< Trk::TrackSurfaceIntersection > intersect(const EventContext &ctx, const TrackParameters &, const Surface &, const MagneticFieldProperties &, ParticleHypothesis, const TrackingVolume *tvol=nullptr) const override final
Global position together with direction of the trajectory on the surface.
virtual void globalPositions(const EventContext &ctx, std::deque< Amg::Vector3D > &, const TrackParameters &, const MagneticFieldProperties &, const CylinderBounds &, double, ParticleHypothesis, const TrackingVolume *tvol=nullptr) const override final
GlobalPositions list interface:
Abstract Base Class for tracking surfaces.
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
virtual NeutralTrackParametersUniquePtr createUniqueNeutralParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - neutral.
virtual ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theat, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const =0
Use the Surface as a ParametersBase constructor, from local parameters - charged.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
virtual constexpr SurfaceType type() const =0
Returns the Surface type to avoid dynamic casts.
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
Definition of ATLAS Math & Geometry primitives (Amg)
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Trk::RungeKuttaUtils is set algorithms for track parameters transformation from local to global and g...
const double r0
electron radius{cm}
void transformGlobalToCurvilinear(bool, double *ATH_RESTRICT, double *ATH_RESTRICT, double *ATH_RESTRICT)
bool transformLocalToGlobal(bool, const Trk::TrackParameters &, double *ATH_RESTRICT)
void transformGlobalToLocal(double *ATH_RESTRICT, double *ATH_RESTRICT)
int fillDistancesMap(std::vector< std::pair< const Trk::Surface *, Trk::BoundaryCheck > > &, std::multimap< double, int > &, const double *ATH_RESTRICT, double, const Trk::Surface *, double *ATH_RESTRICT)
double stepEstimator(int kind, double *ATH_RESTRICT Su, const double *ATH_RESTRICT P, bool &Q)
Ensure that the ATLAS eigen extensions are properly loaded.
PropDirection
PropDirection, enum for direction of the propagation.
SurfaceType
This enumerator simplifies the persistency & calculations,.
ATH_ALWAYS_INLINE void propJacobian(double *ATH_RESTRICT P, const double *ATH_RESTRICT H0, const double *ATH_RESTRICT H1, const double *ATH_RESTRICT H2, const double *ATH_RESTRICT A, const double *ATH_RESTRICT A0, const double *ATH_RESTRICT A3, const double *ATH_RESTRICT A4, const double *ATH_RESTRICT A6, const double S3)
This provides an inline helper function for updating the jacobian during Runge-Kutta propagation.
std::vector< ComponentParameters > MultiComponentState
ParametersBase< NeutralParametersDim, Neutral > NeutralParameters
@ FastField
call the fast field access method of the FieldSvc
@ NoField
Field is set to 0., 0., 0.,.
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters
Macro wrapping the nonstandard restrict keyword.
hold the test vectors and ease the comparison
MagField::AtlasFieldCache m_fieldCache