Project
Loading...
Searching...
No Matches
Propagator.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13#include "GPUCommonLogger.h"
14#include "GPUCommonConstants.h"
15#include "GPUCommonMath.h"
17#include "MathUtils/Utils.h"
20
21using namespace o2::base;
22using namespace o2::gpu;
23
24#if !defined(GPUCA_GPUCODE)
25#include "Field/MagFieldFast.h" // Don't use this on the GPU
26#endif
27
28#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
29#include "Field/MagneticField.h"
33#include <FairRunAna.h> // eventually will get rid of it
34#include <TGeoGlobalMagField.h>
35
36template <typename value_T>
38{
39 if (uninitialized) {
40 return;
41 }
43 updateField();
44}
45
46//____________________________________________________________
47template <typename value_T>
49{
50 if (!mField) {
51 mField = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
52 if (!mField) {
53 LOG(warning) << "No Magnetic Field in TGeoGlobalMagField, checking legacy FairRunAna";
54 mField = dynamic_cast<o2::field::MagneticField*>(FairRunAna::Instance()->GetField());
55 }
56 if (!mField) {
57 LOG(fatal) << "Magnetic field is not initialized!";
58 }
59 if (!mField->getFastField() && mField->fastFieldExists()) {
60 mField->AllowFastField(true);
61 mFieldFast = mField->getFastField();
62 }
63 }
64 const value_type xyz[3] = {0.};
65 if (mFieldFast) {
66 mFieldFast->GetBz(xyz, mNominalBz);
67 } else {
68 mNominalBz = mField->GetBz(xyz[0], xyz[1], xyz[2]);
69 }
70}
71
72//____________________________________________________________
73template <typename value_T>
74int PropagatorImpl<value_T>::initFieldFromGRP(const std::string grpFileName, bool verbose)
75{
77 if (verbose) {
78 LOG(info) << "Loading field from GRP of " << grpFileName;
79 }
80 const auto grp = o2::parameters::GRPObject::loadFrom(grpFileName);
81 if (!grp) {
82 return -1;
83 }
84 if (verbose) {
85 grp->print();
86 }
87
88 return initFieldFromGRP(grp);
89}
90
91//____________________________________________________________
92template <typename value_T>
94{
96
97 if (TGeoGlobalMagField::Instance()->IsLocked()) {
98 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
99 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
100 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
101 return 0;
102 } else {
103 LOG(info) << "Destroying existing B field instance";
104 delete TGeoGlobalMagField::Instance();
105 }
106 }
108 TGeoGlobalMagField::Instance()->SetField(fld);
109 TGeoGlobalMagField::Instance()->Lock();
110 if (verbose) {
111 LOG(info) << "Running with the B field constructed out of GRP";
112 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
113 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
114 }
115 return 0;
116}
117
118//____________________________________________________________
119template <typename value_T>
121{
123
124 if (TGeoGlobalMagField::Instance()->IsLocked()) {
125 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
126 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
127 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
128 return 0;
129 } else {
130 LOG(info) << "Destroying existing B field instance";
131 delete TGeoGlobalMagField::Instance();
132 }
133 }
135 TGeoGlobalMagField::Instance()->SetField(fld);
136 TGeoGlobalMagField::Instance()->Lock();
137 if (verbose) {
138 LOG(info) << "Running with the B field constructed out of GRP";
139 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
140 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
141 }
142 return 0;
143}
144
145#elif !defined(GPUCA_GPUCODE)
146template <typename value_T>
148{
149} // empty dummy constructor for standalone benchmark
150#endif
151
152//_______________________________________________________________________
153template <typename value_T>
154GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackParCov_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
155 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
156{
157 //----------------------------------------------------------------
158 //
159 // Propagates the track to the plane X=xk (cm)
160 // taking into account all the three components of the magnetic field
161 // and correcting for the crossed material.
162 //
163 // maxStep - maximal step for propagation
164 // tofInfo - optional container for track length and PID-dependent TOF integration
165 //
166 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
167 //----------------------------------------------------------------
168 auto dx = xToGo - track.getX();
169 int dir = dx > 0.f ? 1 : -1;
170 if (!signCorr) {
171 signCorr = -dir; // sign of eloss correction is not imposed
172 }
173
174 std::array<value_type, 3> b{};
175 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
176 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
177 if (dir < 0) {
178 step = -step;
179 }
180 auto x = track.getX() + step;
181 auto xyz0 = track.getXYZGlo();
182 getFieldXYZ(xyz0, &b[0]);
184 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
185 bool res = true;
186 if (matCorr != MatCorrType::USEMatCorrNONE) {
187 auto xyz1 = track.getXYZGlo();
188 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
189 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
190 res = false;
191 }
192 if (tofInfo) {
193 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
194 tofInfo->addX2X0(mb.meanX2X0);
195 tofInfo->addXRho(mb.getXRho(signCorr));
196 }
197 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
198 auto xyz1 = track.getXYZGlo();
199 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
200 tofInfo->addStep(stepV.R(), track.getQ2P2());
201 }
202 return res;
203 };
204
205 if (!track.propagateTo(x, b)) {
206 return false;
207 }
208 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
209 correct();
210 return false;
211 }
212 if (!correct()) {
213 return false;
214 }
215 dx = xToGo - track.getX();
216 }
217 track.setX(xToGo);
218 return true;
219}
220
221//_______________________________________________________________________
222template <typename value_T>
223GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackParCov_t& track, TrackPar_t& linRef, value_type xToGo, value_type maxSnp, value_type maxStep,
224 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
225{
226 //----------------------------------------------------------------
227 //
228 // Propagates the track to the plane X=xk (cm), using linRef as a Kalman linearisation point.
229 // taking into account all the three components of the magnetic field
230 // and correcting for the crossed material.
231 //
232 // maxStep - maximal step for propagation
233 // tofInfo - optional container for track length and PID-dependent TOF integration
234 //
235 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
236 //----------------------------------------------------------------
237 auto dx = xToGo - track.getX();
238 int dir = dx > 0.f ? 1 : -1;
239 if (!signCorr) {
240 signCorr = -dir; // sign of eloss correction is not imposed
241 }
242
243 std::array<value_type, 3> b{};
244 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
245 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
246 if (dir < 0) {
247 step = -step;
248 }
249 auto x = track.getX() + step;
250 auto xyz0 = linRef.getXYZGlo();
251 getFieldXYZ(xyz0, &b[0]);
252
253 auto correct = [&track, &linRef, &xyz0, tofInfo, matCorr, signCorr, this]() {
254 bool res = true;
255 if (matCorr != MatCorrType::USEMatCorrNONE) {
256 auto xyz1 = linRef.getXYZGlo();
257 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
258 if (!track.correctForMaterial(linRef, mb.meanX2X0, mb.getXRho(signCorr))) {
259 res = false;
260 }
261 if (tofInfo) {
262 tofInfo->addStep(mb.length, linRef.getQ2P2()); // fill L,ToF info using already calculated step length
263 tofInfo->addX2X0(mb.meanX2X0);
264 tofInfo->addXRho(mb.getXRho(signCorr));
265 }
266 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
267 auto xyz1 = linRef.getXYZGlo();
268 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
269 tofInfo->addStep(stepV.R(), linRef.getQ2P2());
270 }
271 return res;
272 };
273
274 if (!track.propagateTo(x, linRef, b)) {
275 return false;
276 }
277 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
278 correct();
279 return false;
280 }
281 if (!correct()) {
282 return false;
283 }
284 dx = xToGo - track.getX();
285 }
286 track.setX(xToGo);
287 return true;
288}
289
290//_______________________________________________________________________
291template <typename value_T>
292GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackPar_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
293 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
294{
295 //----------------------------------------------------------------
296 //
297 // Propagates the track params to the plane X=xk (cm), NO error evaluation
298 // taking into account all the three components of the magnetic field
299 // and optionally correcting for the e.loss crossed material.
300 //
301 // maxStep - maximal step for propagation
302 // tofInfo - optional container for track length and PID-dependent TOF integration
303 //
304 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
305 //----------------------------------------------------------------
306 auto dx = xToGo - track.getX();
307 int dir = dx > 0.f ? 1 : -1;
308 if (!signCorr) {
309 signCorr = -dir; // sign of eloss correction is not imposed
310 }
311
312 std::array<value_type, 3> b{};
313 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
314 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
315 if (dir < 0) {
316 step = -step;
317 }
318 auto x = track.getX() + step;
319 auto xyz0 = track.getXYZGlo();
320 getFieldXYZ(xyz0, &b[0]);
321
322 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
323 bool res = true;
324 if (matCorr != MatCorrType::USEMatCorrNONE) {
325 auto xyz1 = track.getXYZGlo();
326 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
327 if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) {
328 res = false;
329 }
330 if (tofInfo) {
331 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
332 tofInfo->addX2X0(mb.meanX2X0);
333 tofInfo->addXRho(mb.getXRho(signCorr));
334 }
335 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
336 auto xyz1 = track.getXYZGlo();
337 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
338 tofInfo->addStep(stepV.R(), track.getQ2P2());
339 }
340 return res;
341 };
342
343 if (!track.propagateParamTo(x, b)) {
344 return false;
345 }
346 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
347 correct();
348 return false;
349 }
350 if (!correct()) {
351 return false;
352 }
353 dx = xToGo - track.getX();
354 }
355 track.setX(xToGo);
356 return true;
357}
358
359//_______________________________________________________________________
360template <typename value_T>
361GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackParCov_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
362 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
363{
364 //----------------------------------------------------------------
365 //
366 // Propagates the track to the plane X=xk (cm)
367 // Use bz only and correct for the crossed material.
368 //
369 // maxStep - maximal step for propagation
370 // tofInfo - optional container for track length and PID-dependent TOF integration
371 //
372 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
373 //----------------------------------------------------------------
374 auto dx = xToGo - track.getX();
375 int dir = dx > 0.f ? 1 : -1;
376 if (!signCorr) {
377 signCorr = -dir; // sign of eloss correction is not imposed
378 }
379
380 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
381 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
382 if (dir < 0) {
383 step = -step;
384 }
385 auto x = track.getX() + step;
386 auto xyz0 = track.getXYZGlo();
387 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
388 bool res = true;
389 if (matCorr != MatCorrType::USEMatCorrNONE) {
390 auto xyz1 = track.getXYZGlo();
391 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
392 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
393 res = false;
394 }
395 if (tofInfo) {
396 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
397 tofInfo->addX2X0(mb.meanX2X0);
398 tofInfo->addXRho(mb.getXRho(signCorr));
399 }
400 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
401 auto xyz1 = track.getXYZGlo();
402 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
403 tofInfo->addStep(stepV.R(), track.getQ2P2());
404 }
405 return res;
406 };
407 if (!track.propagateTo(x, bZ)) {
408 return false;
409 }
410 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
411 correct();
412 return false;
413 }
414 if (!correct()) {
415 return false;
416 }
417 dx = xToGo - track.getX();
418 }
419 track.setX(xToGo);
420 return true;
421}
422
423//_______________________________________________________________________
424template <typename value_T>
425GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackParCov_t& track, TrackPar_t& linRef, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
426 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
427{
428 //----------------------------------------------------------------
429 //
430 // Propagates the track to the plane X=xk (cm), using linRef as a Kalman linearisation point.
431 // Use bz only and correct for the crossed material if requested.
432 //
433 // maxStep - maximal step for propagation
434 // tofInfo - optional container for track length and PID-dependent TOF integration
435 //
436 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
437 //----------------------------------------------------------------
438 auto dx = xToGo - track.getX();
439 int dir = dx > 0.f ? 1 : -1;
440 if (!signCorr) {
441 signCorr = -dir; // sign of eloss correction is not imposed
442 }
443
444 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
445 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
446 if (dir < 0) {
447 step = -step;
448 }
449 auto x = track.getX() + step;
450 auto xyz0 = linRef.getXYZGlo();
451
452 auto correct = [&track, &linRef, &xyz0, tofInfo, matCorr, signCorr, this]() {
453 bool res = true;
454 if (matCorr != MatCorrType::USEMatCorrNONE) {
455 auto xyz1 = linRef.getXYZGlo();
456 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
457 if (!track.correctForMaterial(linRef, mb.meanX2X0, mb.getXRho(signCorr))) {
458 res = false;
459 }
460 if (tofInfo) {
461 tofInfo->addStep(mb.length, linRef.getQ2P2()); // fill L,ToF info using already calculated step length
462 tofInfo->addX2X0(mb.meanX2X0);
463 tofInfo->addXRho(mb.getXRho(signCorr));
464 }
465 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
466 auto xyz1 = linRef.getXYZGlo();
467 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
468 tofInfo->addStep(stepV.R(), linRef.getQ2P2());
469 }
470 return res;
471 };
472
473 if (!track.propagateTo(x, linRef, bZ)) { // linRef also updated
474 return false;
475 }
476 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
477 correct();
478 return false;
479 }
480 if (!correct()) {
481 return false;
482 }
483 dx = xToGo - track.getX();
484 }
485 track.setX(xToGo);
486 return true;
487}
488
489//_______________________________________________________________________
490template <typename value_T>
491GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackPar_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
492 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
493{
494 //----------------------------------------------------------------
495 //
496 // Propagates the track parameters only to the plane X=xk (cm)
497 // taking into account all the three components of the magnetic field
498 // and correcting for the crossed material.
499 //
500 // maxStep - maximal step for propagation
501 // tofInfo - optional container for track length and PID-dependent TOF integration
502 //
503 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
504 //----------------------------------------------------------------
505 auto dx = xToGo - track.getX();
506 int dir = dx > 0.f ? 1 : -1;
507 if (!signCorr) {
508 signCorr = -dir; // sign of eloss correction is not imposed
509 }
510
511 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
512 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
513 if (dir < 0) {
514 step = -step;
515 }
516 auto x = track.getX() + step;
517 auto xyz0 = track.getXYZGlo();
518
519 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
520 bool res = true;
521 if (matCorr != MatCorrType::USEMatCorrNONE) {
522 auto xyz1 = track.getXYZGlo();
523 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
524 if (!track.correctForELoss(mb.getXRho(signCorr))) {
525 res = false;
526 }
527 if (tofInfo) {
528 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
529 tofInfo->addX2X0(mb.meanX2X0);
530 tofInfo->addXRho(mb.getXRho(signCorr));
531 }
532 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
533 auto xyz1 = track.getXYZGlo();
534 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
535 tofInfo->addStep(stepV.R(), track.getQ2P2());
536 }
537 return res;
538 };
539
540 if (!track.propagateParamTo(x, bZ)) {
541 return false;
542 }
543 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
544 correct();
545 return false;
546 }
547 if (!correct()) {
548 return false;
549 }
550 dx = xToGo - track.getX();
551 }
552 track.setX(xToGo);
553 return true;
554}
555
556//_______________________________________________________________________
557template <typename value_T>
558template <typename track_T>
559GPUd() bool PropagatorImpl<value_T>::propagateToR(track_T& track, value_type r, bool bzOnly, value_type maxSnp, value_type maxStep,
560 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
561{
562 const value_T MaxPhiLoc = math_utils::detail::asin<value_T>(maxSnp), MaxPhiLocSafe = 0.95 * MaxPhiLoc;
563 auto bz = getNominalBz();
564 if (math_utils::detail::abs(bz) > constants::math::Almost0) {
565 o2::track::TrackAuxPar traux(track, bz);
567 value_type r0 = math_utils::detail::sqrt<value_T>(track.getX() * track.getX() + track.getY() * track.getY());
568 value_type dr = (r - r0);
569 value_type rTmp = r - (math_utils::detail::abs<value_T>(dr) > 1. ? (dr > 0 ? 0.5 : -0.5) : 0.5 * dr); // 1st propagate a few mm short of the targer R
570 crad.rC = rTmp;
571 crad.c = crad.cc = 1.f;
572 crad.s = crad.ss = crad.cs = 0.f;
574 cross.circlesCrossInfo(crad, traux, 0.);
575 if (cross.nDCA < 1) {
576 return false;
577 }
578 double phiCross[2] = {}, dphi[2] = {};
579 auto curv = track.getCurvature(bz);
580 bool clockwise = curv < 0; // q+ in B+ or q- in B- goes clockwise
581 auto phiLoc = math_utils::detail::asin<double>(track.getSnp());
582 auto phi0 = phiLoc + track.getAlpha();
584 for (int i = 0; i < cross.nDCA; i++) {
585 // track pT direction angle at crossing points:
586 // == angle of the tangential to track circle at the crossing point X,Y
587 // == normal to the radial vector from the track circle center {X-cX, Y-cY}
588 // i.e. the angle of the vector {Y-cY, -(X-cx)}
589 auto normX = double(cross.yDCA[i]) - double(traux.yC), normY = -(double(cross.xDCA[i]) - double(traux.xC));
590 if (!clockwise) {
591 normX = -normX;
592 normY = -normY;
593 }
594 phiCross[i] = math_utils::detail::atan2<double>(normY, normX);
596 dphi[i] = phiCross[i] - phi0;
597 if (dphi[i] > o2::constants::math::PI) {
599 } else if (dphi[i] < -o2::constants::math::PI) {
601 }
602 }
603 int sel = cross.nDCA == 1 ? 0 : (clockwise ? (dphi[0] < dphi[1] ? 0 : 1) : (dphi[1] < dphi[0] ? 0 : 1));
604 auto deltaPhi = dphi[sel];
605
606 while (1) {
607 auto phiLocFin = phiLoc + deltaPhi;
608 // case1
609 if (math_utils::detail::abs<value_type>(phiLocFin) < MaxPhiLocSafe) { // just 1 step propagation
610 auto deltaX = (math_utils::detail::sin<double>(phiLocFin) - track.getSnp()) / track.getCurvature(bz);
611 if (!track.propagateTo(track.getX() + deltaX, bz)) {
612 return false;
613 }
614 break;
615 }
616 if (math_utils::detail::abs<value_type>(deltaPhi) < (2 * MaxPhiLocSafe)) { // still can go in 1 step with one extra rotation
617 auto rot = phiLoc + 0.5 * deltaPhi;
618 if (!track.rotate(track.getAlpha() + rot)) {
619 return false;
620 }
621 phiLoc -= rot;
622 continue; // should be ok for the case 1 now.
623 }
624
625 auto rot = phiLoc + (deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe);
626 if (!track.rotate(track.getAlpha() + rot)) {
627 return false;
628 }
629 phiLoc -= rot; // = +- MaxPhiLocSafe
630
631 // propagate to phiLoc = +-MaxPhiLocSafe
632 auto tgtPhiLoc = deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe;
633 auto deltaX = (math_utils::detail::sin<double>(tgtPhiLoc) - track.getSnp()) / track.getCurvature(bz);
634 if (!track.propagateTo(track.getX() + deltaX, bz)) {
635 return false;
636 }
637 deltaPhi -= tgtPhiLoc - phiLoc;
638 phiLoc = deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe;
639 continue; // should be of for the case 1 now.
640 }
641 bz = getBz(math_utils::Point3D<value_type>{value_type(cross.xDCA[sel]), value_type(cross.yDCA[sel]), value_type(track.getZ())});
642 }
643 // do final step till target R, also covers Bz = 0;
644 value_type xfin;
645 if (!track.getXatLabR(r, xfin, bz)) {
646 return false;
647 }
648 return propagateToX(track, xfin, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr);
649}
650
651template <typename value_T>
652GPUd() bool PropagatorImpl<value_T>::propagateToAlphaX(TrackParCov_t& track, TrackPar_t* linRef, value_type alpha, value_type x, bool bzOnly, value_type maxSnp, value_type maxStep, int minSteps,
653 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
654{
655 // propagate to alpha,X, if needed in a few steps
656 auto snp = track.getSnpAt(alpha, x, getNominalBz());
657 // apply safety factor 0.9 for crude rotation estimate
658 if (math_utils::detail::abs<value_type>(snp) < maxSnp * 0.9 && (linRef ? track.rotate(alpha, *linRef, getNominalBz()) : track.rotate(alpha))) {
659 auto dx = math_utils::detail::abs<value_type>(x - track.getX());
660 if (dx < Epsilon) {
661 return true;
662 }
663 return propagateTo(track, linRef, x, bzOnly, maxSnp, math_utils::detail::min<value_type>(dx / minSteps, maxStep), matCorr, tofInfo, signCorr);
664 }
665 return false;
666}
667
668//_______________________________________________________________________
669template <typename value_T>
670template <typename track_T>
671GPUd() bool PropagatorImpl<value_T>::propagateToAlphaX(track_T& track, value_type alpha, value_type x, bool bzOnly, value_type maxSnp, value_type maxStep, int minSteps,
672 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
673{
674 // propagate to alpha,X, if needed in a few steps
675 auto snp = track.getSnpAt(alpha, x, getNominalBz());
676 // apply safety factor 0.9 for crude rotation estimate
677 if (math_utils::detail::abs<value_type>(snp) < maxSnp * 0.9 && track.rotate(alpha)) {
678 auto dx = math_utils::detail::abs<value_type>(x - track.getX());
679 if (dx < Epsilon) {
680 return true;
681 }
682 return propagateTo(track, x, bzOnly, maxSnp, math_utils::detail::min<value_type>(dx / minSteps, maxStep), matCorr, tofInfo, signCorr);
683 }
684 return false;
685 /*
686 // try to go in a few steps with intermediate rotations
687
688
689 auto alphaTrg = alpha;
690 math_utils::detail::bringToPMPi<value_type>(alphaTrg);
691 auto alpCurr = track.getAlpha();
692 math_utils::detail::bringToPMPi<value_type>(alpCurr);
693 int nsteps = minSteps > 2 ? minSteps : 2;
694 auto dalp = math_utils::detail::deltaPhiSmall<value_type>(alpCurr, alphaTrg) / nsteps; // effective (alpha - alphaCurr)/nsteps
695 auto xtmp = (track.getX() + x) / nsteps;
696 return track.rotate(alpCurr + dalp) && propagateTo(track, xtmp, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr) &&
697 track.rotate(alpha) && propagateTo(track, x, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr);
698 */
699}
700
701//_______________________________________________________________________
702template <typename value_T>
703GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track, value_type bZ,
704 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
705 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
706 int signCorr, value_type maxD) const
707{
708 // propagate track to DCA to the vertex
709 value_type sn, cs, alp = track.getAlpha();
710 math_utils::detail::sincos<value_type>(alp, sn, cs);
711 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
712 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
713 x -= xv;
714 y -= yv;
715 // Estimate the impact parameter neglecting the track curvature
716 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
717 if (d > maxD) {
718 if (dca) { // provide default DCA for failed propag
721 }
722 return false;
723 }
724 value_type crv = track.getCurvature(bZ);
725 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
726 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
727 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
728 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
729
730 x = xv * cs + yv * sn;
731 yv = -xv * sn + yv * cs;
732 xv = x;
733
734 auto tmpT(track); // operate on the copy to recover after the failure
735 alp += math_utils::detail::asin<value_type>(sn);
736 if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
737#ifndef GPUCA_ALIGPUCODE
738 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
739#elif !defined(GPUCA_NO_FMT)
740 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
741#endif
742 if (dca) { // provide default DCA for failed propag
745 }
746 return false;
747 }
748 track = tmpT;
749 if (dca) {
750 math_utils::detail::sincos<value_type>(alp, sn, cs);
751 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
752 dca->set(track.getY() - yv, track.getZ() - zv,
753 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
754 }
755 return true;
756}
757
758//_______________________________________________________________________
759template <typename value_T>
760GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track,
761 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
762 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
763 int signCorr, value_type maxD) const
764{
765 // propagate track to DCA to the vertex
766 value_type sn, cs, alp = track.getAlpha();
767 math_utils::detail::sincos<value_type>(alp, sn, cs);
768 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
769 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
770 x -= xv;
771 y -= yv;
772 // Estimate the impact parameter neglecting the track curvature
773 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
774 if (d > maxD) {
775 if (dca) { // provide default DCA for failed propag
778 }
779 return false;
780 }
781 value_type crv = track.getCurvature(mNominalBz);
782 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
783 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
784 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
785 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
786
787 x = xv * cs + yv * sn;
788 yv = -xv * sn + yv * cs;
789 xv = x;
790
791 auto tmpT(track); // operate on the copy to recover after the failure
792 alp += math_utils::detail::asin<value_type>(sn);
793 if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
794#ifndef GPUCA_ALIGPUCODE
795 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
796#elif !defined(GPUCA_NO_FMT)
797 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
798#endif
799 if (dca) { // provide default DCA for failed propag
802 }
803 return false;
804 }
805 track = tmpT;
806 if (dca) {
807 math_utils::detail::sincos<value_type>(alp, sn, cs);
808 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
809 dca->set(track.getY() - yv, track.getZ() - zv,
810 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
811 }
812 return true;
813}
814
815//_______________________________________________________________________
816template <typename value_T>
817GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track, value_type bZ,
818 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
819 std::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
820 int signCorr, value_type maxD) const
821{
822 // propagate track to DCA to the vertex
823 value_type sn, cs, alp = track.getAlpha();
824 math_utils::detail::sincos<value_type>(alp, sn, cs);
825 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
826 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
827 x -= xv;
828 y -= yv;
829 // Estimate the impact parameter neglecting the track curvature
830 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
831 if (d > maxD) {
832 if (dca) { // provide default DCA for failed propag
833 (*dca)[0] = o2::track::DefaultDCA;
834 (*dca)[1] = o2::track::DefaultDCA;
835 }
836 return false;
837 }
838 value_type crv = track.getCurvature(bZ);
839 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
840 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
841 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
842 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
843
844 x = xv * cs + yv * sn;
845 yv = -xv * sn + yv * cs;
846 xv = x;
847
848 auto tmpT(track); // operate on the copy to recover after the failure
849 alp += math_utils::detail::asin<value_type>(sn);
850 if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
851#ifndef GPUCA_ALIGPUCODE
852 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
853 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
854#else
855 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
856#endif
857 if (dca) { // provide default DCA for failed propag
858 (*dca)[0] = o2::track::DefaultDCA;
859 (*dca)[1] = o2::track::DefaultDCA;
860 }
861 return false;
862 }
863 track = tmpT;
864 if (dca) {
865 (*dca)[0] = track.getY() - yv;
866 (*dca)[1] = track.getZ() - zv;
867 }
868 return true;
869}
870
871//_______________________________________________________________________
872template <typename value_T>
873GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track,
874 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
875 std::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
876 int signCorr, value_type maxD) const
877{
878 // propagate track to DCA to the vertex
879 value_type sn, cs, alp = track.getAlpha();
880 math_utils::detail::sincos<value_type>(alp, sn, cs);
881 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
882 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
883 x -= xv;
884 y -= yv;
885 // Estimate the impact parameter neglecting the track curvature
886 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
887 if (d > maxD) {
888 if (dca) { // provide default DCA for failed propag
889 (*dca)[0] = o2::track::DefaultDCA;
890 (*dca)[1] = o2::track::DefaultDCA;
891 }
892 return false;
893 }
894 value_type crv = track.getCurvature(mNominalBz);
895 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
896 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
897 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
898 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
899
900 x = xv * cs + yv * sn;
901 yv = -xv * sn + yv * cs;
902 xv = x;
903
904 auto tmpT(track); // operate on the copy to recover after the failure
905 alp += math_utils::detail::asin<value_type>(sn);
906 if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
907#ifndef GPUCA_ALIGPUCODE
908 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
909 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
910#else
911 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
912#endif
913 if (dca) { // provide default DCA for failed propag
914 (*dca)[0] = o2::track::DefaultDCA;
915 (*dca)[1] = o2::track::DefaultDCA;
916 }
917 return false;
918 }
919 track = tmpT;
920 if (dca) {
921 (*dca)[0] = track.getY() - yv;
922 (*dca)[1] = track.getZ() - zv;
923 }
924 return true;
925}
926
927//____________________________________________________________
928template <typename value_T>
929GPUd() float PropagatorImpl<value_T>::estimateLTIncrement(const o2::track::TrackParametrization<value_type>& trc,
930 const o2::math_utils::Point3D<value_type>& posStart,
931 const o2::math_utils::Point3D<value_type>& posEnd) const
932{
933 // estimate helical step increment between 2 point
934 float dX = posEnd.X() - posStart.X(), dY = posEnd.Y() - posStart.Y(), dZ = posEnd.Z() - posStart.Z(), d2XY = dX * dX + dY * dY;
935 if (getNominalBz() != 0) { // circular arc = 2*R*asin(dXY/2R)
936 float b[3];
937 o2::math_utils::Point3D<float> posAv(0.5 * (posEnd.X() + posStart.X()), 0.5 * (posEnd.Y() + posStart.Y()), 0.5 * (posEnd.Z() + posStart.Z()));
938 getFieldXYZ(posAv, b);
939 float curvH = math_utils::detail::abs<value_type>(0.5f * trc.getCurvature(b[2])), asArg = curvH * math_utils::detail::sqrt<value_type>(d2XY);
940 if (curvH > 0.f) {
941 d2XY = asArg < 1.f ? math_utils::detail::asin<value_type>(asArg) / curvH : o2::constants::math::PIHalf / curvH;
942 d2XY *= d2XY;
943 }
944 }
945 return math_utils::detail::sqrt<value_type>(d2XY + dZ * dZ);
946}
947
948//____________________________________________________________
949template <typename value_T>
950GPUd() value_T PropagatorImpl<value_T>::estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization<value_type>& trc) const
951{
952 value_T xdca = 0., ydca = 0., length = 0.; // , zdca = 0. // zdca might be used in future
954 constexpr float TinyF = 1e-9;
955 auto straigh_line_approx = [&]() {
956 auto csp2 = (1.f - trc.getSnp()) * (1.f + trc.getSnp());
957 if (csp2 > TinyF) {
958 auto csp = math_utils::detail::sqrt<value_type>(csp2);
959 auto tgp = trc.getSnp() / csp, f = trc.getX() * tgp - trc.getY();
960 xdca = tgp * f * csp2;
961 ydca = -f * csp2;
962 auto dx = xdca - trc.getX(), dy = ydca - trc.getY(), dz = dx * trc.getTgl() / csp;
963 return math_utils::detail::sqrt<value_type>(dx * dx + dy * dy + dz * dz);
964 } else { // track is parallel to Y axis
965 xdca = trc.getX(); // ydca = 0
966 return math_utils::detail::abs<value_type>(trc.getY() * math_utils::detail::sqrt<value_type>(1. + trc.getTgl() * trc.getTgl())); // distance from the current point to DCA
967 }
968 };
969 trc.getCircleParamsLoc(mNominalBz, c);
970 if (c.rC != 0.) { // helix
971 auto distC = math_utils::detail::sqrt<value_type>(c.getCenterD2()); // distance from the circle center to origin
972 if (distC > 1.e-3) {
973 auto nrm = (distC - c.rC) / distC;
974 xdca = nrm * c.xC; // coordinates of the DCA to 0,0 in the local frame
975 ydca = nrm * c.yC;
976 auto v0x = trc.getX() - c.xC, v0y = trc.getY() - c.yC, v1x = xdca - c.xC, v1y = ydca - c.yC;
977 auto angcos = (v0x * v1x + v0y * v1y) / (c.rC * c.rC);
978 if (math_utils::detail::abs<value_type>(angcos) < 1.f) {
979 auto ang = math_utils::detail::acos<value_type>(angcos);
980 if ((trc.getSign() > 0.f) == (mNominalBz > 0.f)) {
981 ang = -ang; // we need signeg angle
982 c.rC = -c.rC; // we need signed curvature for zdca
983 }
984 // zdca = trc.getZ() + (trc.getSign() > 0. ? c.rC : -c.rC) * trc.getTgl() * ang;
985 length = math_utils::detail::abs<value_type>(c.rC * ang * math_utils::detail::sqrt<value_type>(1. + trc.getTgl() * trc.getTgl()));
986 } else { // calculation of the arc length between the position and DCA makes no sense
987 length = straigh_line_approx();
988 }
989 } else { // track with circle center at the origin, and LT makes no sense, take direct distance
990 xdca = trc.getX();
991 ydca = trc.getY();
992 }
993 } else { // straight line
994 length = straigh_line_approx();
995 }
996 // since we assume the track or its parent comes from the beam-line or decay, add XY(?) distance to it
997 value_T dcaT = math_utils::detail::sqrt<value_type>(xdca * xdca + ydca * ydca);
998 length += dcaT;
999 lt.addStep(length, trc.getQ2P2());
1000 return dcaT;
1001}
1002
1003//____________________________________________________________
1004template <typename value_T>
1005GPUd() MatBudget PropagatorImpl<value_T>::getMatBudget(PropagatorImpl<value_type>::MatCorrType corrType, const math_utils::Point3D<value_type>& p0, const math_utils::Point3D<value_type>& p1) const
1006{
1007#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
1008 if (corrType == MatCorrType::USEMatCorrTGeo) {
1010 }
1011 if (!mMatLUT) {
1012 if (mTGeoFallBackAllowed) {
1014 } else {
1015 throw std::runtime_error("requested MatLUT is absent and fall-back to TGeo is disabled");
1016 }
1017 }
1018#endif
1019 return mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z());
1020}
1021
1022template <typename value_T>
1023template <typename T>
1024GPUd() void PropagatorImpl<value_T>::getFieldXYZImpl(const math_utils::Point3D<T> xyz, T* bxyz) const
1025{
1026 if (mGPUField) {
1027#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM)
1028 const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies)
1029#else
1030 const auto* f = mGPUField;
1031#endif
1032 float bxyzF[3] = {};
1033 f->GetField(xyz.X(), xyz.Y(), xyz.Z(), bxyzF);
1034 // copy and convert
1035 constexpr value_type kCLight1 = 1. / o2::gpu::gpu_common_constants::kCLight;
1036 for (uint i = 0; i < 3; ++i) {
1037 bxyz[i] = static_cast<value_type>(bxyzF[i]) * kCLight1;
1038 }
1039 } else {
1040#ifndef GPUCA_GPUCODE
1041 if (mFieldFast) {
1042 mFieldFast->Field(xyz, bxyz); // Must not call the host-only function in GPU compilation
1043 } else {
1044#ifdef GPUCA_STANDALONE
1045 LOG(fatal) << "Normal field cannot be used in standalone benchmark";
1046#else
1047 mField->field(xyz, bxyz);
1048#endif
1049 }
1050#endif
1051 }
1052}
1053
1054template <typename value_T>
1055template <typename T>
1056GPUd() T PropagatorImpl<value_T>::getBzImpl(const math_utils::Point3D<T> xyz) const
1057{
1058 T bz = 0;
1059 if (mGPUField) {
1060#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM)
1061 const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies)
1062#else
1063 const auto* f = mGPUField;
1064#endif
1065 constexpr value_type kCLight1 = 1. / o2::gpu::gpu_common_constants::kCLight;
1066 bz = f->GetFieldBz(xyz.X(), xyz.Y(), xyz.Z()) * kCLight1;
1067 } else {
1068#ifndef GPUCA_GPUCODE
1069 if (mFieldFast) {
1070 mFieldFast->GetBz(xyz, bz); // Must not call the host-only function in GPU compilation
1071 } else {
1072#ifdef GPUCA_STANDALONE
1073 LOG(fatal) << "Normal field cannot be used in standalone benchmark";
1074#else
1075 bz = mField->GetBz(xyz.X(), xyz.Y(), xyz.Z());
1076#endif
1077 }
1078#endif
1079 }
1080 return bz;
1081}
1082
1083template <typename value_T>
1084GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const
1085{
1086 getFieldXYZImpl<float>(xyz, bxyz);
1087}
1088
1089template <typename value_T>
1090GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<double> xyz, double* bxyz) const
1091{
1092 getFieldXYZImpl<double>(xyz, bxyz);
1093}
1094
1095template <typename value_T>
1096GPUd() float PropagatorImpl<value_T>::getBz(const math_utils::Point3D<float> xyz) const
1097{
1098 return getBzImpl<float>(xyz);
1099}
1100
1101template <typename value_T>
1102GPUd() double PropagatorImpl<value_T>::getBz(const math_utils::Point3D<double> xyz) const
1103{
1104 return getBzImpl<double>(xyz);
1105}
1106
1107namespace o2::base
1108{
1109#if !defined(GPUCA_GPUCODE) || defined(GPUCA_GPUCODE_DEVICE) // FIXME: DR: WORKAROUND to avoid CUDA bug creating host symbols for device code.
1110template class PropagatorImpl<float>;
1111template bool GPUdni() PropagatorImpl<float>::propagateToAlphaX<PropagatorImpl<float>::TrackPar_t>(PropagatorImpl<float>::TrackPar_t&, float, float, bool, float, float, int, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
1112template bool GPUdni() PropagatorImpl<float>::propagateToAlphaX<PropagatorImpl<float>::TrackParCov_t>(PropagatorImpl<float>::TrackParCov_t&, float, float, bool, float, float, int, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
1113template bool GPUdni() PropagatorImpl<float>::propagateToR<PropagatorImpl<float>::TrackPar_t>(PropagatorImpl<float>::TrackPar_t&, float, bool, float, float, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
1114template bool GPUdni() PropagatorImpl<float>::propagateToR<PropagatorImpl<float>::TrackParCov_t>(PropagatorImpl<float>::TrackParCov_t&, float, bool, float, float, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
1115#endif
1116#ifndef GPUCA_GPUCODE
1117template class PropagatorImpl<double>;
1120#endif
1121} // namespace o2::base
General auxilliary methods.
Definition of the GeometryManager class.
std::ostringstream debug
int32_t i
#define GPUdni()
#define GPUCA_CONSMEM
Header of the General Run Parameters object for B field values.
Header of the General Run Parameters object.
Helper classes for helical tracks manipulations.
constexpr int p1()
constexpr to accelerate the coordinates changing
Definition of the fast magnetic field parametrization MagFieldFast.
Definition of the MagF class.
uint32_t res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
GPUd() bool propagateToDCA(const o2 GPUd() bool propagateToDCABxByBz(const o2 GPUd() bool propagateToDCA(const o2 GPUd() bool propagateToDCABxByBz(const o2 PropagatorImpl(PropagatorImpl const &)=delete
static int initFieldFromGRP(const o2::parameters::GRPMagField *grp, bool verbose=false)
static MagneticField * createFieldMap(float l3Current=-30000., float diCurrent=-6000., Int_t convention=0, Bool_t uniform=kFALSE, float beamenergy=7000, const Char_t *btype="pp", const std::string path=std::string(gSystem->Getenv("VMCWORKDIR"))+std::string("/Common/maps/mfchebKGI_sym.root"))
void AllowFastField(bool v=true)
allow fast field param
o2::units::Current_t getDipoleCurrent() const
Definition GRPMagField.h:43
bool getFieldUniformity() const
Definition GRPMagField.h:49
o2::units::Current_t getL3Current() const
getters/setters for magnets currents
Definition GRPMagField.h:37
o2::units::Current_t getDipoleCurrent() const
Definition GRPObject.h:80
bool getFieldUniformity() const
Definition GRPObject.h:81
static GRPObject * loadFrom(const std::string &grpFileName="")
o2::units::Current_t getL3Current() const
getters/setters for magnets currents
Definition GRPObject.h:79
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum array
Definition glcorearb.h:4274
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean r
Definition glcorearb.h:1233
constexpr float Almost0
constexpr float TwoPI
constexpr float PI
constexpr float PIHalf
constexpr float Almost1
GPUd() const expr uint32_t MultivariatePolynomialHelper< Dim
std::array< int, 24 > p0
value_T step
Definition TrackUtils.h:42
constexpr float DefaultDCACov
constexpr float DefaultDCA
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"