15#define GPUCA_CADEBUG 0
16#define GPUCA_MERGE_LOOPER_MC 0
21#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC)
26#ifndef GPUCA_GPUCODE_DEVICE
40#include "GPUDefParametersRuntime.h"
64using namespace gputpcgmmergertypes;
91 GPUd() bool operator()(const int32_t
aa, const int32_t
bb)
98 if (
a.CCE() !=
b.CCE()) {
99 return a.CCE() >
b.CCE();
102 if (
a.NClusters() !=
b.NClusters()) {
103 return a.NClusters() > b.NClusters();
104 }
if (CAMath::Abs(
a.GetParam().GetQPt()) != CAMath::Abs(
b.GetParam().GetQPt())) {
105 return CAMath::Abs(a.GetParam().GetQPt()) > CAMath::Abs(b.GetParam().GetQPt());
106 }
if (
a.GetParam().GetY() !=
b.GetParam().GetY()) {
107 return a.GetParam().GetY() > b.GetParam().GetY();
111 return a.NClusters() >
b.NClusters();
119 GPUd() bool operator()(const int32_t
aa, const int32_t
bb)
125 return CAMath::Abs(
a.GetParam().GetQPt()) > CAMath::Abs(
b.GetParam().GetQPt());
126 }
if (
a.GetParam().GetY() !=
b.GetParam().GetY()) {
127 return a.GetParam().GetY() >
b.GetParam().GetY();
129 return a.GetParam().GetZ() >
b.GetParam().GetZ();
131 return CAMath::Abs(
a.GetParam().GetQPt()) > CAMath::Abs(
b.GetParam().GetQPt());
139 return GPUCA_DETERMINISTIC_CODE(CAMath::Abs(
a.refz) != CAMath::Abs(
b.refz) ? CAMath::Abs(
a.refz) < CAMath::Abs(
b.refz) :
a.id <
b.id, CAMath::Abs(
a.refz) < CAMath::Abs(
b.refz));
160 mNextSectorInd[mid] = 0;
161 mPrevSectorInd[0] = mid;
162 mNextSectorInd[last] =
NSECTORS / 2;
163 mPrevSectorInd[
NSECTORS / 2] = last;
167#if !defined(GPUCA_GPUCODE) && (defined(GPUCA_MERGER_BY_MC_LABEL) || defined(GPUCA_CADEBUG_ENABLED) || GPUCA_MERGE_LOOPER_MC)
181template <
class T,
class S>
182int64_t GPUTPCGMMerger::GetTrackLabelA(
const S& trk)
const
186 if constexpr (std::is_same_v<S, GPUTPCGMBorderTrack&>) {
187 sectorTrack = &mSectorTrackInfos[trk.TrackID()];
188 nClusters = sectorTrack->OrigTrack()->NHits();
192 auto acc =
GPUTPCTrkLbl<false, GPUTPCTrkLbl_ret>(resolveMCLabels<T>(GetConstantMem()->ioPtrs.clustersNative ? GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth : nullptr, GetConstantMem()->ioPtrs.mcLabelsTPC), 0.5f);
195 if constexpr (std::is_same_v<S, GPUTPCGMBorderTrack&>) {
196 const GPUTPCTracker& tracker = GetConstantMem()->tpcTrackers[sectorTrack->Sector()];
197 const GPUTPCHitId& ic = tracker.TrackHits()[sectorTrack->OrigTrack()->FirstHitID() +
i];
198 id = tracker.Data().ClusterDataIndex(tracker.Data().Row(ic.RowIndex()), ic.HitIndex()) + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[sectorTrack->Sector()][0];
200 id = mClusters[trk.FirstClusterRef() +
i].
num;
204 return acc.computeLabel().id;
208int64_t GPUTPCGMMerger::GetTrackLabel(
const S& trk)
const
210#ifdef GPUCA_TPC_GEOMETRY_O2
211 if (GetConstantMem()->ioPtrs.clustersNative->clustersMCTruth) {
212 return GetTrackLabelA<o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>,
S>(trk);
216 return GetTrackLabelA<AliHLTTPCClusterMCLabel, S>(trk);
226 for (uint32_t
i = 0;
i < mMemory->nMergedTracks;
i++) {
229 if (trk.NClusters() == 0) {
230 GPUError(
"FAILURE: Track marked ok but has 0 clusters");
233 if (!trk.CCE() && !trk.MergedLooper()) {
235 while (updTrk->PrevSegment() >= 0) {
236 auto next = &mMergedTracks[updTrk->PrevSegment()];
237 if (!next->MergedLooper()) {
238 GPUError(
"FAILURE: prev segment not marked as merged looper\n");
242 GPUError(
"FAILURE: segment cycle found\n");
247 if (updTrk->NClusters() == 0) {
248 printf(
"FAILURE: segment leg has 0 clusters");
255 GPUInfo(
"Merged Tracks OK");
257 throw std::runtime_error(
"Error during track merging");
264 std::vector<bool> trkUsed(SectorTrackInfoLocalTotal());
265 for (int32_t
i = 0;
i < SectorTrackInfoLocalTotal();
i++) {
269 for (int32_t itr = 0; itr < SectorTrackInfoLocalTotal(); itr++) {
271 if (track.PrevSegmentNeighbour() >= 0 && mSectorTrackInfos[track.PrevSegmentNeighbour()].NextSegmentNeighbour() != itr) {
272 GPUError(
"FAILURE: Invalid reciprocal segment link: %d PrevSegmentNeighbour %d NextSegmentNeighbour %d", itr, track.PrevSegmentNeighbour(), mSectorTrackInfos[track.PrevSegmentNeighbour()].NextSegmentNeighbour());
275 if (track.NextSegmentNeighbour() >= 0 && mSectorTrackInfos[track.NextSegmentNeighbour()].PrevSegmentNeighbour() != itr) {
276 GPUError(
"FAILURE: Invalid reciprocal segment link: %d NextSegmentNeighbour %d PrevSegmentNeighbour %d", itr, track.NextSegmentNeighbour(), mSectorTrackInfos[track.NextSegmentNeighbour()].PrevSegmentNeighbour());
279 if (track.PrevNeighbour() >= 0 && mSectorTrackInfos[track.PrevNeighbour()].NextNeighbour() != itr) {
280 GPUError(
"FAILURE: Invalid reciprocal link: %d PrevNeighbour %d NextNeighbour %d", itr, track.PrevNeighbour(), mSectorTrackInfos[track.PrevNeighbour()].NextNeighbour());
283 if (track.NextNeighbour() >= 0 && mSectorTrackInfos[track.NextNeighbour()].PrevNeighbour() != itr) {
284 GPUError(
"FAILURE: Invalid reciprocal link: %d NextNeighbour %d PrevNeighbour %d", itr, track.NextNeighbour(), mSectorTrackInfos[track.NextNeighbour()].PrevNeighbour());
287 if (track.PrevSegmentNeighbour() >= 0) {
290 if (track.PrevNeighbour() >= 0) {
295 int32_t iTrk = tr - mSectorTrackInfos;
297 GPUError(
"FAILURE: double use");
301 trkUsed[iTrk] =
true;
303 int32_t jtr = tr->NextSegmentNeighbour();
305 tr = &(mSectorTrackInfos[jtr]);
306 if (tr->PrevNeighbour() >= 0) {
307 GPUError(
"FAILURE: Non-base segment has previous leg");
312 jtr = trbase->NextNeighbour();
314 trbase = &(mSectorTrackInfos[jtr]);
316 if (tr->PrevSegmentNeighbour() >= 0) {
317 GPUError(
"FAILURE: Neibhbour leg has previous segment neightbout");
326 for (int32_t
i = 0;
i < SectorTrackInfoLocalTotal();
i++) {
327 if (trkUsed[
i] ==
false) {
328 GPUError(
"FAILURE: trk missed");
333 GPUInfo(
"Merged Track Graph OK");
335 throw std::runtime_error(
"Invalid merge graph");
339void GPUTPCGMMerger::PrintMergeGraph(
const GPUTPCGMSectorTrack* trk, std::ostream& out)
const
342 while (trk->PrevSegmentNeighbour() >= 0) {
343 trk = &mSectorTrackInfos[trk->PrevSegmentNeighbour()];
346 while (trk->PrevNeighbour() >= 0) {
347 trk = &mSectorTrackInfos[trk->PrevNeighbour()];
350 int32_t nextId = trk - mSectorTrackInfos;
351 out <<
"Graph of track " << (orgTrack - mSectorTrackInfos) <<
"\n";
352 while (nextId >= 0) {
353 trk = &mSectorTrackInfos[nextId];
354 if (trk->PrevSegmentNeighbour() >= 0) {
355 out <<
"TRACK TREE INVALID!!! " << trk->PrevSegmentNeighbour() <<
" --> " << nextId <<
"\n";
357 out << (trk == orgTower ?
"--" :
" ");
358 while (nextId >= 0) {
360 if (trk != trk2 && (trk2->PrevNeighbour() >= 0 || trk2->NextNeighbour() >= 0)) {
361 out <<
" (TRACK TREE INVALID!!! " << trk2->PrevNeighbour() <<
" <-- " << nextId <<
" --> " << trk2->NextNeighbour() <<
") ";
364 snprintf(tmp, 128,
" %s%5d(%5.2f)", trk2 == orgTrack ?
"!" :
" ", nextId, trk2->QPt());
366 nextId = trk2->NextSegmentNeighbour();
369 nextId = trk->NextNeighbour();
389 mBorder[
iSector] = mBorderMemory + 2 * nTracks;
391 mBorderRange[
iSector] = mBorderRangeMemory + 2 * nTracks;
399 memMax = (
void*)std::max((
size_t)mem, (size_t)memMax);
403 memMax = (
void*)std::max((
size_t)mem, (size_t)memMax);
407 memMax = (
void*)std::max((
size_t)mem, (size_t)memMax);
410 memMax = (
void*)std::max((
size_t)mem, (size_t)memMax);
424 if (mergerSortTracks) {
449 mClusterStateExt =
nullptr;
499 mNTotalSectorTracks = 0;
501 mNMaxSingleSectorTracks = 0;
504 mNTotalSectorTracks += ntrk;
506 if (mNMaxSingleSectorTracks < ntrk) {
507 mNMaxSingleSectorTracks = ntrk;
511 if (CAMath::Abs(Param().polynomialField.GetNominalBz()) < (gpu_common_constants::kZeroFieldCut * gpu_common_constants::kCLight)) {
524 mNMaxClusters = mNClusters;
526 mNMaxLooperMatches = mNMaxClusters / 4;
533 throw std::runtime_error(
"mNMaxSingleSectorTracks too small");
537 throw std::runtime_error(
"Must run also sector tracking");
546 const int32_t
n =
output ? mMemory->nMergedTracks : SectorTrackInfoLocalTotal();
547 for (int32_t
i = iBlock * nThreads + iThread;
i <
n;
i += nThreads * nBlocks) {
555 prop.SetMaterialTPC();
557 prop.SetSeedingErrors(
true);
558 prop.SetFitInProjections(
false);
559 prop.SetPolynomialField(&Param().polynomialField);
561 trk.X() = inTrack->Param().GetX();
562 trk.
Y() = inTrack->Param().GetY();
563 trk.
Z() = inTrack->Param().GetZ();
564 trk.SinPhi() = inTrack->Param().GetSinPhi();
565 trk.DzDs() = inTrack->Param().GetDzDs();
566 trk.QPt() = inTrack->Param().GetQPt();
567 trk.TOffset() = Param().par.continuousTracking ? GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convZOffsetToVertexTime(sector, inTrack->Param().GetZOffset(), Param().continuousMaxTimeBin) : 0;
568 const auto tmp = sectorTrack.ClusterTN() > sectorTrack.ClusterT0() ? std::array<float, 2>{sectorTrack.ClusterTN(), sectorTrack.ClusterT0()} : std::array<float, 2>{sectorTrack.ClusterT0(), sectorTrack.ClusterTN()};
569 trk.ShiftZ(
this, sector, tmp[0], tmp[1], inTrack->Param().GetX());
570 sectorTrack.SetX2(0.f);
571 for (int32_t way = 0; way < 2; way++) {
573 prop.SetFitInProjections(
true);
574 prop.SetPropagateBzOnly(
true);
576 trk.ResetCovariance();
577 prop.SetTrack(&trk,
alpha);
578 int32_t
start = way ? inTrack->NHits() - 1 : 0;
579 int32_t
end = way ? 0 : (inTrack->NHits() - 1);
580 int32_t incr = way ? -1 : 1;
584 const GPUTPCTracker& tracker = GetConstantMem()->tpcTrackers[sector];
585 const GPUTPCHitId& ic = tracker.TrackHits()[inTrack->FirstHitID() +
i];
586 int32_t clusterIndex = tracker.Data().ClusterDataIndex(tracker.Data().Row(ic.RowIndex()), ic.HitIndex());
588 const ClusterNative& cl = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[GetConstantMem()->ioPtrs.clustersNative->clusterOffset[sector][0] + clusterIndex];
589 flags = cl.getFlags();
590 GetConstantMem()->calibObjects.fastTransformHelper->Transform(sector,
row, cl.getPad(), cl.getTime(),
x,
y,
z, trk.TOffset());
591 if (prop.PropagateToXAlpha(
x,
alpha, way == 0)) {
594 trk.ConstrainSinPhi();
595 if (prop.Update(
y,
z,
row, Param(),
flags &
GPUTPCGMMergedTrackHit::clustererAndSharedFlags, 0,
false, sector, -1.f, 0.f, 0.f)) {
598 trk.ConstrainSinPhi();
601 sectorTrack.SetParam2(trk);
603 sectorTrack.Set(trk, inTrack,
alpha, sector);
611 const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSector];
612 const GPUTPCHitId& ic1 = trk.TrackHits()[sectorTr->FirstHitID()];
613 const GPUTPCHitId& ic2 = trk.TrackHits()[sectorTr->FirstHitID() + sectorTr->NHits() - 1];
614 int32_t clusterIndex1 = trk.Data().ClusterDataIndex(trk.Data().Row(ic1.RowIndex()), ic1.HitIndex());
615 int32_t clusterIndex2 = trk.Data().ClusterDataIndex(trk.Data().Row(ic2.RowIndex()), ic2.HitIndex());
616 const ClusterNative* cl = GetConstantMem()->ioPtrs.clustersNative->clustersLinear + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[iSector][0];
617 track.SetClusterT(cl[clusterIndex1].
getTime(), cl[clusterIndex2].
getTime());
622 mSectorTrackInfoIndex[
id] = mMemory->nUnpackedTracks;
625GPUd()
void GPUTPCGMMerger::UnpackSectorGlobal(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector)
627 const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSector];
628 float alpha = Param().Alpha(iSector);
629 const GPUTPCTrack* sectorTr = mMemory->firstExtrapolatedTracks[iSector];
630 uint32_t nLocalTracks = trk.CommonMemory()->nLocalTracks;
631 uint32_t nTracks = *trk.NTracks();
632 for (uint32_t itr = nLocalTracks + iBlock * nThreads + iThread; itr < nTracks; itr += nBlocks * nThreads) {
633 sectorTr = &trk.Tracks()[itr];
634 int32_t localId = mTrackIDs[((sectorTr->LocalTrackId() >> 24) & 0x3F) * mNMaxSingleSectorTracks + (sectorTr->LocalTrackId() & 0xFFFFFF)];
638 uint32_t myTrack = CAMath::AtomicAdd(&mMemory->nUnpackedTracks, 1u);
640 SetTrackClusterT(track, iSector, sectorTr);
641 track.Set(
this, sectorTr,
alpha, iSector);
642 track.SetGlobalSectorTrackCov();
643 track.SetPrevNeighbour(-1);
644 track.SetNextNeighbour(-1);
645 track.SetNextSegmentNeighbour(-1);
646 track.SetPrevSegmentNeighbour(-1);
647 track.SetLocalTrackId(localId | (sectorTr->LocalTrackId() & 0x40000000));
651GPUd()
void GPUTPCGMMerger::UnpackResetIds(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector)
653 const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSector];
654 uint32_t nLocalTracks = trk.CommonMemory()->nLocalTracks;
655 for (uint32_t
i = iBlock * nThreads + iThread;
i < nLocalTracks;
i += nBlocks * nThreads) {
656 mTrackIDs[iSector * mNMaxSingleSectorTracks +
i] = -1;
660GPUd()
void GPUTPCGMMerger::RefitSectorTracks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector)
662 const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[iSector];
663 uint32_t nLocalTracks = trk.CommonMemory()->nLocalTracks;
665 float alpha = Param().Alpha(iSector);
668 for (uint32_t itr = iBlock * nThreads + iThread; itr < nLocalTracks; itr += nBlocks * nThreads) {
669 sectorTr = &trk.Tracks()[itr];
671 SetTrackClusterT(track, iSector, sectorTr);
672 if (RefitSectorTrack(track, sectorTr,
alpha, iSector)) {
673 track.Set(
this, sectorTr,
alpha, iSector);
679 CADEBUG(GPUInfo(
"INPUT Sector %d, Track %u, QPt %f DzDs %f", iSector, itr, track.QPt(), track.DzDs()));
680 track.SetPrevNeighbour(-1);
681 track.SetNextNeighbour(-1);
682 track.SetNextSegmentNeighbour(-1);
683 track.SetPrevSegmentNeighbour(-1);
684 track.SetExtrapolatedTrackId(0, -1);
685 track.SetExtrapolatedTrackId(1, -1);
686 uint32_t myTrack = CAMath::AtomicAdd(&mMemory->nUnpackedTracks, 1u);
687 mTrackIDs[iSector * mNMaxSingleSectorTracks + sectorTr->LocalTrackId()] = myTrack;
688 mSectorTrackInfos[myTrack] = track;
692GPUd()
void GPUTPCGMMerger::LinkExtrapolatedTracks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
694 for (int32_t itr = SectorTrackInfoGlobalFirst(0) + iBlock * nThreads + iThread; itr < SectorTrackInfoGlobalLast(NSECTORS - 1); itr += nThreads * nBlocks) {
696 GPUTPCGMSectorTrack& localTrack = mSectorTrackInfos[extrapolatedTrack.LocalTrackId() & 0xFFFFFF];
697 int up = (extrapolatedTrack.LocalTrackId() & 0x40000000) ? 1 : 0;
698 localTrack.SetExtrapolatedTrackId(up, itr);
707 float fieldBz = Param().bzCLight;
709 float dAlpha = Param().dAlpha / 2;
713 dAlpha = dAlpha - CAMath::Pi() / 2;
714 }
else if (iBorder == 1) {
715 dAlpha = -dAlpha - CAMath::Pi() / 2;
716 }
else if (iBorder == 2) {
717 x0 = GPUTPCGeometry::Row2X(63);
718 }
else if (iBorder == 3) {
720 x0 = GPUTPCGeometry::Row2X(63);
721 }
else if (iBorder == 4) {
723 x0 = GPUTPCGeometry::Row2X(63);
726 const float maxSin = CAMath::Sin(60.f / 180.f * CAMath::Pi());
727 float cosAlpha = CAMath::Cos(dAlpha);
728 float sinAlpha = CAMath::Sin(dAlpha);
731 for (int32_t itr = iBlock * nThreads + iThread; itr < SectorTrackInfoLocalTotal(); itr += nThreads * nBlocks) {
733 int32_t iSector = track->Sector();
735 if (track->PrevSegmentNeighbour() >= 0 && track->Sector() == mSectorTrackInfos[track->PrevSegmentNeighbour()].Sector()) {
738 if (useOrigTrackParam) {
739 if (CAMath::Abs(track->QPt()) * Param().qptB5Scaler < Param().rec.tpc.mergerLooperQPtB5Limit) {
743 while (track->NextSegmentNeighbour() >= 0 && track->Sector() == mSectorTrackInfos[track->NextSegmentNeighbour()].Sector()) {
744 track = &mSectorTrackInfos[track->NextSegmentNeighbour()];
745 if (track->OrigTrack()->Param().X() < trackMin->OrigTrack()->Param().X()) {
749 trackTmp = *trackMin;
751 if (trackTmp.X2() != 0.f) {
752 trackTmp.UseParam2();
754 trackTmp.Set(
this, trackMin->OrigTrack(), trackMin->Alpha(), trackMin->Sector());
757 if (CAMath::Abs(track->QPt()) * Param().qptB5Scaler < Param().rec.tpc.mergerLooperSecondHorizontalQPtB5Limit) {
758 if (iBorder == 0 && track->NextNeighbour() >= 0) {
761 if (iBorder == 1 && track->PrevNeighbour() >= 0) {
768 if (track->TransportToXAlpha(
this,
x0, sinAlpha, cosAlpha, fieldBz,
b, maxSin)) {
770 b.SetNClusters(track->NClusters());
771 for (int32_t
i = 0;
i < 4;
i++) {
772 if (CAMath::Abs(
b.Cov()[
i]) >= 5.0f) {
776 if (CAMath::Abs(
b.Cov()[4]) >= 0.5f) {
779 uint32_t myTrack = CAMath::AtomicAdd(&nB[iSector], 1u);
780 B[iSector][myTrack] =
b;
786GPUd()
void GPUTPCGMMerger::MergeBorderTracks<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector1,
GPUTPCGMBorderTrack* B1, int32_t N1, int32_t iSector2,
GPUTPCGMBorderTrack* B2, int32_t N2, int32_t mergeMode)
788 CADEBUG(GPUInfo(
"\nMERGING Sectors %d %d NTracks %d %d CROSS %d", iSector1, iSector2, N1, N2, mergeMode));
790 GPUTPCGMBorderRange* range2 = mBorderRange[iSector2] + *GetConstantMem()->tpcTrackers[iSector2].NTracks();
791 bool sameSector = (iSector1 == iSector2);
792 for (int32_t itr = iBlock * nThreads + iThread; itr < N1; itr += nThreads * nBlocks) {
794 float d = CAMath::Max(0.5f, 3.5f * CAMath::Sqrt(
b.Cov()[1]));
795 if (CAMath::Abs(
b.Par()[4]) * Param().qptB5Scaler >= 20) {
800 CADEBUG(printf(
" Input Sector 1 %d Track %d: ", iSector1, itr);
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Par()[
i]); } printf(
" - ");
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Cov()[
i]); } printf(
" - D %8.3f\n", d));
803 range.fMin =
b.Par()[1] +
b.ZOffsetLinear() - d;
804 range.fMax =
b.Par()[1] +
b.ZOffsetLinear() + d;
811 for (int32_t itr = iBlock * nThreads + iThread; itr < N2; itr += nThreads * nBlocks) {
813 float d = CAMath::Max(0.5f, 3.5f * CAMath::Sqrt(
b.Cov()[1]));
814 if (CAMath::Abs(
b.Par()[4]) * Param().qptB5Scaler >= 20) {
819 CADEBUG(printf(
" Input Sector 2 %d Track %d: ", iSector2, itr);
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Par()[
i]); } printf(
" - ");
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Cov()[
i]); } printf(
" - D %8.3f\n", d));
822 range.fMin =
b.Par()[1] +
b.ZOffsetLinear() - d;
823 range.fMax =
b.Par()[1] +
b.ZOffsetLinear() + d;
830GPUd()
void GPUTPCGMMerger::MergeBorderTracks<1>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector1,
GPUTPCGMBorderTrack* B1, int32_t N1, int32_t iSector2,
GPUTPCGMBorderTrack* B2, int32_t N2, int32_t mergeMode)
832#if !defined(GPUCA_GPUCODE_COMPILEKERNELS)
834 GPUTPCGMBorderRange* range2 = mBorderRange[iSector2] + *GetConstantMem()->tpcTrackers[iSector2].NTracks();
839 }
else if (iBlock == 1) {
844 printf(
"This sorting variant is disabled for RTC");
851#ifndef GPUCA_SPECIALIZE_THRUST_SORTS
852 if (iThread == 0 && iBlock == 0) {
863GPUd()
void GPUTPCGMMerger::MergeBorderTracks<2>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector1,
GPUTPCGMBorderTrack* B1, int32_t N1, int32_t iSector2,
GPUTPCGMBorderTrack* B2, int32_t N2, int32_t mergeMode)
866 float factor2ys = Param().rec.tpc.trackMergerFactor2YS;
867 float factor2zt = Param().rec.tpc.trackMergerFactor2ZT;
868 float factor2k = Param().rec.tpc.trackMergerFactor2K;
869 float factor2General = Param().rec.tpc.trackMergerFactor2General;
871 factor2k = factor2General * factor2k;
872 factor2ys = factor2General * factor2ys;
873 factor2zt = factor2General * factor2zt;
875 int32_t minNPartHits = Param().rec.tpc.trackMergerMinPartHits;
876 int32_t minNTotalHits = Param().rec.tpc.trackMergerMinTotalHits;
878 bool sameSector = (iSector1 == iSector2);
881 GPUTPCGMBorderRange* range2 = mBorderRange[iSector2] + *GetConstantMem()->tpcTrackers[iSector2].NTracks();
884 for (int32_t i1 = iBlock * nThreads + iThread; i1 < N1; i1 += nThreads * nBlocks) {
886 while (i2 < N2 && range2[i2].fMax < r1.
fMin) {
891 if (b1.NClusters() < minNPartHits) {
897 for (int32_t k2 = i2; k2 < N2; k2++) {
902 if (sameSector && (r1.
fId >= r2.
fId)) {
908#if defined(GPUCA_MERGER_BY_MC_LABEL) && !defined(GPUCA_GPUCODE)
909 int64_t label1 = GetTrackLabel(b1);
910 int64_t label2 = GetTrackLabel(b2);
911 if (label1 != label2 && label1 != -1)
914 CADEBUG(
if (GetConstantMem()->ioPtrs.mcLabelsTPC) {printf(
"Comparing track %3d to %3d: ", r1.fId, r2.fId); for (int32_t i = 0; i < 5; i++) { printf(
"%8.3f ", b1.Par()[i]); } printf(
" - ");
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ", b1.Cov()[
i]); } printf(
"\n%28s",
""); });
915 CADEBUG(
if (GetConstantMem()->ioPtrs.mcLabelsTPC) {for (int32_t i = 0; i < 5; i++) { printf(
"%8.3f ", b2.Par()[i]); } printf(
" - ");
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ", b2.Cov()[
i]); } printf(
" - %5s - ", GetTrackLabel(b1) == GetTrackLabel(b2) ?
"CLONE" :
"FAKE"); });
916 if (b2.NClusters() < lBest2) {
917 CADEBUG2(
continue, printf(
"!NCl1\n"));
921 int32_t maxRowDiff = mergeMode == 2 ? 1 : 3;
922 if (CAMath::Abs(b1.Row() - b2.Row()) > maxRowDiff) {
923 CADEBUG2(
continue, printf(
"!ROW\n"));
925 if (CAMath::Abs(b1.Par()[2] - b2.Par()[2]) > 0.5f || CAMath::Abs(b1.Par()[3] - b2.Par()[3]) > 0.5f) {
926 CADEBUG2(
continue, printf(
"!CE SinPhi/Tgl\n"));
932 if (!b1.CheckChi2Y(b2, factor2ys)) {
936 if (!b1.CheckChi2QPt(b2, factor2k)) {
937 CADEBUG2(
continue, printf(
"!QPt\n"));
939 float fys = CAMath::Abs(b1.Par()[4]) * Param().qptB5Scaler < 20 ? factor2ys : (2.f * factor2ys);
940 float fzt = CAMath::Abs(b1.Par()[4]) * Param().qptB5Scaler < 20 ? factor2zt : (2.f * factor2zt);
941 if (!b1.CheckChi2YS(b2, fys)) {
942 CADEBUG2(
continue, printf(
"!YS\n"));
944 if (!b1.CheckChi2ZT(b2, fzt)) {
945 CADEBUG2(
continue, printf(
"!ZT\n"));
947 if (CAMath::Abs(b1.Par()[4]) * Param().qptB5Scaler < 20) {
948 if (b2.NClusters() < minNPartHits) {
949 CADEBUG2(
continue, printf(
"!NCl2\n"));
951 if (b1.NClusters() + b2.NClusters() < minNTotalHits) {
952 CADEBUG2(
continue, printf(
"!NCl3\n"));
955 CADEBUG(printf(
"OK: dZ %8.3f D1 %8.3f D2 %8.3f\n", CAMath::Abs(b1.Par()[1] - b2.Par()[1]), 3.5f * sqrt(b1.Cov()[1]), 3.5f * sqrt(b2.Cov()[1])));
957 lBest2 = b2.NClusters();
958 iBest2 = b2.TrackID();
964 GPUCA_DEBUG_STREAMER_CHECK(
float weight = b1.Par()[4] * b1.Par()[4];
if (o2::utils::DebugStreamer::checkStream(
o2::utils::StreamFlags::streamMergeBorderTracksBest, b1.TrackID(),
weight)) { MergedTrackStreamer(b1, MergedTrackStreamerFindBorderTrack(B2, N2, iBest2),
"merge_best_track", iSector1, iSector2, mergeMode,
weight, o2::utils::DebugStreamer::getSamplingFrequency(
o2::utils::StreamFlags::streamMergeBorderTracksBest)); });
968 CADEBUG(GPUInfo(
"Found match %d %d", b1.TrackID(), iBest2));
970 mTrackLinks[b1.TrackID()] = iBest2;
972 GPUCA_DETERMINISTIC_CODE(CAMath::AtomicMax(&mTrackLinks[iBest2], b1.TrackID()), mTrackLinks[iBest2] = b1.TrackID());
980 if (withinSector == 1) {
982 n1 = n2 = mMemory->tmpCounter[iSector];
983 b1 = b2 = mBorder[iSector];
984 }
else if (withinSector == -1) {
985 jSector = (iSector + NSECTORS / 2);
986 const int32_t
offset = mergeMode == 2 ? NSECTORS : 0;
987 n1 = mMemory->tmpCounter[iSector +
offset];
988 n2 = mMemory->tmpCounter[jSector +
offset];
989 b1 = mBorder[iSector +
offset];
990 b2 = mBorder[jSector +
offset];
992 jSector = mNextSectorInd[iSector];
993 n1 = mMemory->tmpCounter[iSector];
994 n2 = mMemory->tmpCounter[NSECTORS + jSector];
995 b1 = mBorder[iSector];
996 b2 = mBorder[NSECTORS + jSector];
1001GPUd()
void GPUTPCGMMerger::MergeBorderTracks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector, int8_t withinSector, int8_t mergeMode)
1006 MergeBorderTracksSetup(n1, n2, b1, b2, jSector, iSector, withinSector, mergeMode);
1007 MergeBorderTracks<I>(nBlocks, nThreads, iBlock, iThread, iSector, b1, n1, jSector, b2, n2, mergeMode);
1010#if !defined(GPUCA_GPUCODE) || defined(GPUCA_GPUCODE_DEVICE)
1011template GPUdni()
void GPUTPCGMMerger::MergeBorderTracks<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector, int8_t withinSector, int8_t mergeMode);
1012template
GPUdni()
void GPUTPCGMMerger::MergeBorderTracks<1>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector, int8_t withinSector, int8_t mergeMode);
1013template
GPUdni()
void GPUTPCGMMerger::MergeBorderTracks<2>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t iSector, int8_t withinSector, int8_t mergeMode);
1016GPUd()
void GPUTPCGMMerger::MergeWithinSectorsPrepare(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1018 float x0 = GPUTPCGeometry::Row2X(63);
1019 const float maxSin = CAMath::Sin(60.f / 180.f * CAMath::Pi());
1021 for (int32_t itr = iBlock * nThreads + iThread; itr < SectorTrackInfoLocalTotal(); itr += nThreads * nBlocks) {
1023 int32_t iSector = track.Sector();
1025 if (track.TransportToX(
this,
x0, Param().bzCLight,
b, maxSin)) {
1027 CADEBUG(printf(
"WITHIN SECTOR %d Track %d - ", iSector, itr);
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Par()[
i]); } printf(
" - ");
for (int32_t
i = 0;
i < 5;
i++) { printf(
"%8.3f ",
b.Cov()[
i]); } printf(
"\n"));
1028 b.SetNClusters(track.NClusters());
1029 uint32_t myTrack = CAMath::AtomicAdd(&mMemory->tmpCounter[iSector], 1u);
1030 mBorder[iSector][myTrack] =
b;
1035GPUd()
void GPUTPCGMMerger::MergeSectorsPrepare(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, int32_t border0, int32_t border1, int8_t useOrigTrackParam)
1037 bool part2 = iBlock & 1;
1038 int32_t
border = part2 ? border1 : border0;
1039 GPUAtomic(uint32_t)*
n = mMemory->tmpCounter;
1045 MergeSectorsPrepareStep2((nBlocks + !part2) >> 1, nThreads, iBlock >> 1, iThread,
border,
b,
n, useOrigTrackParam);
1050 start = (elems + nBlocks - 1) / nBlocks * iBlock;
1051 end = (elems + nBlocks - 1) / nBlocks * (iBlock + 1);
1052 end = CAMath::Min(elems,
end);
1061 u = mTrackCCRoots[u];
1062 v = mTrackCCRoots[
v];
1066 int32_t
h = CAMath::Max(u,
v);
1067 int32_t l = CAMath::Min(u,
v);
1069 int32_t old = CAMath::AtomicCAS(&mTrackCCRoots[
h],
h, l);
1074 u = mTrackCCRoots[
h];
1079GPUd()
void GPUTPCGMMerger::ResolveFindConnectedComponentsSetup(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1082 setBlockRange(SectorTrackInfoLocalTotal(), nBlocks, iBlock,
start,
end);
1083 for (int32_t
i =
start + iThread;
i <
end;
i += nThreads) {
1084 mTrackCCRoots[
i] =
i;
1088GPUd()
void GPUTPCGMMerger::ResolveFindConnectedComponentsHookLinks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1093 setBlockRange(SectorTrackInfoLocalTotal(), nBlocks, iBlock,
start,
end);
1094 for (int32_t itr =
start + iThread; itr <
end; itr += nThreads) {
1095 hookEdge(itr, mTrackLinks[itr]);
1099GPUd()
void GPUTPCGMMerger::ResolveFindConnectedComponentsHookNeighbors(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1102 nBlocks = nBlocks / 4 * 4;
1103 if (iBlock >= nBlocks) {
1108 setBlockRange(SectorTrackInfoLocalTotal(), nBlocks / 4, iBlock / 4,
start,
end);
1110 int32_t myNeighbor = iBlock % 4;
1112 for (int32_t itr =
start + iThread; itr <
end; itr += nThreads) {
1113 int32_t
v = mSectorTrackInfos[itr].AnyNeighbour(myNeighbor);
1118GPUd()
void GPUTPCGMMerger::ResolveFindConnectedComponentsMultiJump(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1122 setBlockRange(SectorTrackInfoLocalTotal(), nBlocks, iBlock,
start,
end);
1123 for (int32_t itr =
start + iThread; itr <
end; itr += nThreads) {
1125 int32_t next = mTrackCCRoots[root];
1131 next = mTrackCCRoots[next];
1132 }
while (root != next);
1133 mTrackCCRoots[itr] = root;
1170 setBlockRange(SectorTrackInfoLocalTotal(), nBlocks, iBlock,
start,
end);
1172 for (int32_t baseIdx = 0; baseIdx < SectorTrackInfoLocalTotal(); baseIdx += nThreads) {
1173 int32_t itr = baseIdx + iThread;
1174 bool inRange = itr < SectorTrackInfoLocalTotal();
1178 itr2 = mTrackLinks[itr];
1181 bool resolveSector = (itr2 > -1);
1182 if (resolveSector) {
1183 int32_t root = mTrackCCRoots[itr];
1184 resolveSector &= (
start <= root) && (root <
end);
1187 int16_t smemIdx = work_group_scan_inclusive_add(int16_t(resolveSector));
1189 if (resolveSector) {
1190 smem.iTrack1[smemIdx - 1] = itr;
1191 smem.iTrack2[smemIdx - 1] = itr2;
1195 if (iThread < nThreads - 1) {
1199 const int32_t nSectors = smemIdx;
1201 for (int32_t
i = 0;
i < nSectors;
i++) {
1202 itr = smem.iTrack1[
i];
1203 itr2 = smem.iTrack2[
i];
1210 bool sameSegment = CAMath::Abs(track1->NClusters() > track2->NClusters() ? track1->QPt() : track2->QPt()) * Param().qptB5Scaler < 2 || track1->QPt() * track2->QPt() > 0;
1215 while (track2->PrevSegmentNeighbour() >= 0) {
1216 track2 = &mSectorTrackInfos[track2->PrevSegmentNeighbour()];
1219 if (track1 == track2) {
1222 while (track1->PrevSegmentNeighbour() >= 0) {
1223 track1 = &mSectorTrackInfos[track1->PrevSegmentNeighbour()];
1224 if (track1 == track2) {
1228 GPUCommonAlgorithm::swap(track1, track1Base);
1229 for (int32_t k = 0; k < 2; k++) {
1231 while (tmp->Neighbour(k) >= 0) {
1232 tmp = &mSectorTrackInfos[tmp->Neighbour(k)];
1233 if (tmp == track2) {
1239 while (track1->NextSegmentNeighbour() >= 0) {
1240 track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()];
1241 if (track1 == track2) {
1246 while (track1->PrevSegmentNeighbour() >= 0) {
1247 track1 = &mSectorTrackInfos[track1->PrevSegmentNeighbour()];
1250 if (track1 == track2) {
1253 for (int32_t k = 0; k < 2; k++) {
1255 while (tmp->Neighbour(k) >= 0) {
1256 tmp = &mSectorTrackInfos[tmp->Neighbour(k)];
1257 if (tmp == track2) {
1263 float z1min, z1max, z2min, z2max;
1264 z1min = track1->MinClusterT();
1265 z1max = track1->MaxClusterT();
1266 z2min = track2->MinClusterT();
1267 z2max = track2->MaxClusterT();
1268 if (track1 != track1Base) {
1269 z1min = CAMath::Min(z1min, track1Base->MinClusterT());
1270 z1max = CAMath::Max(z1max, track1Base->MaxClusterT());
1272 if (track2 != track2Base) {
1273 z2min = CAMath::Min(z2min, track2Base->MinClusterT());
1274 z2max = CAMath::Max(z2max, track2Base->MaxClusterT());
1276 bool goUp = z2max - z1min > z1max - z2min;
1278 if (track1->Neighbour(goUp) < 0 && track2->Neighbour(!goUp) < 0) {
1279 track1->SetNeighbor(track2 - mSectorTrackInfos, goUp);
1280 track2->SetNeighbor(track1 - mSectorTrackInfos, !goUp);
1284 }
else if (track1->Neighbour(goUp) < 0) {
1285 track2 = &mSectorTrackInfos[track2->Neighbour(!goUp)];
1286 GPUCommonAlgorithm::swap(track1, track2);
1287 }
else if (track2->Neighbour(!goUp) < 0) {
1288 track1 = &mSectorTrackInfos[track1->Neighbour(goUp)];
1290 track1 = &mSectorTrackInfos[track1->Neighbour(goUp)];
1292 track1Base = track1;
1295 track2Base = track2;
1297 while (track1->NextSegmentNeighbour() >= 0) {
1298 track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()];
1301 track1->SetNextSegmentNeighbour(track2 - mSectorTrackInfos);
1302 track2->SetPrevSegmentNeighbour(track1 - mSectorTrackInfos);
1305 for (int32_t k = 0; k < 2; k++) {
1306 track1 = track1Base;
1307 track2 = track2Base;
1308 while (track2->Neighbour(k) >= 0) {
1309 if (track1->Neighbour(k) >= 0) {
1312 track2->SetNeighbor(-1, k);
1313 track2new->SetNeighbor(-1, k ^ 1);
1315 while (track1->NextSegmentNeighbour() >= 0) {
1316 track1 = &mSectorTrackInfos[track1->NextSegmentNeighbour()];
1318 track1->SetNextSegmentNeighbour(track2new - mSectorTrackInfos);
1319 track2new->SetPrevSegmentNeighbour(track1 - mSectorTrackInfos);
1324 track1->SetNeighbor(track2->Neighbour(k), k);
1325 track2->SetNeighbor(-1, k);
1326 track2new->SetNeighbor(track1 - mSectorTrackInfos, k ^ 1);
1339 if (Param().
rec.tpc.mergerCERowLimit > 0 && CAMath::Abs(track->QPt()) * Param().qptB5Scaler < 0.3f && (cls.row < Param().
rec.tpc.mergerCERowLimit || cls.row >=
GPUCA_ROW_COUNT - Param().
rec.tpc.mergerCERowLimit)) {
1346 auto& cln = mConstantMem->ioPtrs.clustersNative->clustersLinear[cls.num];
1347 GPUTPCConvertImpl::convert(*mConstantMem, cls.sector, cls.row, cln.getPad(), cln.getTime(),
x,
y,
z);
1350 if (!Param().
par.continuousTracking && CAMath::Abs(
z) > 10) {
1353 int32_t sector = track->Sector();
1354 for (int32_t attempt = 0; attempt < 2; attempt++) {
1356 const float x0 = GPUTPCGeometry::Row2X(attempt == 0 ? 63 : cls.
row);
1359 b.SetNClusters(mMergedTracks[itr].NClusters());
1360 if (CAMath::Abs(
b.Cov()[4]) >= 0.5f) {
1363 if (track->CSide()) {
1364 b.SetPar(1,
b.Par()[1] - 2 * (
z -
b.ZOffsetLinear()));
1365 b.SetZOffsetLinear(-
b.ZOffsetLinear());
1368 uint32_t
id = sector + attempt * NSECTORS;
1369 uint32_t myTrack = CAMath::AtomicAdd(&mMemory->tmpCounter[
id], 1u);
1370 mBorder[
id][myTrack] =
b;
1378 const ClusterNative* cls = mConstantMem->ioPtrs.clustersNative->clustersLinear;
1379 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nThreads * nBlocks) {
1380 if (mMergedTracks[
i].CSide() == 0 && mTrackLinks[
i] >= 0) {
1381 if (mTrackLinks[mTrackLinks[
i]] != (int32_t)
i) {
1386 if (!trk[1]->OK() || trk[1]->CCE()) {
1389 bool celooper = (trk[0]->GetParam().GetQPt() * Param().qptB5Scaler > 1 && trk[0]->GetParam().GetQPt() * trk[1]->GetParam().GetQPt() < 0);
1390 celooper |= trk[0]->PrevSegment() != -1 && trk[1]->PrevSegment() != -1;
1391 if (!celooper && trk[0]->GetParam().GetPar(3) * trk[1]->GetParam().GetPar(3) < 0) {
1395 bool needswap =
false;
1396 if (trk[0]->PrevSegment() == -1 && trk[1]->PrevSegment() >= 0) {
1398 }
else if (celooper) {
1399 const float z0max = -CAMath::Min(cls[mClusters[trk[0]->FirstClusterRef()].
num].
getTime(), cls[mClusters[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].
num].
getTime());
1400 const float z1max = -CAMath::Min(cls[mClusters[trk[1]->FirstClusterRef()].
num].
getTime(), cls[mClusters[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].
num].
getTime());
1401 if (z1max < z0max) {
1405 if (mClusters[trk[0]->FirstClusterRef()].
row > mClusters[trk[1]->FirstClusterRef()].
row) {
1410 GPUCommonAlgorithm::swap(trk[0], trk[1]);
1413 if (Param().
par.continuousTracking) {
1415 const float tmax = CAMath::MaxWithRef(cls[mClusters[trk[0]->FirstClusterRef()].
num].
getTime(), cls[mClusters[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1].
num].
getTime(),
1416 cls[mClusters[trk[1]->FirstClusterRef()].
num].
getTime(), cls[mClusters[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1].
num].
getTime(),
1417 &mClusters[trk[0]->FirstClusterRef()], &mClusters[trk[0]->FirstClusterRef() + trk[0]->NClusters() - 1],
1418 &mClusters[trk[1]->FirstClusterRef()], &mClusters[trk[1]->FirstClusterRef() + trk[1]->NClusters() - 1], clsmax);
1419 const float offset = CAMath::Max(tmax - mConstantMem->calibObjects.fastTransformHelper->getCorrMap()->getMaxDriftTime(clsmax->
sector, clsmax->
row, cls[clsmax->
num].getPad()), 0.f);
1420 trk[1]->Param().Z() += mConstantMem->calibObjects.fastTransformHelper->getCorrMap()->convDeltaTimeToDeltaZinTimeFrame(trk[1]->CSide() * NSECTORS / 2, trk[1]->Param().TOffset() -
offset);
1421 trk[1]->Param().TOffset() =
offset;
1423 trk[0]->Param().Z() += mConstantMem->calibObjects.fastTransformHelper->getCorrMap()->convDeltaTimeToDeltaZinTimeFrame(trk[0]->CSide() * NSECTORS / 2, trk[0]->Param().TOffset() -
offset);
1424 trk[0]->Param().TOffset() =
offset;
1429 trk[0]->SetMergedLooperConnected(
true);
1430 trk[0]->SetCCE(
true);
1431 trk[0]->SetLooper(
true);
1432 trk[1]->SetMergedLooperConnected(
true);
1433 trk[1]->SetCCE(
true);
1434 trk[1]->SetLooper(
true);
1438 uint32_t newRef = CAMath::AtomicAdd(&mMemory->nMergedTrackClusters, trk[0]->NClusters() + trk[1]->NClusters());
1439 if (newRef + trk[0]->NClusters() + trk[1]->NClusters() >= mNMaxMergedTrackClusters) {
1440 raiseError(GPUErrors::ERROR_MERGER_CE_HIT_OVERFLOW, newRef + trk[0]->NClusters() + trk[1]->NClusters(), mNMaxMergedTrackClusters);
1441 for (uint32_t k = newRef; k < mNMaxMergedTrackClusters; k++) {
1442 mClusters[k].num = 0;
1443 mClusters[k].state = 0;
1445 CAMath::AtomicExch(&mMemory->nMergedTrackClusters, mNMaxMergedTrackClusters);
1449 int32_t
pos = newRef;
1451 for (int32_t k = 1; k >= 0; k--) {
1452 for (uint32_t
j = 0;
j != trk[k]->NClusters();
j++) {
1453 mClusters[
pos++] = mClusters[trk[k]->FirstClusterRef() +
j];
1456 trk[1]->SetFirstClusterRef(newRef);
1457 trk[1]->SetNClusters(trk[0]->NClusters() + trk[1]->NClusters());
1462 trk[1]->SetCCE(
true);
1463 trk[0]->SetNClusters(0);
1464 trk[0]->SetOK(
false);
1475struct GPUTPCGMMerger_CompareClusterIds {
1479 GPUd() bool operator()(const int16_t
aa, const int16_t
bb)
1483 if (
a.row !=
b.row) {
1492GPUd()
void GPUTPCGMMerger::CollectMergedTracks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1494 static constexpr int32_t kMaxParts = 16;
1499 int32_t itr = iBlock * nThreads + iThread;
1502 int32_t lastMergedSegment = -1;
1503 bool revertSegments =
false;
1504 bool revertInSegment =
false;
1506 if (trbase && !Param().
rec.tpc.dropLoopers) {
1507 int32_t jtr = trbase->NextNeighbour();
1509 trbase = &(mSectorTrackInfos[jtr]);
1510 if (trbase->PrevSegmentNeighbour() >= 0) {
1513 if (Param().rec.enableCyclicGraphWorkarounds) {
1514 trbase->SetPrevSegmentNeighbour(1000000001);
1516 leg += revertSegments ? 1 : -1;
1523 if (trbase ==
nullptr) {
1524 while (itr < SectorTrackInfoLocalTotal()) {
1525 trbase = &mSectorTrackInfos[itr];
1526 if (trbase->PrevSegmentNeighbour() >= 0 || trbase->PrevNeighbour() >= 0) {
1527 itr += nThreads * nBlocks;
1532 if (itr >= SectorTrackInfoLocalTotal()) {
1535 revertSegments =
false;
1536 revertInSegment =
false;
1537 if (Param().rec.enableCyclicGraphWorkarounds) {
1538 trbase->SetPrevSegmentNeighbour(1000000000);
1540 int32_t jtr = trbase->NextNeighbour();
1543 int32_t lasttr = itr;
1545 if (Param().rec.enableCyclicGraphWorkarounds && &mSectorTrackInfos[jtr] == trbase) {
1550 jtr = mSectorTrackInfos[jtr].NextNeighbour();
1554 revertSegments =
true;
1555 for (uint32_t k = 0; k < 2; k++) {
1556 int32_t ichk = k ? lasttr : itr;
1559 float t = -trchk->MinClusterT();
1562 revertSegments =
false;
1567 int32_t next = trchk->NextSegmentNeighbour();
1568 if (next < 0 || (Param().
rec.enableCyclicGraphWorkarounds && next == ichk)) {
1571 trchk = &mSectorTrackInfos[next];
1574 if (revertSegments) {
1580 int32_t ichk = revertSegments ? itr : lasttr;
1584 if (trchk->OrigTrack()->NHits() >
length) {
1586 length = trchk->OrigTrack()->NHits();
1588 int32_t next = trchk->NextSegmentNeighbour();
1589 if (next < 0 || (Param().
rec.enableCyclicGraphWorkarounds && next == ichk)) {
1592 trchk = &mSectorTrackInfos[next];
1594 revertInSegment = longest->ClusterT0() < longest->ClusterTN();
1597 lastMergedSegment = -1;
1598 itr += nThreads * nBlocks;
1607 if (nParts >= kMaxParts) {
1610 if (nHits + tr->NClusters() > kMaxClusters) {
1613 nHits += tr->NClusters();
1615 trackParts[nParts++] = tr;
1616 for (int32_t
i = 0;
i < 2;
i++) {
1617 if (tr->ExtrapolatedTrackId(
i) != -1) {
1618 if (nParts >= kMaxParts) {
1621 if (nHits + mSectorTrackInfos[tr->ExtrapolatedTrackId(
i)].NClusters() > kMaxClusters) {
1624 trackParts[nParts++] = &mSectorTrackInfos[tr->ExtrapolatedTrackId(
i)];
1625 nHits += mSectorTrackInfos[tr->ExtrapolatedTrackId(
i)].NClusters();
1628 int32_t jtr = tr->NextSegmentNeighbour();
1630 tr = &(mSectorTrackInfos[jtr]);
1631 if (Param().rec.enableCyclicGraphWorkarounds) {
1632 tr->SetPrevSegmentNeighbour(1000000002);
1640 if (nParts > 1 && (!revertInSegment ^ (leg & 1))) {
1643 if (
a->X() !=
b->X()) {
1644 return (a->X() > b->X());
1646 if (
a->Y() !=
b->Y()) {
1647 return (a->Y() > b->Y());
1649 if (
a->Z() !=
b->Z()) {
1650 return (a->Z() > b->Z());
1652 return a->QPt() >
b->QPt();
1654 return (
a->X() >
b->X());
1659 trackCluster trackClusters[kMaxClusters];
1661 for (int32_t ipart = 0; ipart < nParts; ipart++) {
1663 CADEBUG(printf(
"Collect Track %d Part %d QPt %f DzDs %f\n", mMemory->nMergedTracks, ipart, t->QPt(), t->DzDs()));
1664 int32_t nTrackHits = t->NClusters();
1665 trackCluster* c2 = trackClusters + nHits + nTrackHits - 1;
1666 for (int32_t
i = 0;
i < nTrackHits;
i++, c2--) {
1667 const GPUTPCTracker& trk = GetConstantMem()->tpcTrackers[t->Sector()];
1668 const GPUTPCHitId& ic = trk.TrackHits()[t->OrigTrack()->FirstHitID() +
i];
1669 uint32_t
id = trk.Data().ClusterDataIndex(trk.Data().Row(ic.RowIndex()), ic.HitIndex()) + GetConstantMem()->ioPtrs.clustersNative->clusterOffset[t->Sector()][0];
1670 *c2 = trackCluster{
id, (
uint8_t)ic.RowIndex(), t->Sector()};
1672 nHits += nTrackHits;
1678 const bool mustReverse = revertInSegment ^ (leg & 1);
1681 for (int32_t
i = 1;
i < nHits;
i++) {
1682 if ((trackClusters[
i].
row > trackClusters[
i - 1].
row) ^ mustReverse || trackClusters[
i].id == trackClusters[
i - 1].id) {
1688 int32_t firstTrackIndex = 0;
1689 int32_t lastTrackIndex = nParts - 1;
1691 int32_t nTmpHits = 0;
1692 trackCluster trackClustersUnsorted[kMaxClusters];
1693 int16_t clusterIndices[kMaxClusters];
1694 for (int32_t
i = 0;
i < nHits;
i++) {
1695 trackClustersUnsorted[
i] = trackClusters[
i];
1696 clusterIndices[
i] =
i;
1699 GPUCommonAlgorithm::sort(clusterIndices, clusterIndices + nHits, GPUTPCGMMerger_CompareClusterIds(trackClusters, mustReverse));
1702 firstTrackIndex = lastTrackIndex = -1;
1703 for (int32_t
i = 0;
i < nParts;
i++) {
1704 nTmpHits += trackParts[
i]->NClusters();
1705 if (nTmpHits > clusterIndices[0] && firstTrackIndex == -1) {
1706 firstTrackIndex =
i;
1708 if (nTmpHits > clusterIndices[nHits - 1] && lastTrackIndex == -1) {
1713 int32_t nFilteredHits = 0;
1714 int32_t indPrev = -1;
1715 for (int32_t
i = 0;
i < nHits;
i++) {
1716 int32_t ind = clusterIndices[
i];
1717 if (indPrev >= 0 && trackClustersUnsorted[ind].
id == trackClustersUnsorted[indPrev].
id) {
1721 trackClusters[nFilteredHits] = trackClustersUnsorted[ind];
1724 nHits = nFilteredHits;
1727 const uint32_t iMergedTrackFirstCluster = CAMath::AtomicAdd(&mMemory->nMergedTrackClusters, (uint32_t)nHits);
1728 if (iMergedTrackFirstCluster + nHits > mNMaxMergedTrackClusters) {
1729 raiseError(GPUErrors::ERROR_MERGER_HIT_OVERFLOW, iMergedTrackFirstCluster, mNMaxMergedTrackClusters);
1730 CAMath::AtomicExch(&mMemory->nMergedTrackClusters, mNMaxMergedTrackClusters);
1736 for (int32_t
i = 0;
i < nHits;
i++) {
1738 const ClusterNative&
c = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[trackClusters[
i].id];
1741 cl[
i].
row = trackClusters[
i].row;
1742 cl[
i].
num = trackClusters[
i].id;
1743 cl[
i].
sector = trackClusters[
i].sector;
1746 uint32_t iOutputTrack = CAMath::AtomicAdd(&mMemory->nMergedTracks, 1u);
1747 if (iOutputTrack >= mNMaxTracks) {
1748 raiseError(GPUErrors::ERROR_MERGER_TRACK_OVERFLOW, iOutputTrack, mNMaxTracks);
1749 CAMath::AtomicExch(&mMemory->nMergedTracks, mNMaxTracks);
1756 mergedTrack.SetFlags(0);
1757 mergedTrack.SetOK(
true);
1758 mergedTrack.SetLeg(leg);
1759 mergedTrack.SetLooper(leg > 0);
1760 mergedTrack.SetNClusters(nHits);
1761 mergedTrack.SetFirstClusterRef(iMergedTrackFirstCluster);
1762 mergedTrack.SetCSide(
p2.CSide());
1763 mergedTrack.SetMergedLooperConnected(leg > 0);
1764 if (revertSegments) {
1765 mergedTrack.SetPrevSegment(-1);
1766 if (lastMergedSegment >= 0) {
1767 mMergedTracks[lastMergedSegment].SetPrevSegment(iOutputTrack);
1770 mergedTrack.SetPrevSegment(lastMergedSegment);
1772 lastMergedSegment = iOutputTrack;
1775 const float toX = GPUTPCGeometry::Row2X(cl[0].
row);
1778 p1.Y() =
b.Par()[0];
1779 p1.Z() =
b.Par()[1];
1780 p1.SinPhi() =
b.Par()[2];
1785 p1.SinPhi() =
p2.SinPhi();
1787 p1.TOffset() =
p2.TOffset();
1788 p1.DzDs() =
p2.DzDs();
1789 p1.QPt() =
p2.QPt();
1790 mergedTrack.SetAlpha(
p2.Alpha());
1791 if (CAMath::Abs(Param().polynomialField.GetNominalBz()) < (gpu_common_constants::kZeroFieldCut * gpu_common_constants::kCLight)) {
1792 p1.QPt() = 100.f / Param().rec.bz0Pt10MeV;
1803 if (leg == 0 && Param().
rec.tpc.mergeCE) {
1804 auto& cls = mConstantMem->ioPtrs.clustersNative->clustersLinear;
1805 bool CEside = cls[cl[0].
num].getTime() < cls[cl[nHits - 1].
num].getTime();
1806 MergeCEFill(trackParts[CEside ? lastTrackIndex : firstTrackIndex], cl[CEside ? (nHits - 1) : 0], iOutputTrack);
1812GPUd()
void GPUTPCGMMerger::SortTracksPrepare(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1814 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nThreads * nBlocks) {
1815 mTrackOrderProcess[
i] =
i;
1819GPUd()
void GPUTPCGMMerger::PrepareForFit0(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1821 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nBlocks * nThreads) {
1826GPUd()
void GPUTPCGMMerger::SortTracks(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1828#ifndef GPUCA_SPECIALIZE_THRUST_SORTS
1829 if (iThread == 0 && iBlock == 0) {
1830 GPUCommonAlgorithm::sortDeviceDynamic(mTrackOrderProcess, mTrackOrderProcess + mMemory->nMergedTracks,
GPUTPCGMMergerSortTracks_comp(mMergedTracks));
1835GPUd()
void GPUTPCGMMerger::SortTracksQPt(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1837#ifndef GPUCA_SPECIALIZE_THRUST_SORTS
1838 if (iThread == 0 && iBlock == 0) {
1844GPUd()
void GPUTPCGMMerger::PrepareForFit1(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1846 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nBlocks * nThreads) {
1847 mTrackOrderAttach[mTrackSort[
i]] =
i;
1850 for (uint32_t
j = 0;
j < trk.NClusters();
j++) {
1852 if (CAMath::Abs(trk.GetParam().GetQPt() * Param().qptB5Scaler) <= Param().
rec.tpc.rejectQPtB5 && !trk.MergedLooper() && trk.Leg() == 0) {
1855 mClusterAttachment[mClusters[trk.FirstClusterRef() +
j].num] =
weight;
1856 CAMath::AtomicAdd(&mSharedCount[mClusters[trk.FirstClusterRef() +
j].num], 1u);
1858 if (!trk.CCE() && !trk.MergedLooper()) {
1859 GPUTPCGMMergedTrack* updTrk = trk.GetFirstSegment(mMergedTracks, Param().
rec.enableCyclicGraphWorkarounds);
1860 const auto &cl0 = mClusters[trk.FirstClusterRef()], &cln = mClusters[updTrk->FirstClusterRef() + updTrk->NClusters() - 1];
1861 const auto&
GPUrestrict() cls = GetConstantMem()->ioPtrs.clustersNative->clustersLinear;
1863 const auto tmp = zn > z0 ?
std::
array<
float, 3>{zn, z0, GPUTPCGeometry::Row2X(cln.row)} : std::array<float, 3>{z0, zn, GPUTPCGeometry::Row2X(cl0.row)};
1864 trk.Param().ShiftZ(
this, cl0.sector, tmp[0], tmp[1], tmp[2]);
1866 while (updTrk->PrevSegment() >= 0) {
1867 auto next = &mMergedTracks[updTrk->PrevSegment()];
1868 if (Param().
rec.enableCyclicGraphWorkarounds && next == &trk) {
1872 updTrk->Param().TOffset() = trk.Param().TOffset();
1879GPUd()
void GPUTPCGMMerger::PrepareForFit2(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1881 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTrackClusters;
i += nBlocks * nThreads) {
1882 if (mSharedCount[mClusters[
i].
num] > 1) {
1886 if (mClusterStateExt) {
1887 for (uint32_t
i = iBlock * nThreads + iThread;
i < mNMaxClusters;
i += nBlocks * nThreads) {
1888 uint8_t state = GetConstantMem()->ioPtrs.clustersNative->clustersLinear[
i].getFlags();
1889 if (mSharedCount[
i] > 1) {
1892 mClusterStateExt[
i] =
state;
1899 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nThreads * nBlocks) {
1900 mTrackSort[mTrackOrderAttach[
i]] =
i;
1902 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTrackClusters;
i += nThreads * nBlocks) {
1904 mClusterAttachment[mClusters[
i].num] = 0;
1911 for (uint32_t
i = iBlock * nThreads + iThread;
i < mMemory->nMergedTracks;
i += nThreads * nBlocks) {
1913 if (!trk.OK() || trk.NClusters() == 0) {
1916 for (uint32_t
j = 0;
j < trk.NClusters();
j++) {
1917 int32_t
id = mClusters[trk.FirstClusterRef() +
j].num;
1919 uint8_t clusterState = mClusters[trk.FirstClusterRef() +
j].state;
1925 if (trk.Leg() == 0) {
1928 if (CAMath::Abs(trk.GetParam().GetQPt() * Param().qptB5Scaler) <= Param().
rec.tpc.rejectQPtB5 && !trk.MergedLooper() && trk.Leg() == 0) {
1931 CAMath::AtomicMax(&mClusterAttachment[
id],
weight);
1938 for (uint32_t
i = iBlock * nThreads + iThread;
i < mNMaxClusters;
i += nThreads * nBlocks) {
1939 if (mClusterAttachment[
i] != 0) {
1945GPUd()
void GPUTPCGMMerger::MergeLoopersInit(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1947 const float lowPtThresh = Param().rec.tpc.rejectQPtB5 * 1.1f;
1949 const auto& trk = mMergedTracks[
i];
1950 const auto&
p = trk.GetParam();
1951 const float qptabs = CAMath::Abs(
p.GetQPt());
1952 if (trk.OK() && trk.NClusters() && trk.Leg() == 0 && qptabs * Param().qptB5Scaler > 5.f && qptabs * Param().qptB5Scaler <= lowPtThresh) {
1953 const int32_t sector = mClusters[trk.FirstClusterRef() + trk.NClusters() - 1].sector;
1954 const float refz =
p.GetZ() + (Param().par.continuousTracking ? GetConstantMem()->calibObjects.fastTransformHelper->getCorrMap()->convVertexTimeToZOffset(sector,
p.GetTOffset(), Param().continuousMaxTimeBin) : 0) + (trk.CSide() ? -100 : 100);
1956 CAMath::SinCos(trk.GetAlpha(), sinA, cosA);
1957 float gx = cosA *
p.GetX() - sinA *
p.GetY();
1958 float gy = cosA *
p.GetY() + sinA *
p.GetX();
1959 float bz = Param().polynomialField.GetFieldBz(gx, gy,
p.GetZ());
1960 const float r1 =
p.GetQPt() * bz;
1961 const float r = CAMath::Abs(r1) > 0.0001f ? (1.f / r1) : 10000;
1962 const float mx =
p.GetX() +
r *
p.GetSinPhi();
1963 const float my =
p.GetY() -
r * CAMath::Sqrt(1 -
p.GetSinPhi() *
p.GetSinPhi());
1964 const float gmx = cosA * mx - sinA * my;
1965 const float gmy = cosA * my + sinA * mx;
1966 uint32_t myId = CAMath::AtomicAdd(&mMemory->nLooperMatchCandidates, 1u);
1967 if (myId >= mNMaxLooperMatches) {
1968 raiseError(GPUErrors::ERROR_LOOPER_MATCH_OVERFLOW, myId, mNMaxLooperMatches);
1969 CAMath::AtomicExch(&mMemory->nLooperMatchCandidates, mNMaxLooperMatches);
1990GPUd()
void GPUTPCGMMerger::MergeLoopersSort(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
1992#ifndef GPUCA_SPECIALIZE_THRUST_SORTS
1993 if (iThread == 0 && iBlock == 0) {
1999GPUd()
void GPUTPCGMMerger::MergeLoopersMain(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread)
2003#if GPUCA_MERGE_LOOPER_MC && !defined(GPUCA_GPUCODE)
2004 std::vector<int64_t> paramLabels(mMemory->nLooperMatchCandidates);
2005 for (uint32_t
i = 0;
i < mMemory->nLooperMatchCandidates;
i++) {
2006 paramLabels[
i] = GetTrackLabel(mMergedTracks[candidates[
i].
id]);
2012 if (!mRec->GetProcessingSettings().runQA) {
2013 throw std::runtime_error(
"Need QA enabled for the Merge Loopers MC QA");
2018 for (uint32_t
j =
i + 1;
j < mMemory->nLooperMatchCandidates;
j++) {
2020 assert(CAMath::Abs(candidates[
i].refz) <= CAMath::Abs(candidates[
j].refz));
2021 if (CAMath::Abs(candidates[
j].refz) > CAMath::Abs(candidates[
i].refz) + 100.f) {
2024 const float d2xy = CAMath::Sum2(candidates[
i].
x - candidates[
j].
x, candidates[
i].
y - candidates[
j].
y);
2031 float refZI = candidates[
i].refz;
2033 const auto* tmp = trkI->GetFirstSegment(mMergedTracks, Param().
rec.enableCyclicGraphWorkarounds);
2034 if (tmp != trkI && tmp->CSide() == trkI->CSide() && CAMath::Abs(tmp->GetParam().GetZ()) > CAMath::Abs(trkI->GetParam().GetZ())) {
2035 float tmpRefZ = refZI + tmp->GetParam().GetZ() - trkI->GetParam().GetZ();
2036 if (CAMath::Abs(tmpRefZ) < CAMath::Abs(candidates[
j].refz) && CAMath::Abs(tmpRefZ) > CAMath::Abs(refZI)) {
2042 const auto& trk1 = *trkI;
2043 const auto& trk2 = mMergedTracks[candidates[
j].id];
2044 const auto& param1 = trk1.GetParam();
2045 const auto& param2 = trk2.GetParam();
2046 if (CAMath::Abs(param1.GetDzDs()) > 0.03f && CAMath::Abs(param2.GetDzDs()) > 0.03f && param1.GetDzDs() * param2.GetDzDs() * param1.GetQPt() * param2.GetQPt() < 0) {
2051 const float dznormalized = (CAMath::Abs(candidates[
j].refz) - CAMath::Abs(refZI)) / (CAMath::TwoPi() * 0.5f * (CAMath::Abs(param1.GetDzDs()) + CAMath::Abs(param2.GetDzDs())) * 1.f / (0.5f * (CAMath::Abs(param1.GetQPt()) + CAMath::Abs(param2.GetQPt())) * CAMath::Abs(Param().polynomialField.GetNominalBz())));
2052 const float phasecorr = CAMath::Modf((CAMath::ASin(param1.GetSinPhi()) + trk1.GetAlpha() - CAMath::ASin(param2.GetSinPhi()) - trk2.GetAlpha()) / CAMath::TwoPi() + 5.5f, 1.f) - 0.5f;
2053 const float phasecorrdirection = (candidates[
j].refz * param1.GetQPt() * param1.GetDzDs()) > 0 ? 1 : -1;
2054 const float dzcorr = dznormalized + phasecorr * phasecorrdirection;
2055 const bool sameside = !(trk1.CSide() ^ trk2.CSide());
2056 const float dzcorrlimit[4] = {sameside ? 0.018f : 0.012f, sameside ? 0.12f : 0.025f, 0.14f, 0.15f};
2057 const int32_t dzcorrcount = sameside ? 4 : 2;
2058 bool dzcorrok =
false;
2060 for (int32_t k = 0; k < dzcorrcount; k++) {
2061 const float d = CAMath::Abs(dzcorr - 0.5f * k);
2062 if (d <= dzcorrlimit[k]) {
2064 dznorm = d / dzcorrlimit[k];
2073 const float dtgl = param1.GetDzDs() - (param1.GetQPt() * param2.GetQPt() > 0 ? param2.GetDzDs() : -param2.GetDzDs());
2074 const float dqpt = (CAMath::Abs(param1.GetQPt()) - CAMath::Abs(param2.GetQPt())) / CAMath::Min(param1.GetQPt(), param2.GetQPt());
2075 float d = CAMath::Sum2(dtgl * (1.f / 0.03f), dqpt * (1.f / 0.04f)) + d2xy * (1.f / 4.f) + dznorm * (1.f / 0.3f);
2077#if GPUCA_MERGE_LOOPER_MC && !defined(GPUCA_GPUCODE)
2078 const int64_t label1 = paramLabels[
i];
2079 const int64_t label2 = paramLabels[
j];
2080 bool labelEQ = label1 != -1 && label1 == label2;
2081 if (1 || EQ || labelEQ) {
2083 static auto& tup =
GPUROOTDump<TNtuple>::get(
"mergeloopers",
"labeleq:sides:d2xy:tgl1:tgl2:qpt1:qpt2:dz:dzcorr:dtgl:dqpt:dznorm:bs");
2084 tup.Fill((
float)labelEQ, (trk1.CSide() ? 1 : 0) | (trk2.CSide() ? 2 : 0), d2xy, param1.GetDzDs(), param2.GetDzDs(), param1.GetQPt(), param2.GetQPt(),
CAMath::
Abs(candidates[
j].refz) -
CAMath::
Abs(refZI), dzcorr, dtgl, dqpt, dznorm, bs);
2085 static auto tup2 =
GPUROOTDump<TNtuple>::getNew(
"mergeloopers2",
"labeleq:refz1:refz2:tgl1:tgl2:qpt1:qpt2:snp1:snp2:a1:a2:dzn:phasecor:phasedir:dzcorr");
2086 tup2.Fill((
float)labelEQ, refZI, candidates[
j].refz, param1.GetDzDs(), param2.GetDzDs(), param1.GetQPt(), param2.GetQPt(), param1.GetSinPhi(), param2.GetSinPhi(), trk1.GetAlpha(), trk2.GetAlpha(), dznormalized, phasecorr, phasecorrdirection, dzcorr);
2100 mMergedTracks[candidates[
j].id].SetMergedLooperUnconnected(
true);
2101 if (CAMath::Abs(param2.GetQPt() * Param().qptB5Scaler) >= Param().
rec.tpc.rejectQPtB5) {
2102 mMergedTracks[candidates[
i].id].SetMergedLooperUnconnected(
true);
Class of a TPC cluster in TPC-native coordinates (row, time)
A const (ready only) version of MCTruthContainer.
#define get_global_size(dim)
#define get_global_id(dim)
#define GPUCA_DEBUG_STREAMER_CHECK(...)
#define GPUCA_DETERMINISTIC_CODE(det, indet)
#define GPUCA_MERGER_MAX_TRACK_CLUSTERS
#define GPUCA_MAX_SIN_PHI_LOW
#define GPUCA_TRACKLET_SELECTOR_MIN_HITS_B5(QPTB5)
#define GPUCA_MAX_SIN_PHI
#define CADEBUG2(cmd,...)
const GPUTPCGMMerger::trackCluster *const mCmp
constexpr int p1()
constexpr to accelerate the coordinates changing
Class for time synchronization of RawReader instances.
static void computePointerWithAlignment(T *&basePtr, S *&objPtr, size_t nEntries=1)
void AllocateAndInitializeLate()
static GPUROOTDump< T, Args... > getNew(const char *name1, Names... names)
static GPUROOTDump< T, Args... > & get(const char *name1, Names... names)
RecoStepField GetRecoStepsGPU() const
int16_t RegisterMemoryAllocation(T *proc, void *(T::*setPtr)(void *), int32_t type, const char *name="", const GPUMemoryReuse &re=GPUMemoryReuse())
RecoStepField GetRecoSteps() const
const GPUParam & GetParam() const
const GPUConstantMem & GetConstantMem() const
GPUMemorySizeScalers * MemoryScalers()
const GPUSettingsProcessing & GetProcessingSettings() const
virtual const GPUDefParameters & getGPUParameters(bool doGPU) const =0
void * SetPointersRefitScratch(void *mem)
void CheckCollectedTracks()
void RegisterMemoryAllocation()
void * SetPointersMemory(void *mem)
static constexpr const int32_t NSECTORS
void * SetPointersOutput(void *mem)
void InitializeProcessor()
void * SetPointersOutputO2MC(void *mem)
void * SetPointersOutputO2Scratch(void *mem)
void * SetPointersMerger(void *mem)
void * SetPointersOutputO2Clus(void *mem)
void * SetPointersOutputState(void *mem)
void SetMaxData(const GPUTrackingInOutPointers &io)
void * SetPointersOutputO2(void *mem)
int32_t int32_t int32_t bool float float Z
int32_t int32_t int32_t bool float Y
GLint GLint GLsizei GLint border
GLfloat GLfloat GLfloat alpha
GLuint GLuint GLfloat weight
GLboolean GLboolean GLboolean b
GLuint GLsizei GLsizei * length
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t
Node par(int index)
Parameters.
GPUd() const expr uint32_t MultivariatePolynomialHelper< Dim
if(!okForPhiMin(phi0, phi1))
Global TPC definitions and constants.
@ streamMergeBorderTracksBest
stream MergeBorderTracks best track
@ streamMergeBorderTracksAll
stream MergeBorderTracks all tracks
Defining DataPointCompositeObject explicitly as copiable.
std::string getTime(uint64_t ts)
GPUTPCTracker tpcTrackers[GPUCA_NSECTORS]
size_t getValue(size_t maxVal, size_t val)
size_t NTPCMergedTrackHits(size_t tpcSectorTrackHitss)
size_t NTPCMergedTracks(size_t tpcSectorTracks)
@ clustererAndSharedFlags
const o2::tpc::ClusterNativeAccess * clustersNative
const GPUTPCGMMergedTrack & GPUrestrict() b
GPUd() bool operator()(const int32_t aa
const GPUTPCGMMergedTrack *const mCmp
GPUhd() GPUTPCGMMergerSortTracksQPt_comp(GPUTPCGMMergedTrack *cmp)
const GPUTPCGMMergedTrack & GPUrestrict() b
GPUhd() GPUTPCGMMergerSortTracks_comp(GPUTPCGMMergedTrack *cmp)
GPUd() bool operator()(const int32_t aa
const GPUTPCGMMergedTrack *const mCmp
unsigned int nClustersTotal
char const *restrict const cmp