38 static constexpr int MaxLinks = (NLayers * (NLayers - 1)) / 2;
39 static constexpr int MaxCells = (NLayers * (NLayers - 1) * (NLayers - 2)) / 6;
40 using Id = std::conditional_t<MaxCells <= std::numeric_limits<uint8_t>::max(), uint8_t, uint16_t>;
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());
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)));
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));
89 for (
Id linkId = 0; linkId <
nLinks; ++linkId) {
90 const auto& t =
links[linkId];
91 out += fmt::format(
"\n {}: {} -> {}", linkId, t.fromLayer, t.toLayer);
94 for (
Id cellId = 0; cellId <
nCells; ++cellId) {
95 const auto&
c =
cells[cellId];
97 const auto& second =
links[
c.secondLink];
98 out += fmt::format(
"\n {}: {} -> {} -> {} hitMask={} links=({}, {}) maxLevel={}", cellId,
first.fromLayer,
first.toLayer, second.toLayer,
c.hitLayerMask.asString(),
c.firstLink,
c.secondLink,
maxCellLevel !=
nullptr ?
int(
maxCellLevel[cellId]) : -1);
110 void init(
int maxLayers,
int maxHoles,
Mask holeLayerMask,
Mask seedingLayerMask = 0)
113 mMaxLayers = o2::gpu::CAMath::Max(0, o2::gpu::CAMath::Min(maxLayers, NLayers));
114 mMaxHoles = o2::gpu::CAMath::Max(maxHoles, 0);
115 mHoleLayerMask = holeLayerMask;
116 mSeedingLayerMask = seedingLayerMask.empty() ? Mask::span(0, mMaxLayers - 1) : (seedingLayerMask & Mask::span(0, mMaxLayers - 1));
119 LOGP(fatal,
"Tracking topology has {} seeding layers, but at least {} are required to build CA cells", mSeedingLayerMask.count(),
constants::ClustersPerCell);
122 for (
int fromLayer = 0; fromLayer < mMaxLayers; ++fromLayer) {
123 if (!mSeedingLayerMask.has(fromLayer)) {
126 for (
int toLayer = fromLayer + 1; toLayer < mMaxLayers; ++toLayer) {
127 if (mSeedingLayerMask.has(toLayer) && isAllowedSeedingLink(fromLayer, toLayer)) {
128 mLinks[mNLinks++] =
LayerLink{
static_cast<Id>(fromLayer),
static_cast<Id>(toLayer)};
133 for (
Id firstId = 0; firstId < mNLinks; ++firstId) {
134 const auto&
first = mLinks[firstId];
135 for (
Id secondId = 0; secondId < mNLinks; ++secondId) {
136 const auto& second = mLinks[secondId];
137 if (
first.toLayer != second.fromLayer) {
140 const Mask hitMask{
first.fromLayer,
first.toLayer, second.toLayer};
141 if ((hitMask.holeMask() & mSeedingLayerMask).isAllowedHoleMask(mMaxHoles, mHoleLayerMask)) {
142 mCells[mNCells++] =
CellTopology{firstId, secondId, hitMask};
153 return View{mLinks.data(),
155 mCellsByFirstLinkIndex.data(),
156 mCellsByFirstLink.data(),
157 mMaxCellLevel.data(),
166 const Range* deviceCellsByFirstLinkIndex,
167 const Id* deviceCellsByFirstLink)
const
169 return View{deviceLinks,
171 deviceCellsByFirstLinkIndex,
172 deviceCellsByFirstLink,
180 const auto&
getLinks() const noexcept {
return mLinks; }
181 const auto&
getCells() const noexcept {
return mCells; }
194 mNCellsByFirstLink = 0;
197 mCellsByFirstLinkIndex.fill(
Range{0, 0});
198 mCellsByFirstLink.fill(0);
199 mMaxCellLevel.fill(0);
202 void fillMaxCellLevels()
204 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
205 mMaxCellLevel[cellId] = 1;
207 for (
int outerLayer = 0; outerLayer < mMaxLayers; ++outerLayer) {
208 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
209 if (mCells[cellId].hitLayerMask.last() != outerLayer) {
212 const auto& successors = mCellsByFirstLinkIndex[mCells[cellId].secondLink];
213 for (
Id i = 0;
i < successors.getEntries(); ++
i) {
214 const Id next = mCellsByFirstLink[successors.getFirstEntry() +
i];
215 mMaxCellLevel[next] = o2::gpu::CAMath::Max(mMaxCellLevel[next],
static_cast<Id>(mMaxCellLevel[cellId] + 1));
221 void fillCellsByLink()
223 std::array<Id, MaxLinks> counts{};
224 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
225 ++counts[mCells[cellId].firstLink];
229 for (
Id linkId = 0; linkId < mNLinks; ++linkId) {
230 mCellsByFirstLinkIndex[linkId].setFirstEntry(
offset);
231 mCellsByFirstLinkIndex[linkId].setEntries(counts[linkId]);
235 std::array<Id, MaxLinks> cursor{};
236 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
237 const Id linkId = mCells[cellId].firstLink;
238 mCellsByFirstLink[mCellsByFirstLinkIndex[linkId].getFirstEntry() + cursor[linkId]++] = cellId;
240 mNCellsByFirstLink =
offset;
243 bool isAllowedSeedingLink(
int fromLayer,
int toLayer)
const noexcept
245 return (Mask::skipped(fromLayer, toLayer) & mSeedingLayerMask).isAllowedHoleMask(mMaxHoles, mHoleLayerMask);
250 Mask mHoleLayerMask{0};
251 Mask mSeedingLayerMask{0};
254 Id mNCellsByFirstLink{0};
255 std::array<LayerLink, MaxLinks> mLinks{};
256 std::array<CellTopology, MaxCells> mCells{};
257 std::array<Range, MaxLinks> mCellsByFirstLinkIndex{};
258 std::array<Id, MaxCells> mCellsByFirstLink{};
259 std::array<Id, MaxCells> mMaxCellLevel{};