Project
Loading...
Searching...
No Matches
TrackingTopology.h
Go to the documentation of this file.
1// Copyright 2019-2026 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
12#ifndef TRACKINGITSU_INCLUDE_TRACKINGTOPOLOGY_H_
13#define TRACKINGITSU_INCLUDE_TRACKINGTOPOLOGY_H_
14
15#include <array>
16#include <cstdint>
17#include <limits>
18#include <type_traits>
19
20#ifndef GPUCA_GPUCODE
21#include <fmt/format.h>
22#include <string>
23#include "Framework/Logger.h"
24#endif
25
27#include "GPUCommonDef.h"
28#include "GPUCommonMath.h"
30
31namespace o2::its
32{
33
34template <int NLayers>
36{
37 public:
38 using Id = uint8_t;
39 using Mask = LayerMask;
41 static constexpr int MaxLinks = (NLayers * (NLayers - 1)) / 2;
42 static constexpr int MaxCells = (NLayers * (NLayers - 1) * (NLayers - 2)) / 6;
43 static_assert(NLayers < std::numeric_limits<Id>::max());
44 static_assert(MaxLinks <= std::numeric_limits<Id>::max());
45 static_assert(MaxCells <= std::numeric_limits<Id>::max());
46
47 // Describes from which layer to which layer the look-up happens
48 struct LayerLink {
51 };
52 static_assert(std::is_standard_layout_v<LayerLink>);
53 static_assert(std::is_trivially_copyable_v<LayerLink>);
54 static_assert(sizeof(LayerLink) == (2 * sizeof(Id)));
55
56 // Describes from which LayerLink a tracklet is allowed to originate
57 // and with which LayerLink this can be combined additionally the hitMasked is cached
63 static_assert(std::is_standard_layout_v<CellTopology>);
64 static_assert(std::is_trivially_copyable_v<CellTopology>);
65 static_assert(sizeof(CellTopology) == (2 * sizeof(Id)) + sizeof(Mask));
66
67 // GPU ready view of the underlying LUTs
68 struct View {
69 const LayerLink* links{nullptr};
70 const CellTopology* cells{nullptr};
72 const Id* cellsByFirstLink{nullptr};
77
78 GPUhdi() const LayerLink& getLink(Id id) const { return links[id]; }
79 GPUhdi() const CellTopology& getCell(Id id) const { return cells[id]; }
80 GPUhdi() Range getCellsStartingWithLink(Id linkId) const { return cellsByFirstLinkIndex[linkId]; }
81
82#ifndef GPUCA_GPUCODE
83 std::string asString() const
84 {
85 std::string out = fmt::format("TrackingTopology: links={} cells={} seedingLayers={}", nLinks, nCells, seedingLayerMask.asString());
86 out += "\n links:";
87 for (Id linkId = 0; linkId < nLinks; ++linkId) {
88 const auto& t = links[linkId];
89 out += fmt::format("\n {}: {} -> {}", linkId, t.fromLayer, t.toLayer);
90 }
91 out += "\n cells:";
92 for (Id cellId = 0; cellId < nCells; ++cellId) {
93 const auto& c = cells[cellId];
94 const auto& first = links[c.firstLink];
95 const auto& second = links[c.secondLink];
96 out += fmt::format("\n {}: {} -> {} -> {} hitMask={} links=({}, {})", cellId, first.fromLayer, first.toLayer, second.toLayer, c.hitLayerMask.asString(), c.firstLink, c.secondLink);
97 }
98 return out;
99 }
100
101 void print() const
102 {
103 LOGP(info, "{}", asString());
104 }
105#endif
106 };
107
108 void init(int maxLayers, int maxHoles, Mask holeLayerMask, Mask seedingLayerMask = 0)
109 {
110 clear();
111 mMaxLayers = o2::gpu::CAMath::Max(0, o2::gpu::CAMath::Min(maxLayers, NLayers));
112 mMaxHoles = o2::gpu::CAMath::Max(maxHoles, 0);
113 mHoleLayerMask = holeLayerMask;
114 mSeedingLayerMask = seedingLayerMask.empty() ? Mask::span(0, mMaxLayers - 1) : (seedingLayerMask & Mask::span(0, mMaxLayers - 1));
115#ifndef GPUCA_GPUCODE
116 if (mSeedingLayerMask.count() < constants::ClustersPerCell) {
117 LOGP(fatal, "Tracking topology has {} seeding layers, but at least {} are required to build CA cells", mSeedingLayerMask.count(), constants::ClustersPerCell);
118 }
119#endif
120 for (int fromLayer = 0; fromLayer < mMaxLayers; ++fromLayer) {
121 if (!mSeedingLayerMask.has(fromLayer)) {
122 continue;
123 }
124 for (int toLayer = fromLayer + 1; toLayer < mMaxLayers; ++toLayer) {
125 if (mSeedingLayerMask.has(toLayer) && isAllowedSeedingLink(fromLayer, toLayer)) {
126 mLinks[mNLinks++] = LayerLink{static_cast<Id>(fromLayer), static_cast<Id>(toLayer)};
127 }
128 }
129 }
130
131 for (Id firstId = 0; firstId < mNLinks; ++firstId) {
132 const auto& first = mLinks[firstId];
133 for (Id secondId = 0; secondId < mNLinks; ++secondId) {
134 const auto& second = mLinks[secondId];
135 if (first.toLayer != second.fromLayer) {
136 continue;
137 }
138 const Mask hitMask{first.fromLayer, first.toLayer, second.toLayer};
139 if ((hitMask.holeMask() & mSeedingLayerMask).isAllowedHoleMask(mMaxHoles, mHoleLayerMask)) {
140 mCells[mNCells++] = CellTopology{firstId, secondId, hitMask};
141 }
142 }
143 }
144
145 fillCellsByLink();
146 }
147
148 View getView() const
149 {
150 return View{mLinks.data(),
151 mCells.data(),
152 mCellsByFirstLinkIndex.data(),
153 mCellsByFirstLink.data(),
154 mSeedingLayerMask,
155 mNLinks,
156 mNCells,
157 mNCellsByFirstLink};
158 }
159
160 View getDeviceView(const LayerLink* deviceLinks,
161 const CellTopology* deviceCells,
162 const Range* deviceCellsByFirstLinkIndex,
163 const Id* deviceCellsByFirstLink) const
164 {
165 return View{deviceLinks,
166 deviceCells,
167 deviceCellsByFirstLinkIndex,
168 deviceCellsByFirstLink,
169 mSeedingLayerMask,
170 mNLinks,
171 mNCells,
172 mNCellsByFirstLink};
173 }
174
175 const auto& getLinks() const noexcept { return mLinks; }
176 const auto& getCells() const noexcept { return mCells; }
177 const auto& getCellsByFirstLinkIndex() const noexcept { return mCellsByFirstLinkIndex; }
178 const auto& getCellsByFirstLink() const noexcept { return mCellsByFirstLink; }
179 Id getNLinks() const noexcept { return mNLinks; }
180 Id getNCells() const noexcept { return mNCells; }
181 Id getNCellsByFirstLink() const noexcept { return mNCellsByFirstLink; }
182
183 private:
184 void clear()
185 {
186 mNLinks = 0;
187 mNCells = 0;
188 mNCellsByFirstLink = 0;
189 mLinks.fill({});
190 mCells.fill({});
191 mCellsByFirstLinkIndex.fill(Range{0, 0});
192 mCellsByFirstLink.fill(0);
193 }
194
195 void fillCellsByLink()
196 {
197 std::array<Id, MaxLinks> counts{};
198 for (Id cellId = 0; cellId < mNCells; ++cellId) {
199 ++counts[mCells[cellId].firstLink];
200 }
201
202 Id offset = 0;
203 for (Id linkId = 0; linkId < mNLinks; ++linkId) {
204 mCellsByFirstLinkIndex[linkId].setFirstEntry(offset);
205 mCellsByFirstLinkIndex[linkId].setEntries(counts[linkId]);
206 offset += counts[linkId];
207 }
208
209 std::array<Id, MaxLinks> cursor{};
210 for (Id cellId = 0; cellId < mNCells; ++cellId) {
211 const Id linkId = mCells[cellId].firstLink;
212 mCellsByFirstLink[mCellsByFirstLinkIndex[linkId].getFirstEntry() + cursor[linkId]++] = cellId;
213 }
214 mNCellsByFirstLink = offset;
215 }
216
217 bool isAllowedSeedingLink(int fromLayer, int toLayer) const noexcept
218 {
219 return (Mask::skipped(fromLayer, toLayer) & mSeedingLayerMask).isAllowedHoleMask(mMaxHoles, mHoleLayerMask);
220 }
221
222 int mMaxLayers{0};
223 int mMaxHoles{0};
224 Mask mHoleLayerMask{0};
225 Mask mSeedingLayerMask{0};
226 Id mNLinks{0};
227 Id mNCells{0};
228 Id mNCellsByFirstLink{0};
229 std::array<LayerLink, MaxLinks> mLinks{};
230 std::array<CellTopology, MaxCells> mCells{};
231 std::array<Range, MaxLinks> mCellsByFirstLinkIndex{};
232 std::array<Id, MaxCells> mCellsByFirstLink{};
233};
234
235} // namespace o2::its
236
237#endif
Class to refer to the 1st entry and N elements of some group in the continuous container.
uint32_t c
Definition RawData.h:2
const auto & getCellsByFirstLinkIndex() const noexcept
View getDeviceView(const LayerLink *deviceLinks, const CellTopology *deviceCells, const Range *deviceCellsByFirstLinkIndex, const Id *deviceCellsByFirstLink) const
const auto & getCells() const noexcept
Id getNCellsByFirstLink() const noexcept
o2::dataformats::RangeReference< Id, Id > Range
static constexpr int MaxCells
const auto & getCellsByFirstLink() const noexcept
Id getNLinks() const noexcept
const auto & getLinks() const noexcept
static constexpr int MaxLinks
void init(int maxLayers, int maxHoles, Mask holeLayerMask, Mask seedingLayerMask=0)
Id getNCells() const noexcept
GLintptr offset
Definition glcorearb.h:660
GLuint id
Definition glcorearb.h:650
constexpr int ClustersPerCell
Definition Constants.h:31
GPUhdi() Range getCellsStartingWithLink(Id linkId) const
GPUhdi() const LayerLink &getLink(Id id) const
GPUhdi() const CellTopology &getCell(Id id) const