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"
19
20using namespace o2::base;
21using namespace o2::gpu;
22
23#if !defined(GPUCA_GPUCODE)
24#include "Field/MagFieldFast.h" // Don't use this on the GPU
25#endif
26
27#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
28#include "Field/MagneticField.h"
32#include <FairRunAna.h> // eventually will get rid of it
33#include <TGeoGlobalMagField.h>
34
35template <typename value_T>
37{
38 if (uninitialized) {
39 return;
40 }
42 updateField();
43}
44
45//____________________________________________________________
46template <typename value_T>
48{
49 if (!mField) {
50 mField = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
51 if (!mField) {
52 LOG(warning) << "No Magnetic Field in TGeoGlobalMagField, checking legacy FairRunAna";
53 mField = dynamic_cast<o2::field::MagneticField*>(FairRunAna::Instance()->GetField());
54 }
55 if (!mField) {
56 LOG(fatal) << "Magnetic field is not initialized!";
57 }
58 if (!mField->getFastField() && mField->fastFieldExists()) {
59 mField->AllowFastField(true);
60 mFieldFast = mField->getFastField();
61 }
62 }
63 const value_type xyz[3] = {0.};
64 if (mFieldFast) {
65 mFieldFast->GetBz(xyz, mNominalBz);
66 } else {
67 mNominalBz = mField->GetBz(xyz[0], xyz[1], xyz[2]);
68 }
69}
70
71//____________________________________________________________
72template <typename value_T>
73int PropagatorImpl<value_T>::initFieldFromGRP(const std::string grpFileName, bool verbose)
74{
76 if (verbose) {
77 LOG(info) << "Loading field from GRP of " << grpFileName;
78 }
79 const auto grp = o2::parameters::GRPObject::loadFrom(grpFileName);
80 if (!grp) {
81 return -1;
82 }
83 if (verbose) {
84 grp->print();
85 }
86
87 return initFieldFromGRP(grp);
88}
89
90//____________________________________________________________
91template <typename value_T>
93{
95
96 if (TGeoGlobalMagField::Instance()->IsLocked()) {
97 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
98 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
99 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
100 return 0;
101 } else {
102 LOG(info) << "Destroying existing B field instance";
103 delete TGeoGlobalMagField::Instance();
104 }
105 }
107 TGeoGlobalMagField::Instance()->SetField(fld);
108 TGeoGlobalMagField::Instance()->Lock();
109 if (verbose) {
110 LOG(info) << "Running with the B field constructed out of GRP";
111 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
112 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
113 }
114 return 0;
115}
116
117//____________________________________________________________
118template <typename value_T>
120{
122
123 if (TGeoGlobalMagField::Instance()->IsLocked()) {
124 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
125 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
126 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
127 return 0;
128 } else {
129 LOG(info) << "Destroying existing B field instance";
130 delete TGeoGlobalMagField::Instance();
131 }
132 }
134 TGeoGlobalMagField::Instance()->SetField(fld);
135 TGeoGlobalMagField::Instance()->Lock();
136 if (verbose) {
137 LOG(info) << "Running with the B field constructed out of GRP";
138 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
139 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
140 }
141 return 0;
142}
143
144#elif !defined(GPUCA_GPUCODE)
145template <typename value_T>
147{
148} // empty dummy constructor for standalone benchmark
149#endif
151//_______________________________________________________________________
152template <typename value_T>
153GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackParCov_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
154 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
155{
156 //----------------------------------------------------------------
157 //
158 // Propagates the track to the plane X=xk (cm)
159 // taking into account all the three components of the magnetic field
160 // and correcting for the crossed material.
161 //
162 // maxStep - maximal step for propagation
163 // tofInfo - optional container for track length and PID-dependent TOF integration
164 //
165 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
166 //----------------------------------------------------------------
167 auto dx = xToGo - track.getX();
168 int dir = dx > 0.f ? 1 : -1;
169 if (!signCorr) {
170 signCorr = -dir; // sign of eloss correction is not imposed
171 }
172
174 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
175 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
176 if (dir < 0) {
177 step = -step;
178 }
179 auto x = track.getX() + step;
180 auto xyz0 = track.getXYZGlo();
181 getFieldXYZ(xyz0, &b[0]);
182
183 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
184 bool res = true;
185 if (matCorr != MatCorrType::USEMatCorrNONE) {
186 auto xyz1 = track.getXYZGlo();
187 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
188 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
189 res = false;
190 }
191 if (tofInfo) {
192 tofInfo->addStep(mb.length, track.getP2Inv()); // fill L,ToF info using already calculated step length
193 tofInfo->addX2X0(mb.meanX2X0);
194 tofInfo->addXRho(mb.getXRho(signCorr));
195 }
196 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
197 auto xyz1 = track.getXYZGlo();
198 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
199 tofInfo->addStep(stepV.R(), track.getP2Inv());
200 }
201 return res;
202 };
203
204 if (!track.propagateTo(x, b)) {
205 return false;
206 }
207 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
208 correct();
209 return false;
210 }
211 if (!correct()) {
212 return false;
213 }
214 dx = xToGo - track.getX();
215 }
216 track.setX(xToGo);
217 return true;
218}
219
220//_______________________________________________________________________
221template <typename value_T>
222GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackPar_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
223 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
224{
225 //----------------------------------------------------------------
226 //
227 // Propagates the track params to the plane X=xk (cm), NO error evaluation
228 // taking into account all the three components of the magnetic field
229 // and optionally correcting for the e.loss crossed material.
230 //
231 // maxStep - maximal step for propagation
232 // tofInfo - optional container for track length and PID-dependent TOF integration
233 //
234 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
235 //----------------------------------------------------------------
236 auto dx = xToGo - track.getX();
237 int dir = dx > 0.f ? 1 : -1;
238 if (!signCorr) {
239 signCorr = -dir; // sign of eloss correction is not imposed
240 }
241
243 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
244 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
245 if (dir < 0) {
246 step = -step;
247 }
248 auto x = track.getX() + step;
249 auto xyz0 = track.getXYZGlo();
250 getFieldXYZ(xyz0, &b[0]);
251
252 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
253 bool res = true;
254 if (matCorr != MatCorrType::USEMatCorrNONE) {
255 auto xyz1 = track.getXYZGlo();
256 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
257 if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) {
258 res = false;
259 }
260 if (tofInfo) {
261 tofInfo->addStep(mb.length, track.getP2Inv()); // fill L,ToF info using already calculated step length
262 tofInfo->addX2X0(mb.meanX2X0);
263 tofInfo->addXRho(mb.getXRho(signCorr));
264 }
265 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
266 auto xyz1 = track.getXYZGlo();
267 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
268 tofInfo->addStep(stepV.R(), track.getP2Inv());
269 }
270 return res;
271 };
272
273 if (!track.propagateParamTo(x, b)) {
274 return false;
275 }
276 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
277 correct();
278 return false;
279 }
280 if (!correct()) {
281 return false;
282 }
283 dx = xToGo - track.getX();
284 }
285 track.setX(xToGo);
286 return true;
287}
288
289//_______________________________________________________________________
290template <typename value_T>
291GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackParCov_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
292 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
293{
294 //----------------------------------------------------------------
295 //
296 // Propagates the track to the plane X=xk (cm)
297 // taking into account all the three components of the magnetic field
298 // and correcting for the crossed material.
299 //
300 // maxStep - maximal step for propagation
301 // tofInfo - optional container for track length and PID-dependent TOF integration
302 //
303 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
304 //----------------------------------------------------------------
305 auto dx = xToGo - track.getX();
306 int dir = dx > 0.f ? 1 : -1;
307 if (!signCorr) {
308 signCorr = -dir; // sign of eloss correction is not imposed
309 }
310
311 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
312 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
313 if (dir < 0) {
314 step = -step;
315 }
316 auto x = track.getX() + step;
317 auto xyz0 = track.getXYZGlo();
318 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
319 bool res = true;
320 if (matCorr != MatCorrType::USEMatCorrNONE) {
321 auto xyz1 = track.getXYZGlo();
322 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
323 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
324 res = false;
325 }
326 if (tofInfo) {
327 tofInfo->addStep(mb.length, track.getP2Inv()); // fill L,ToF info using already calculated step length
328 tofInfo->addX2X0(mb.meanX2X0);
329 tofInfo->addXRho(mb.getXRho(signCorr));
330 }
331 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
332 auto xyz1 = track.getXYZGlo();
333 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
334 tofInfo->addStep(stepV.R(), track.getP2Inv());
335 }
336 return res;
337 };
338 if (!track.propagateTo(x, bZ)) {
339 return false;
340 }
341 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
342 correct();
343 return false;
344 }
345 if (!correct()) {
346 return false;
347 }
348 dx = xToGo - track.getX();
349 }
350 track.setX(xToGo);
351 return true;
352}
353
354//_______________________________________________________________________
355template <typename value_T>
356GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackPar_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
357 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
358{
359 //----------------------------------------------------------------
360 //
361 // Propagates the track parameters only to the plane X=xk (cm)
362 // taking into account all the three components of the magnetic field
363 // and correcting for the crossed material.
364 //
365 // maxStep - maximal step for propagation
366 // tofInfo - optional container for track length and PID-dependent TOF integration
367 //
368 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
369 //----------------------------------------------------------------
370 auto dx = xToGo - track.getX();
371 int dir = dx > 0.f ? 1 : -1;
372 if (!signCorr) {
373 signCorr = -dir; // sign of eloss correction is not imposed
374 }
375
376 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
377 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
378 if (dir < 0) {
379 step = -step;
380 }
381 auto x = track.getX() + step;
382 auto xyz0 = track.getXYZGlo();
383
384 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
385 bool res = true;
386 if (matCorr != MatCorrType::USEMatCorrNONE) {
387 auto xyz1 = track.getXYZGlo();
388 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
389 if (!track.correctForELoss(mb.getXRho(signCorr))) {
390 res = false;
391 }
392 if (tofInfo) {
393 tofInfo->addStep(mb.length, track.getP2Inv()); // fill L,ToF info using already calculated step length
394 tofInfo->addX2X0(mb.meanX2X0);
395 tofInfo->addXRho(mb.getXRho(signCorr));
396 }
397 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
398 auto xyz1 = track.getXYZGlo();
399 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
400 tofInfo->addStep(stepV.R(), track.getP2Inv());
401 }
402 return res;
403 };
404
405 if (!track.propagateParamTo(x, bZ)) {
406 return false;
407 }
408 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
409 correct();
410 return false;
411 }
412 if (!correct()) {
413 return false;
414 }
415 dx = xToGo - track.getX();
416 }
417 track.setX(xToGo);
418 return true;
419}
420
421//_______________________________________________________________________
422template <typename value_T>
423template <typename track_T>
424GPUd() bool PropagatorImpl<value_T>::propagateToAlphaX(track_T& track, value_type alpha, value_type x, bool bzOnly, value_type maxSnp, value_type maxStep, int minSteps,
425 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
426{
427 // propagate to alpha,X, if needed in a few steps
428 auto snp = track.getSnpAt(alpha, x, getNominalBz());
429 // apply safety factor 0.9 for crude rotation estimate
430 if (math_utils::detail::abs<value_type>(snp) < maxSnp * 0.9 && track.rotate(alpha)) {
431 auto dx = math_utils::detail::abs<value_type>(x - track.getX());
432 if (dx < Epsilon) {
433 return true;
434 }
435 return propagateTo(track, x, bzOnly, maxSnp, math_utils::detail::min<value_type>(dx / minSteps, maxStep), matCorr, tofInfo, signCorr);
436 }
437 return false;
438 /*
439 // try to go in a few steps with intermediate rotations
440
441
442 auto alphaTrg = alpha;
443 math_utils::detail::bringToPMPi<value_type>(alphaTrg);
444 auto alpCurr = track.getAlpha();
445 math_utils::detail::bringToPMPi<value_type>(alpCurr);
446 int nsteps = minSteps > 2 ? minSteps : 2;
447 auto dalp = math_utils::detail::deltaPhiSmall<value_type>(alpCurr, alphaTrg) / nsteps; // effective (alpha - alphaCurr)/nsteps
448 auto xtmp = (track.getX() + x) / nsteps;
449 return track.rotate(alpCurr + dalp) && propagateTo(track, xtmp, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr) &&
450 track.rotate(alpha) && propagateTo(track, x, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr);
451 */
452}
453
454//_______________________________________________________________________
455template <typename value_T>
456GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track, value_type bZ,
457 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
458 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
459 int signCorr, value_type maxD) const
460{
461 // propagate track to DCA to the vertex
462 value_type sn, cs, alp = track.getAlpha();
463 math_utils::detail::sincos<value_type>(alp, sn, cs);
464 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
465 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
466 x -= xv;
467 y -= yv;
468 // Estimate the impact parameter neglecting the track curvature
469 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
470 if (d > maxD) {
471 return false;
472 }
473 value_type crv = track.getCurvature(bZ);
474 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
475 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
476 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
477 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
478
479 x = xv * cs + yv * sn;
480 yv = -xv * sn + yv * cs;
481 xv = x;
482
483 auto tmpT(track); // operate on the copy to recover after the failure
484 alp += math_utils::detail::asin<value_type>(sn);
485 if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
486#ifndef GPUCA_ALIGPUCODE
487 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
488#elif !defined(GPUCA_NO_FMT)
489 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
490#endif
491 return false;
492 }
493 track = tmpT;
494 if (dca) {
495 math_utils::detail::sincos<value_type>(alp, sn, cs);
496 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
497 dca->set(track.getY() - yv, track.getZ() - zv,
498 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
499 }
500 return true;
501}
502
503//_______________________________________________________________________
504template <typename value_T>
505GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track,
506 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
507 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
508 int signCorr, value_type maxD) const
509{
510 // propagate track to DCA to the vertex
511 value_type sn, cs, alp = track.getAlpha();
512 math_utils::detail::sincos<value_type>(alp, sn, cs);
513 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
514 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
515 x -= xv;
516 y -= yv;
517 // Estimate the impact parameter neglecting the track curvature
518 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
519 if (d > maxD) {
520 return false;
521 }
522 value_type crv = track.getCurvature(mNominalBz);
523 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
524 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
525 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
526 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
527
528 x = xv * cs + yv * sn;
529 yv = -xv * sn + yv * cs;
530 xv = x;
531
532 auto tmpT(track); // operate on the copy to recover after the failure
533 alp += math_utils::detail::asin<value_type>(sn);
534 if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
535#ifndef GPUCA_ALIGPUCODE
536 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
537#elif !defined(GPUCA_NO_FMT)
538 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
539#endif
540 return false;
541 }
542 track = tmpT;
543 if (dca) {
544 math_utils::detail::sincos<value_type>(alp, sn, cs);
545 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
546 dca->set(track.getY() - yv, track.getZ() - zv,
547 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
548 }
549 return true;
550}
551
552//_______________________________________________________________________
553template <typename value_T>
554GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track, value_type bZ,
555 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
556 gpu::gpustd::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
557 int signCorr, value_type maxD) const
558{
559 // propagate track to DCA to the vertex
560 value_type sn, cs, alp = track.getAlpha();
561 math_utils::detail::sincos<value_type>(alp, sn, cs);
562 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
563 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
564 x -= xv;
565 y -= yv;
566 // Estimate the impact parameter neglecting the track curvature
567 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
568 if (d > maxD) {
569 return false;
570 }
571 value_type crv = track.getCurvature(bZ);
572 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
573 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
574 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
575 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
576
577 x = xv * cs + yv * sn;
578 yv = -xv * sn + yv * cs;
579 xv = x;
580
581 auto tmpT(track); // operate on the copy to recover after the failure
582 alp += math_utils::detail::asin<value_type>(sn);
583 if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
584#ifndef GPUCA_ALIGPUCODE
585 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
586 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
587#else
588 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
589#endif
590 return false;
591 }
592 track = tmpT;
593 if (dca) {
594 (*dca)[0] = track.getY() - yv;
595 (*dca)[1] = track.getZ() - zv;
596 }
597 return true;
598}
599
600//_______________________________________________________________________
601template <typename value_T>
602GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track,
603 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
604 gpu::gpustd::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
605 int signCorr, value_type maxD) const
606{
607 // propagate track to DCA to the vertex
608 value_type sn, cs, alp = track.getAlpha();
609 math_utils::detail::sincos<value_type>(alp, sn, cs);
610 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
611 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
612 x -= xv;
613 y -= yv;
614 // Estimate the impact parameter neglecting the track curvature
615 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
616 if (d > maxD) {
617 return false;
618 }
619 value_type crv = track.getCurvature(mNominalBz);
620 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
621 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
622 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
623 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
624
625 x = xv * cs + yv * sn;
626 yv = -xv * sn + yv * cs;
627 xv = x;
628
629 auto tmpT(track); // operate on the copy to recover after the failure
630 alp += math_utils::detail::asin<value_type>(sn);
631 if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
632#ifndef GPUCA_ALIGPUCODE
633 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
634 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
635#else
636 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
637#endif
638 return false;
639 }
640 track = tmpT;
641 if (dca) {
642 (*dca)[0] = track.getY() - yv;
643 (*dca)[1] = track.getZ() - zv;
644 }
645 return true;
646}
647
648//____________________________________________________________
649template <typename value_T>
650GPUd() float PropagatorImpl<value_T>::estimateLTIncrement(const o2::track::TrackParametrization<value_type>& trc,
651 const o2::math_utils::Point3D<value_type>& posStart,
652 const o2::math_utils::Point3D<value_type>& posEnd) const
653{
654 // estimate helical step increment between 2 point
655 float dX = posEnd.X() - posStart.X(), dY = posEnd.Y() - posStart.Y(), dZ = posEnd.Z() - posStart.Z(), d2XY = dX * dX + dY * dY;
656 if (getNominalBz() != 0) { // circular arc = 2*R*asin(dXY/2R)
657 float b[3];
658 o2::math_utils::Point3D<float> posAv(0.5 * (posEnd.X() + posStart.X()), 0.5 * (posEnd.Y() + posStart.Y()), 0.5 * (posEnd.Z() + posStart.Z()));
659 getFieldXYZ(posAv, b);
660 float curvH = math_utils::detail::abs<value_type>(0.5f * trc.getCurvature(b[2])), asArg = curvH * math_utils::detail::sqrt<value_type>(d2XY);
661 if (curvH > 0.f) {
662 d2XY = asArg < 1.f ? math_utils::detail::asin<value_type>(asArg) / curvH : o2::constants::math::PIHalf / curvH;
663 d2XY *= d2XY;
664 }
665 }
666 return math_utils::detail::sqrt<value_type>(d2XY + dZ * dZ);
667}
668
669//____________________________________________________________
670template <typename value_T>
671GPUd() value_T PropagatorImpl<value_T>::estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization<value_type>& trc) const
672{
673 value_T xdca = 0., ydca = 0., length = 0.; // , zdca = 0. // zdca might be used in future
675 constexpr float TinyF = 1e-9;
676 auto straigh_line_approx = [&]() {
677 auto csp2 = (1.f - trc.getSnp()) * (1.f + trc.getSnp());
678 if (csp2 > TinyF) {
679 auto csp = math_utils::detail::sqrt<value_type>(csp2);
680 auto tgp = trc.getSnp() / csp, f = trc.getX() * tgp - trc.getY();
681 xdca = tgp * f * csp2;
682 ydca = -f * csp2;
683 auto dx = xdca - trc.getX(), dy = ydca - trc.getY(), dz = dx * trc.getTgl() / csp;
684 return math_utils::detail::sqrt<value_type>(dx * dx + dy * dy + dz * dz);
685 } else { // track is parallel to Y axis
686 xdca = trc.getX(); // ydca = 0
687 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
688 }
689 };
690 trc.getCircleParamsLoc(mNominalBz, c);
691 if (c.rC != 0.) { // helix
692 auto distC = math_utils::detail::sqrt<value_type>(c.getCenterD2()); // distance from the circle center to origin
693 if (distC > 1.e-3) {
694 auto nrm = (distC - c.rC) / distC;
695 xdca = nrm * c.xC; // coordinates of the DCA to 0,0 in the local frame
696 ydca = nrm * c.yC;
697 auto v0x = trc.getX() - c.xC, v0y = trc.getY() - c.yC, v1x = xdca - c.xC, v1y = ydca - c.yC;
698 auto angcos = (v0x * v1x + v0y * v1y) / (c.rC * c.rC);
699 if (math_utils::detail::abs<value_type>(angcos) < 1.f) {
700 auto ang = math_utils::detail::acos<value_type>(angcos);
701 if ((trc.getSign() > 0.f) == (mNominalBz > 0.f)) {
702 ang = -ang; // we need signeg angle
703 c.rC = -c.rC; // we need signed curvature for zdca
704 }
705 // zdca = trc.getZ() + (trc.getSign() > 0. ? c.rC : -c.rC) * trc.getTgl() * ang;
706 length = math_utils::detail::abs<value_type>(c.rC * ang * math_utils::detail::sqrt<value_type>(1. + trc.getTgl() * trc.getTgl()));
707 } else { // calculation of the arc length between the position and DCA makes no sense
708 length = straigh_line_approx();
709 }
710 } else { // track with circle center at the origin, and LT makes no sense, take direct distance
711 xdca = trc.getX();
712 ydca = trc.getY();
713 }
714 } else { // straight line
715 length = straigh_line_approx();
716 }
717 // since we assume the track or its parent comes from the beam-line or decay, add XY(?) distance to it
718 value_T dcaT = math_utils::detail::sqrt<value_type>(xdca * xdca + ydca * ydca);
719 length += dcaT;
720 lt.addStep(length, trc.getP2Inv());
721 return dcaT;
722}
723
724//____________________________________________________________
725template <typename value_T>
726GPUd() 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
727{
728#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
729 if (corrType == MatCorrType::USEMatCorrTGeo) {
731 }
732 if (!mMatLUT) {
733 if (mTGeoFallBackAllowed) {
735 } else {
736 throw std::runtime_error("requested MatLUT is absent and fall-back to TGeo is disabled");
737 }
738 }
739#endif
740 return mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z());
741}
742
743template <typename value_T>
744template <typename T>
745GPUd() void PropagatorImpl<value_T>::getFieldXYZImpl(const math_utils::Point3D<T> xyz, T* bxyz) const
746{
747 if (mGPUField) {
748#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM)
749 const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies)
750#else
751 const auto* f = mGPUField;
752#endif
753 float bxyzF[3] = {};
754 f->GetField(xyz.X(), xyz.Y(), xyz.Z(), bxyzF);
755 // copy and convert
756 constexpr value_type kCLight1 = 1. / o2::gpu::gpu_common_constants::kCLight;
757 for (uint i = 0; i < 3; ++i) {
758 bxyz[i] = static_cast<value_type>(bxyzF[i]) * kCLight1;
759 }
760 } else {
761#ifndef GPUCA_GPUCODE
762 if (mFieldFast) {
763 mFieldFast->Field(xyz, bxyz); // Must not call the host-only function in GPU compilation
764 } else {
765#ifdef GPUCA_STANDALONE
766 LOG(fatal) << "Normal field cannot be used in standalone benchmark";
767#else
768 mField->field(xyz, bxyz);
769#endif
770 }
771#endif
772 }
773}
774
775template <typename value_T>
776GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const
777{
778 getFieldXYZImpl<float>(xyz, bxyz);
779}
780
781template <typename value_T>
782GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<double> xyz, double* bxyz) const
783{
784 getFieldXYZImpl<double>(xyz, bxyz);
785}
786
787namespace o2::base
788{
789#if !defined(GPUCA_GPUCODE) || defined(GPUCA_GPUCODE_DEVICE) // FIXME: DR: WORKAROUND to avoid CUDA bug creating host symbols for device code.
790template class PropagatorImpl<float>;
791template 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;
792template 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;
793#endif
794#ifndef GPUCA_GPUCODE
795template class PropagatorImpl<double>;
798#endif
799} // namespace o2::base
General auxilliary methods.
Definition of the GeometryManager class.
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.
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
std::ostringstream debug
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)
constexpr float Almost0
constexpr float PIHalf
constexpr float Almost1
std::array< T, N > array
GPUd() const expr uint32_t MultivariatePolynomialHelper< Dim
std::array< int, 24 > p0
value_T step
Definition TrackUtils.h:42
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"