File indexing completed on 2024-04-23 22:56:30
0001 #ifndef RecoTracker_PixelSeeding_plugins_alpaka_CACell_h
0002 #define RecoTracker_PixelSeeding_plugins_alpaka_CACell_h
0003
0004
0005
0006 #include <cmath>
0007 #include <limits>
0008
0009 #include <alpaka/alpaka.hpp>
0010
0011 #include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
0012 #include "DataFormats/TrackSoA/interface/TracksSoA.h"
0013 #include "DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h"
0014 #include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
0015 #include "HeterogeneousCore/AlpakaInterface/interface/SimpleVector.h"
0016 #include "HeterogeneousCore/AlpakaInterface/interface/VecArray.h"
0017 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0018 #include "RecoTracker/PixelSeeding/interface/CircleEq.h"
0019
0020 #include "CAStructures.h"
0021
0022 namespace ALPAKA_ACCELERATOR_NAMESPACE {
0023 template <typename TrackerTraits>
0024 class CACellT {
0025 public:
0026 using PtrAsInt = unsigned long long;
0027
0028 static constexpr auto maxCellsPerHit = TrackerTraits::maxCellsPerHit;
0029 using OuterHitOfCellContainer = caStructures::OuterHitOfCellContainerT<TrackerTraits>;
0030 using OuterHitOfCell = caStructures::OuterHitOfCellT<TrackerTraits>;
0031 using CellNeighbors = caStructures::CellNeighborsT<TrackerTraits>;
0032 using CellTracks = caStructures::CellTracksT<TrackerTraits>;
0033 using CellNeighborsVector = caStructures::CellNeighborsVectorT<TrackerTraits>;
0034 using CellTracksVector = caStructures::CellTracksVectorT<TrackerTraits>;
0035
0036 using HitsConstView = TrackingRecHitSoAConstView<TrackerTraits>;
0037 using hindex_type = typename TrackerTraits::hindex_type;
0038 using tindex_type = typename TrackerTraits::tindex_type;
0039 static constexpr auto invalidHitId = std::numeric_limits<hindex_type>::max();
0040
0041 using TmpTuple = cms::alpakatools::VecArray<uint32_t, TrackerTraits::maxDepth>;
0042
0043 using HitContainer = typename reco::TrackSoA<TrackerTraits>::HitContainer;
0044 using Quality = ::pixelTrack::Quality;
0045 static constexpr auto bad = ::pixelTrack::Quality::bad;
0046
0047 enum class StatusBit : uint16_t { kUsed = 1, kInTrack = 2, kKilled = 1 << 15 };
0048
0049 CACellT() = default;
0050
0051 ALPAKA_FN_ACC ALPAKA_FN_INLINE void init(CellNeighborsVector& cellNeighbors,
0052 CellTracksVector& cellTracks,
0053 const HitsConstView& hh,
0054 int layerPairId,
0055 hindex_type innerHitId,
0056 hindex_type outerHitId) {
0057 theInnerHitId = innerHitId;
0058 theOuterHitId = outerHitId;
0059 theLayerPairId_ = layerPairId;
0060 theStatus_ = 0;
0061 theFishboneId = invalidHitId;
0062
0063
0064 theInnerZ = hh[innerHitId].zGlobal();
0065 theInnerR = hh[innerHitId].rGlobal();
0066
0067
0068 theOuterNeighbors = &cellNeighbors[0];
0069 theTracks = &cellTracks[0];
0070 ALPAKA_ASSERT_ACC(outerNeighbors().empty());
0071 ALPAKA_ASSERT_ACC(tracks().empty());
0072 }
0073
0074 template <typename TAcc>
0075 ALPAKA_FN_ACC ALPAKA_FN_INLINE __attribute__((always_inline)) int addOuterNeighbor(
0076 const TAcc& acc, typename TrackerTraits::cindex_type t, CellNeighborsVector& cellNeighbors) {
0077
0078 if (outerNeighbors().empty()) {
0079 auto i = cellNeighbors.extend(acc);
0080 if (i > 0) {
0081 cellNeighbors[i].reset();
0082 alpaka::mem_fence(acc, alpaka::memory_scope::Grid{});
0083 #ifdef ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED
0084 theOuterNeighbors = &cellNeighbors[i];
0085 #else
0086 auto zero = (PtrAsInt)(&cellNeighbors[0]);
0087 alpaka::atomicCas(acc,
0088 (PtrAsInt*)(&theOuterNeighbors),
0089 zero,
0090 (PtrAsInt)(&cellNeighbors[i]),
0091 alpaka::hierarchy::Blocks{});
0092 #endif
0093 } else
0094 return -1;
0095 }
0096 alpaka::mem_fence(acc, alpaka::memory_scope::Grid{});
0097 return outerNeighbors().push_back(acc, t);
0098 }
0099
0100 template <typename TAcc>
0101 ALPAKA_FN_ACC ALPAKA_FN_INLINE __attribute__((always_inline)) int addTrack(TAcc const& acc,
0102 tindex_type t,
0103 CellTracksVector& cellTracks) {
0104 if (tracks().empty()) {
0105 auto i = cellTracks.extend(acc);
0106 if (i > 0) {
0107 cellTracks[i].reset();
0108 alpaka::mem_fence(acc, alpaka::memory_scope::Grid{});
0109 #ifdef ALPAKA_ACC_CPU_B_SEQ_T_SEQ_ENABLED
0110 theTracks = &cellTracks[i];
0111 #else
0112 auto zero = (PtrAsInt)(&cellTracks[0]);
0113 alpaka::atomicCas(acc,
0114 (PtrAsInt*)(&theTracks),
0115 zero,
0116 (PtrAsInt)(&cellTracks[i]),
0117 alpaka::hierarchy::Blocks{});
0118
0119 #endif
0120 } else
0121 return -1;
0122 }
0123 alpaka::mem_fence(acc, alpaka::memory_scope::Grid{});
0124 return tracks().push_back(acc, t);
0125 }
0126
0127 ALPAKA_FN_ACC ALPAKA_FN_INLINE CellTracks& tracks() { return *theTracks; }
0128 ALPAKA_FN_ACC ALPAKA_FN_INLINE CellTracks const& tracks() const { return *theTracks; }
0129 ALPAKA_FN_ACC ALPAKA_FN_INLINE CellNeighbors& outerNeighbors() { return *theOuterNeighbors; }
0130 ALPAKA_FN_ACC ALPAKA_FN_INLINE CellNeighbors const& outerNeighbors() const { return *theOuterNeighbors; }
0131 ALPAKA_FN_ACC ALPAKA_FN_INLINE float inner_x(const HitsConstView& hh) const { return hh[theInnerHitId].xGlobal(); }
0132 ALPAKA_FN_ACC ALPAKA_FN_INLINE float outer_x(const HitsConstView& hh) const { return hh[theOuterHitId].xGlobal(); }
0133 ALPAKA_FN_ACC ALPAKA_FN_INLINE float inner_y(const HitsConstView& hh) const { return hh[theInnerHitId].yGlobal(); }
0134 ALPAKA_FN_ACC ALPAKA_FN_INLINE float outer_y(const HitsConstView& hh) const { return hh[theOuterHitId].yGlobal(); }
0135 ALPAKA_FN_ACC ALPAKA_FN_INLINE float inner_z(const HitsConstView& hh) const { return theInnerZ; }
0136 ALPAKA_FN_ACC ALPAKA_FN_INLINE float outer_z(const HitsConstView& hh) const { return hh[theOuterHitId].zGlobal(); }
0137 ALPAKA_FN_ACC ALPAKA_FN_INLINE float inner_r(const HitsConstView& hh) const { return theInnerR; }
0138 ALPAKA_FN_ACC ALPAKA_FN_INLINE float outer_r(const HitsConstView& hh) const { return hh[theOuterHitId].rGlobal(); }
0139
0140 ALPAKA_FN_ACC ALPAKA_FN_INLINE auto inner_iphi(const HitsConstView& hh) const { return hh[theInnerHitId].iphi(); }
0141 ALPAKA_FN_ACC ALPAKA_FN_INLINE auto outer_iphi(const HitsConstView& hh) const { return hh[theOuterHitId].iphi(); }
0142
0143 ALPAKA_FN_ACC ALPAKA_FN_INLINE float inner_detIndex(const HitsConstView& hh) const {
0144 return hh[theInnerHitId].detectorIndex();
0145 }
0146 ALPAKA_FN_ACC ALPAKA_FN_INLINE float outer_detIndex(const HitsConstView& hh) const {
0147 return hh[theOuterHitId].detectorIndex();
0148 }
0149
0150 constexpr unsigned int inner_hit_id() const { return theInnerHitId; }
0151 constexpr unsigned int outer_hit_id() const { return theOuterHitId; }
0152
0153 ALPAKA_FN_ACC void print_cell() const {
0154 printf("printing cell: on layerPair: %d, innerHitId: %d, outerHitId: %d \n",
0155 theLayerPairId_,
0156 theInnerHitId,
0157 theOuterHitId);
0158 }
0159
0160 ALPAKA_FN_ACC bool check_alignment(const HitsConstView& hh,
0161 CACellT const& otherCell,
0162 const float ptmin,
0163 const float hardCurvCut,
0164 const float caThetaCutBarrel,
0165 const float caThetaCutForward,
0166 const float dcaCutInnerTriplet,
0167 const float dcaCutOuterTriplet) const {
0168
0169
0170
0171 auto ri = inner_r(hh);
0172 auto zi = inner_z(hh);
0173
0174 auto ro = outer_r(hh);
0175 auto zo = outer_z(hh);
0176
0177 auto r1 = otherCell.inner_r(hh);
0178 auto z1 = otherCell.inner_z(hh);
0179 auto isBarrel = otherCell.outer_detIndex(hh) < TrackerTraits::last_barrel_detIndex;
0180
0181 bool aligned = areAlignedRZ(r1, z1, ri, zi, ro, zo, ptmin, isBarrel ? caThetaCutBarrel : caThetaCutForward);
0182 return (aligned && dcaCut(hh,
0183 otherCell,
0184 otherCell.inner_detIndex(hh) < TrackerTraits::last_bpix1_detIndex ? dcaCutInnerTriplet
0185 : dcaCutOuterTriplet,
0186 hardCurvCut));
0187 }
0188
0189 ALPAKA_FN_ACC ALPAKA_FN_INLINE __attribute__((always_inline)) static bool areAlignedRZ(
0190 float r1, float z1, float ri, float zi, float ro, float zo, const float ptmin, const float thetaCut) {
0191 float radius_diff = std::abs(r1 - ro);
0192 float distance_13_squared = radius_diff * radius_diff + (z1 - zo) * (z1 - zo);
0193
0194 float pMin = ptmin * std::sqrt(distance_13_squared);
0195
0196
0197 float tan_12_13_half_mul_distance_13_squared = fabs(z1 * (ri - ro) + zi * (ro - r1) + zo * (r1 - ri));
0198 return tan_12_13_half_mul_distance_13_squared * pMin <= thetaCut * distance_13_squared * radius_diff;
0199 }
0200
0201 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool dcaCut(const HitsConstView& hh,
0202 CACellT const& otherCell,
0203 const float region_origin_radius_plus_tolerance,
0204 const float maxCurv) const {
0205 auto x1 = otherCell.inner_x(hh);
0206 auto y1 = otherCell.inner_y(hh);
0207
0208 auto x2 = inner_x(hh);
0209 auto y2 = inner_y(hh);
0210
0211 auto x3 = outer_x(hh);
0212 auto y3 = outer_y(hh);
0213
0214 CircleEq<float> eq(x1, y1, x2, y2, x3, y3);
0215
0216 if (eq.curvature() > maxCurv)
0217 return false;
0218
0219 return std::abs(eq.dca0()) < region_origin_radius_plus_tolerance * std::abs(eq.curvature());
0220 }
0221
0222 ALPAKA_FN_ACC ALPAKA_FN_INLINE __attribute__((always_inline)) static bool dcaCutH(
0223 float x1,
0224 float y1,
0225 float x2,
0226 float y2,
0227 float x3,
0228 float y3,
0229 const float region_origin_radius_plus_tolerance,
0230 const float maxCurv) {
0231 CircleEq<float> eq(x1, y1, x2, y2, x3, y3);
0232
0233 if (eq.curvature() > maxCurv)
0234 return false;
0235
0236 return std::abs(eq.dca0()) < region_origin_radius_plus_tolerance * std::abs(eq.curvature());
0237 }
0238
0239 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool hole0(const HitsConstView& hh, CACellT const& innerCell) const {
0240 using namespace phase1PixelTopology;
0241
0242 int p = innerCell.inner_iphi(hh);
0243 if (p < 0)
0244 p += std::numeric_limits<unsigned short>::max();
0245 p = (max_ladder_bpx0 * p) / std::numeric_limits<unsigned short>::max();
0246 p %= max_ladder_bpx0;
0247 auto il = first_ladder_bpx0 + p;
0248 auto r0 = hh.averageGeometry().ladderR[il];
0249 auto ri = innerCell.inner_r(hh);
0250 auto zi = innerCell.inner_z(hh);
0251 auto ro = outer_r(hh);
0252 auto zo = outer_z(hh);
0253 auto z0 = zi + (r0 - ri) * (zo - zi) / (ro - ri);
0254 auto z_in_ladder = std::abs(z0 - hh.averageGeometry().ladderZ[il]);
0255 auto z_in_module = z_in_ladder - module_length_bpx0 * int(z_in_ladder / module_length_bpx0);
0256 auto gap = z_in_module < module_tolerance_bpx0 || z_in_module > (module_length_bpx0 - module_tolerance_bpx0);
0257 return gap;
0258 }
0259
0260 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool hole4(const HitsConstView& hh, CACellT const& innerCell) const {
0261 using namespace phase1PixelTopology;
0262
0263 int p = outer_iphi(hh);
0264 if (p < 0)
0265 p += std::numeric_limits<unsigned short>::max();
0266 p = (max_ladder_bpx4 * p) / std::numeric_limits<unsigned short>::max();
0267 p %= max_ladder_bpx4;
0268 auto il = first_ladder_bpx4 + p;
0269 auto r4 = hh.averageGeometry().ladderR[il];
0270 auto ri = innerCell.inner_r(hh);
0271 auto zi = innerCell.inner_z(hh);
0272 auto ro = outer_r(hh);
0273 auto zo = outer_z(hh);
0274 auto z4 = zo + (r4 - ro) * (zo - zi) / (ro - ri);
0275 auto z_in_ladder = std::abs(z4 - hh.averageGeometry().ladderZ[il]);
0276 auto z_in_module = z_in_ladder - module_length_bpx4 * int(z_in_ladder / module_length_bpx4);
0277 auto gap = z_in_module < module_tolerance_bpx4 || z_in_module > (module_length_bpx4 - module_tolerance_bpx4);
0278 auto holeP = z4 > hh.averageGeometry().ladderMaxZ[il] && z4 < hh.averageGeometry().endCapZ[0];
0279 auto holeN = z4 < hh.averageGeometry().ladderMinZ[il] && z4 > hh.averageGeometry().endCapZ[1];
0280 return gap || holeP || holeN;
0281 }
0282
0283
0284
0285 template <int DEPTH, typename TAcc>
0286 ALPAKA_FN_ACC ALPAKA_FN_INLINE void find_ntuplets(TAcc const& acc,
0287 const HitsConstView& hh,
0288 CACellT* __restrict__ cells,
0289 CellTracksVector& cellTracks,
0290 HitContainer& foundNtuplets,
0291 cms::alpakatools::AtomicPairCounter& apc,
0292 Quality* __restrict__ quality,
0293 TmpTuple& tmpNtuplet,
0294 const unsigned int minHitsPerNtuplet,
0295 bool startAt0) const {
0296
0297
0298
0299
0300
0301
0302 if constexpr (DEPTH <= 0) {
0303 printf("ERROR: CACellT::find_ntuplets reached full depth!\n");
0304 ALPAKA_ASSERT_ACC(false);
0305 } else {
0306 auto doubletId = this - cells;
0307 tmpNtuplet.push_back_unsafe(doubletId);
0308 ALPAKA_ASSERT_ACC(tmpNtuplet.size() <= int(TrackerTraits::maxHitsOnTrack - 3));
0309
0310 bool last = true;
0311 for (unsigned int otherCell : outerNeighbors()) {
0312 if (cells[otherCell].isKilled())
0313 continue;
0314 last = false;
0315 cells[otherCell].template find_ntuplets<DEPTH - 1>(
0316 acc, hh, cells, cellTracks, foundNtuplets, apc, quality, tmpNtuplet, minHitsPerNtuplet, startAt0);
0317 }
0318 if (last) {
0319 if ((unsigned int)(tmpNtuplet.size()) >= minHitsPerNtuplet - 1) {
0320 #ifdef ONLY_TRIPLETS_IN_HOLE
0321
0322 if (tmpNtuplet.size() >= 3 || (startAt0 && hole4(hh, cells[tmpNtuplet[0]])) ||
0323 ((!startAt0) && hole0(hh, cells[tmpNtuplet[0]])))
0324 #endif
0325 {
0326 hindex_type hits[TrackerTraits::maxDepth + 2];
0327 auto nh = 0U;
0328 constexpr int maxFB = 2;
0329 int nfb = 0;
0330 for (auto c : tmpNtuplet) {
0331 hits[nh++] = cells[c].theInnerHitId;
0332 if (nfb < maxFB && cells[c].hasFishbone()) {
0333 ++nfb;
0334 hits[nh++] = cells[c].theFishboneId;
0335 }
0336 }
0337 ALPAKA_ASSERT_ACC(nh < TrackerTraits::maxHitsOnTrack);
0338 hits[nh] = theOuterHitId;
0339 auto it = foundNtuplets.bulkFill(acc, apc, hits, nh + 1);
0340 if (it >= 0) {
0341 for (auto c : tmpNtuplet)
0342 cells[c].addTrack(acc, it, cellTracks);
0343 quality[it] = bad;
0344 }
0345 }
0346 }
0347 }
0348 tmpNtuplet.pop_back();
0349 ALPAKA_ASSERT_ACC(tmpNtuplet.size() < int(TrackerTraits::maxHitsOnTrack - 1));
0350 }
0351 }
0352
0353
0354 ALPAKA_FN_ACC ALPAKA_FN_INLINE void kill() { theStatus_ |= uint16_t(StatusBit::kKilled); }
0355 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool isKilled() const { return theStatus_ & uint16_t(StatusBit::kKilled); }
0356
0357 ALPAKA_FN_ACC ALPAKA_FN_INLINE int16_t layerPairId() const { return theLayerPairId_; }
0358
0359 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool unused() const { return 0 == (uint16_t(StatusBit::kUsed) & theStatus_); }
0360 ALPAKA_FN_ACC ALPAKA_FN_INLINE void setStatusBits(StatusBit mask) { theStatus_ |= uint16_t(mask); }
0361
0362 template <typename TAcc>
0363 ALPAKA_FN_ACC ALPAKA_FN_INLINE void setFishbone(TAcc const& acc, hindex_type id, float z, const HitsConstView& hh) {
0364
0365 auto old = theFishboneId;
0366 while (old !=
0367 alpaka::atomicCas(
0368 acc,
0369 &theFishboneId,
0370 old,
0371 (invalidHitId == old || std::abs(z - theInnerZ) > std::abs(hh[old].zGlobal() - theInnerZ)) ? id : old,
0372 alpaka::hierarchy::Blocks{}))
0373 old = theFishboneId;
0374 }
0375 ALPAKA_FN_ACC ALPAKA_FN_INLINE auto fishboneId() const { return theFishboneId; }
0376 ALPAKA_FN_ACC ALPAKA_FN_INLINE bool hasFishbone() const { return theFishboneId != invalidHitId; }
0377
0378 private:
0379 CellNeighbors* theOuterNeighbors;
0380 CellTracks* theTracks;
0381
0382 int16_t theLayerPairId_;
0383 uint16_t theStatus_;
0384
0385 float theInnerZ;
0386 float theInnerR;
0387 hindex_type theInnerHitId;
0388 hindex_type theOuterHitId;
0389 hindex_type theFishboneId;
0390 };
0391
0392 }
0393
0394 #endif