42 static constexpr int MaxCells = (NLayers * (NLayers - 1) * (NLayers - 2)) / 6;
43 static_assert(NLayers < std::numeric_limits<Id>::max());
44 static_assert(MaxTransitions <= std::numeric_limits<Id>::max());
45 static_assert(MaxCells <= std::numeric_limits<Id>::max());
52 static_assert(std::is_standard_layout_v<LayerTransition>);
53 static_assert(std::is_trivially_copyable_v<LayerTransition>);
54 static_assert(
sizeof(LayerTransition) == (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));
84 std::string out = fmt::format(
"TrackingTopology: transitions={} cells={}",
nTransitions,
nCells);
85 out +=
"\n transitions:";
86 for (
Id transitionId = 0; transitionId <
nTransitions; ++transitionId) {
88 out += fmt::format(
"\n {}: {} -> {}", transitionId, t.fromLayer, t.toLayer);
91 for (
Id cellId = 0; cellId <
nCells; ++cellId) {
92 const auto&
c =
cells[cellId];
95 out += fmt::format(
"\n {}: {} -> {} -> {} hitMask={} transitions=({}, {})", cellId,
first.fromLayer,
first.toLayer, second.toLayer,
c.hitLayerMask.asString(),
c.firstTransition,
c.secondTransition);
107 void init(
int maxLayers,
int maxHoles,
Mask holeLayerMask)
110 mMaxLayers = o2::gpu::CAMath::Max(0, o2::gpu::CAMath::Min(maxLayers, NLayers));
111 mMaxHoles = o2::gpu::CAMath::Max(maxHoles, 0);
112 mHoleLayerMask = holeLayerMask;
113 for (
int fromLayer = 0; fromLayer < mMaxLayers; ++fromLayer) {
114 for (
int toLayer = fromLayer + 1; toLayer < mMaxLayers; ++toLayer) {
115 if (Mask::skipped(fromLayer, toLayer).isAllowedHoleMask(mMaxHoles, mHoleLayerMask)) {
116 mTransitions[mNTransitions++] =
LayerTransition{
static_cast<Id>(fromLayer),
static_cast<Id>(toLayer)};
121 for (
Id firstId = 0; firstId < mNTransitions; ++firstId) {
122 const auto&
first = mTransitions[firstId];
123 for (
Id secondId = 0; secondId < mNTransitions; ++secondId) {
124 const auto& second = mTransitions[secondId];
125 if (
first.toLayer != second.fromLayer) {
128 const Mask hitMask{
first.fromLayer,
first.toLayer, second.toLayer};
129 if (hitMask.isAllowed(mMaxHoles, mHoleLayerMask)) {
130 mCells[mNCells++] =
CellTopology{firstId, secondId, hitMask};
135 fillCellsByTransition();
140 return View{mTransitions.data(),
142 mCellsByFirstTransitionIndex.data(),
143 mCellsByFirstTransition.data(),
146 mNCellsByFirstTransition};
151 const Range* deviceCellsByFirstTransitionIndex,
152 const Id* deviceCellsByFirstTransition)
const
154 return View{deviceTransitions,
156 deviceCellsByFirstTransitionIndex,
157 deviceCellsByFirstTransition,
160 mNCellsByFirstTransition};
164 const auto&
getCells() const noexcept {
return mCells; }
176 mNCellsByFirstTransition = 0;
177 mTransitions.fill({});
179 mCellsByFirstTransitionIndex.fill(
Range{0, 0});
180 mCellsByFirstTransition.fill(0);
183 void fillCellsByTransition()
185 std::array<Id, MaxTransitions> counts{};
186 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
187 ++counts[mCells[cellId].firstTransition];
191 for (
Id transitionId = 0; transitionId < mNTransitions; ++transitionId) {
192 mCellsByFirstTransitionIndex[transitionId].setFirstEntry(
offset);
193 mCellsByFirstTransitionIndex[transitionId].setEntries(counts[transitionId]);
194 offset += counts[transitionId];
197 std::array<Id, MaxTransitions> cursor{};
198 for (
Id cellId = 0; cellId < mNCells; ++cellId) {
199 const Id transitionId = mCells[cellId].firstTransition;
200 mCellsByFirstTransition[mCellsByFirstTransitionIndex[transitionId].getFirstEntry() + cursor[transitionId]++] = cellId;
202 mNCellsByFirstTransition =
offset;
207 Mask mHoleLayerMask{0};
210 Id mNCellsByFirstTransition{0};
211 std::array<LayerTransition, MaxTransitions> mTransitions{};
212 std::array<CellTopology, MaxCells> mCells{};
213 std::array<Range, MaxTransitions> mCellsByFirstTransitionIndex{};
214 std::array<Id, MaxCells> mCellsByFirstTransition{};