CMS 3D CMS Logo

MiniDoublet.h
Go to the documentation of this file.
1 #ifndef RecoTracker_LSTCore_src_alpaka_MiniDoublet_h
2 #define RecoTracker_LSTCore_src_alpaka_MiniDoublet_h
3 
5 
12 
13 #include "Hit.h"
14 
16  template <typename TAcc>
17  ALPAKA_FN_ACC ALPAKA_FN_INLINE void addMDToMemory(TAcc const& acc,
18  MiniDoublets mds,
21  unsigned int lowerHitIdx,
22  unsigned int upperHitIdx,
23  uint16_t lowerModuleIdx,
24  float dz,
25  float dPhi,
26  float dPhiChange,
27  float shiftedX,
28  float shiftedY,
29  float shiftedZ,
30  float noShiftedDphi,
31  float noShiftedDPhiChange,
32  unsigned int idx) {
33  //the index into which this MD needs to be written will be computed in the kernel
34  //nMDs variable will be incremented in the kernel, no need to worry about that here
35 
36  mds.moduleIndices()[idx] = lowerModuleIdx;
37  unsigned int anchorHitIndex, outerHitIndex;
38  if (modules.moduleType()[lowerModuleIdx] == PS and modules.moduleLayerType()[lowerModuleIdx] == Strip) {
39  mds.anchorHitIndices()[idx] = upperHitIdx;
40  mds.outerHitIndices()[idx] = lowerHitIdx;
41 
42  anchorHitIndex = upperHitIdx;
43  outerHitIndex = lowerHitIdx;
44  } else {
45  mds.anchorHitIndices()[idx] = lowerHitIdx;
46  mds.outerHitIndices()[idx] = upperHitIdx;
47 
48  anchorHitIndex = lowerHitIdx;
49  outerHitIndex = upperHitIdx;
50  }
51 
52  mds.dphichanges()[idx] = dPhiChange;
53 
54  mds.dphis()[idx] = dPhi;
55  mds.dzs()[idx] = dz;
56  mds.shiftedXs()[idx] = shiftedX;
57  mds.shiftedYs()[idx] = shiftedY;
58  mds.shiftedZs()[idx] = shiftedZ;
59 
60  mds.noShiftedDphis()[idx] = noShiftedDphi;
61  mds.noShiftedDphiChanges()[idx] = noShiftedDPhiChange;
62 
63  mds.anchorX()[idx] = hits.xs()[anchorHitIndex];
64  mds.anchorY()[idx] = hits.ys()[anchorHitIndex];
65  mds.anchorZ()[idx] = hits.zs()[anchorHitIndex];
66  mds.anchorRt()[idx] = hits.rts()[anchorHitIndex];
67  mds.anchorPhi()[idx] = hits.phis()[anchorHitIndex];
68  mds.anchorEta()[idx] = hits.etas()[anchorHitIndex];
69  mds.anchorHighEdgeX()[idx] = hits.highEdgeXs()[anchorHitIndex];
70  mds.anchorHighEdgeY()[idx] = hits.highEdgeYs()[anchorHitIndex];
71  mds.anchorLowEdgeX()[idx] = hits.lowEdgeXs()[anchorHitIndex];
72  mds.anchorLowEdgeY()[idx] = hits.lowEdgeYs()[anchorHitIndex];
73  mds.anchorHighEdgePhi()[idx] = alpaka::math::atan2(acc, mds.anchorHighEdgeY()[idx], mds.anchorHighEdgeX()[idx]);
74  mds.anchorLowEdgePhi()[idx] = alpaka::math::atan2(acc, mds.anchorLowEdgeY()[idx], mds.anchorLowEdgeX()[idx]);
75 
76  mds.outerX()[idx] = hits.xs()[outerHitIndex];
77  mds.outerY()[idx] = hits.ys()[outerHitIndex];
78  mds.outerZ()[idx] = hits.zs()[outerHitIndex];
79  mds.outerRt()[idx] = hits.rts()[outerHitIndex];
80  mds.outerPhi()[idx] = hits.phis()[outerHitIndex];
81  mds.outerEta()[idx] = hits.etas()[outerHitIndex];
82  mds.outerHighEdgeX()[idx] = hits.highEdgeXs()[outerHitIndex];
83  mds.outerHighEdgeY()[idx] = hits.highEdgeYs()[outerHitIndex];
84  mds.outerLowEdgeX()[idx] = hits.lowEdgeXs()[outerHitIndex];
85  mds.outerLowEdgeY()[idx] = hits.lowEdgeYs()[outerHitIndex];
86  }
87 
88  ALPAKA_FN_ACC ALPAKA_FN_INLINE bool isTighterTiltedModules(ModulesConst modules, uint16_t moduleIndex) {
89  // The "tighter" tilted modules are the subset of tilted modules that have smaller spacing
90  // This is the same as what was previously considered as"isNormalTiltedModules"
91  // See Figure 9.1 of https://cds.cern.ch/record/2272264/files/CMS-TDR-014.pdf
92  short subdet = modules.subdets()[moduleIndex];
93  short layer = modules.layers()[moduleIndex];
94  short side = modules.sides()[moduleIndex];
95  short rod = modules.rods()[moduleIndex];
96 
97  if (subdet == Barrel) {
98  if ((side != Center and layer == 3) or (side == NegZ and layer == 2 and rod > 5) or
99  (side == PosZ and layer == 2 and rod < 8) or (side == NegZ and layer == 1 and rod > 9) or
100  (side == PosZ and layer == 1 and rod < 4))
101  return true;
102  else
103  return false;
104  } else
105  return false;
106  }
107 
108  ALPAKA_FN_ACC ALPAKA_FN_INLINE float moduleGapSize(ModulesConst modules, uint16_t moduleIndex) {
109  float miniDeltaTilted[3] = {0.26f, 0.26f, 0.26f};
110  float miniDeltaFlat[6] = {0.26f, 0.16f, 0.16f, 0.18f, 0.18f, 0.18f};
111  float miniDeltaLooseTilted[3] = {0.4f, 0.4f, 0.4f};
112  float miniDeltaEndcap[5][15];
113 
114  for (size_t i = 0; i < 5; i++) {
115  for (size_t j = 0; j < 15; j++) {
116  if (i == 0 || i == 1) {
117  if (j < 10) {
118  miniDeltaEndcap[i][j] = 0.4f;
119  } else {
120  miniDeltaEndcap[i][j] = 0.18f;
121  }
122  } else if (i == 2 || i == 3) {
123  if (j < 8) {
124  miniDeltaEndcap[i][j] = 0.4f;
125  } else {
126  miniDeltaEndcap[i][j] = 0.18f;
127  }
128  } else {
129  if (j < 9) {
130  miniDeltaEndcap[i][j] = 0.4f;
131  } else {
132  miniDeltaEndcap[i][j] = 0.18f;
133  }
134  }
135  }
136  }
137 
138  unsigned int iL = modules.layers()[moduleIndex] - 1;
139  unsigned int iR = modules.rings()[moduleIndex] - 1;
140  short subdet = modules.subdets()[moduleIndex];
141  short side = modules.sides()[moduleIndex];
142 
143  float moduleSeparation = 0;
144 
145  if (subdet == Barrel and side == Center) {
146  moduleSeparation = miniDeltaFlat[iL];
147  } else if (isTighterTiltedModules(modules, moduleIndex)) {
148  moduleSeparation = miniDeltaTilted[iL];
149  } else if (subdet == Endcap) {
150  moduleSeparation = miniDeltaEndcap[iL][iR];
151  } else //Loose tilted modules
152  {
153  moduleSeparation = miniDeltaLooseTilted[iL];
154  }
155 
156  return moduleSeparation;
157  }
158 
159  template <typename TAcc>
160  ALPAKA_FN_ACC ALPAKA_FN_INLINE float dPhiThreshold(
161  TAcc const& acc, float rt, ModulesConst modules, uint16_t moduleIndex, float dPhi = 0, float dz = 0) {
162  // =================================================================
163  // Various constants
164  // =================================================================
165  //mean of the horizontal layer position in y; treat this as R below
166 
167  // =================================================================
168  // Computing some components that make up the cut threshold
169  // =================================================================
170 
171  unsigned int iL = modules.layers()[moduleIndex] - 1;
172  const float miniSlope = alpaka::math::asin(acc, alpaka::math::min(acc, rt * k2Rinv1GeVf / ptCut, kSinAlphaMax));
173  const float rLayNominal =
174  ((modules.subdets()[moduleIndex] == Barrel) ? kMiniRminMeanBarrel[iL] : kMiniRminMeanEndcap[iL]);
175  const float miniPVoff = 0.1f / rLayNominal;
176  const float miniMuls = ((modules.subdets()[moduleIndex] == Barrel) ? kMiniMulsPtScaleBarrel[iL] * 3.f / ptCut
177  : kMiniMulsPtScaleEndcap[iL] * 3.f / ptCut);
178  const bool isTilted = modules.subdets()[moduleIndex] == Barrel and modules.sides()[moduleIndex] != Center;
179  //the lower module is sent in irrespective of its layer type. We need to fetch the drdz properly
180 
181  float drdz;
182  if (isTilted) {
183  if (modules.moduleType()[moduleIndex] == PS and modules.moduleLayerType()[moduleIndex] == Strip) {
184  drdz = modules.drdzs()[moduleIndex];
185  } else {
186  drdz = modules.drdzs()[modules.partnerModuleIndices()[moduleIndex]];
187  }
188  } else {
189  drdz = 0;
190  }
191  const float miniTilt2 = ((isTilted) ? (0.5f * 0.5f) * (kPixelPSZpitch * kPixelPSZpitch) * (drdz * drdz) /
192  (1.f + drdz * drdz) / moduleGapSize(modules, moduleIndex)
193  : 0);
194 
195  // Compute luminous region requirement for endcap
196  const float miniLum = alpaka::math::abs(acc, dPhi * kDeltaZLum / dz); // Balaji's new error
197 
198  // =================================================================
199  // Return the threshold value
200  // =================================================================
201  // Following condition is met if the module is central and flatly lying
202  if (modules.subdets()[moduleIndex] == Barrel and modules.sides()[moduleIndex] == Center) {
203  return miniSlope + alpaka::math::sqrt(acc, miniMuls * miniMuls + miniPVoff * miniPVoff);
204  }
205  // Following condition is met if the module is central and tilted
206  else if (modules.subdets()[moduleIndex] == Barrel and
207  modules.sides()[moduleIndex] != Center) //all types of tilted modules
208  {
209  return miniSlope +
210  alpaka::math::sqrt(acc, miniMuls * miniMuls + miniPVoff * miniPVoff + miniTilt2 * miniSlope * miniSlope);
211  }
212  // If not barrel, it is Endcap
213  else {
214  return miniSlope + alpaka::math::sqrt(acc, miniMuls * miniMuls + miniPVoff * miniPVoff + miniLum * miniLum);
215  }
216  }
217 
218  template <typename TAcc>
219  ALPAKA_FN_INLINE ALPAKA_FN_ACC void shiftStripHits(TAcc const& acc,
221  uint16_t lowerModuleIndex,
222  uint16_t upperModuleIndex,
223  unsigned int lowerHitIndex,
224  unsigned int upperHitIndex,
225  float* shiftedCoords,
226  float xLower,
227  float yLower,
228  float zLower,
229  float rtLower,
230  float xUpper,
231  float yUpper,
232  float zUpper,
233  float rtUpper) {
234  // This is the strip shift scheme that is explained in http://uaf-10.t2.ucsd.edu/~phchang/talks/PhilipChang20190607_SDL_Update.pdf (see backup slides)
235  // The main feature of this shifting is that the strip hits are shifted to be "aligned" in the line of sight from interaction point to the the pixel hit.
236  // (since pixel hit is well defined in 3-d)
237  // The strip hit is shifted along the strip detector to be placed in a guessed position where we think they would have actually crossed
238  // The size of the radial direction shift due to module separation gap is computed in "radial" size, while the shift is done along the actual strip orientation
239  // This means that there may be very very subtle edge effects coming from whether the strip hit is center of the module or the at the edge of the module
240  // But this should be relatively minor effect
241 
242  // dependent variables for this if statement
243  // lowerModule
244  // lowerHit
245  // upperHit
246  // endcapGeometry
247  // tiltedGeometry
248 
249  // Some variables relevant to the function
250  float xp; // pixel x (pixel hit x)
251  float yp; // pixel y (pixel hit y)
252  float zp; // pixel y (pixel hit y)
253  float rtp; // pixel y (pixel hit y)
254  float xa; // "anchor" x (the anchor position on the strip module plane from pixel hit)
255  float ya; // "anchor" y (the anchor position on the strip module plane from pixel hit)
256  float xo; // old x (before the strip hit is moved up or down)
257  float yo; // old y (before the strip hit is moved up or down)
258  float xn; // new x (after the strip hit is moved up or down)
259  float yn; // new y (after the strip hit is moved up or down)
260  float abszn; // new z in absolute value
261  float zn; // new z with the sign (+/-) accounted
262  float angleA; // in r-z plane the theta of the pixel hit in polar coordinate is the angleA
263  float angleB; // this is the angle of tilted module in r-z plane ("drdz"), for endcap this is 90 degrees
264  bool isEndcap; // If endcap, drdz = infinity
265  float moduleSeparation;
266  float drprime; // The radial shift size in x-y plane projection
267  float drprime_x; // x-component of drprime
268  float drprime_y; // y-component of drprime
269  const float& slope =
270  modules.dxdys()[lowerModuleIndex]; // The slope of the possible strip hits for a given module in x-y plane
271  float absArctanSlope;
272  float angleM; // the angle M is the angle of rotation of the module in x-y plane if the possible strip hits are along the x-axis, then angleM = 0, and if the possible strip hits are along y-axis angleM = 90 degrees
273  float absdzprime; // The distance between the two points after shifting
274  const float& drdz_ = modules.drdzs()[lowerModuleIndex];
275  // Assign hit pointers based on their hit type
276  if (modules.moduleType()[lowerModuleIndex] == PS) {
277  // TODO: This is somewhat of an mystery.... somewhat confused why this is the case
278  if (modules.subdets()[lowerModuleIndex] == Barrel ? modules.moduleLayerType()[lowerModuleIndex] != Pixel
279  : modules.moduleLayerType()[lowerModuleIndex] == Pixel) {
280  xo = xUpper;
281  yo = yUpper;
282  xp = xLower;
283  yp = yLower;
284  zp = zLower;
285  rtp = rtLower;
286  } else {
287  xo = xLower;
288  yo = yLower;
289  xp = xUpper;
290  yp = yUpper;
291  zp = zUpper;
292  rtp = rtUpper;
293  }
294  } else {
295  xo = xUpper;
296  yo = yUpper;
297  xp = xLower;
298  yp = yLower;
299  zp = zLower;
300  rtp = rtLower;
301  }
302 
303  // If it is endcap some of the math gets simplified (and also computers don't like infinities)
304  isEndcap = modules.subdets()[lowerModuleIndex] == Endcap;
305 
306  // NOTE: TODO: Keep in mind that the sin(atan) function can be simplified to something like x / sqrt(1 + x^2) and similar for cos
307  // I am not sure how slow sin, atan, cos, functions are in c++. If x / sqrt(1 + x^2) are faster change this later to reduce arithmetic computation time
308  angleA = alpaka::math::abs(acc, alpaka::math::atan(acc, rtp / zp));
309  angleB =
310  ((isEndcap)
311  ? kPi / 2.f
312  : alpaka::math::atan(
313  acc,
314  drdz_)); // The tilt module on the positive z-axis has negative drdz slope in r-z plane and vice versa
315 
316  moduleSeparation = moduleGapSize(modules, lowerModuleIndex);
317 
318  // Sign flips if the pixel is later layer
319  if (modules.moduleType()[lowerModuleIndex] == PS and modules.moduleLayerType()[lowerModuleIndex] != Pixel) {
320  moduleSeparation *= -1;
321  }
322 
323  drprime = (moduleSeparation / alpaka::math::sin(acc, angleA + angleB)) * alpaka::math::sin(acc, angleA);
324 
325  // Compute arctan of the slope and take care of the slope = infinity case
326  absArctanSlope = ((slope != kVerticalModuleSlope) ? fabs(alpaka::math::atan(acc, slope)) : kPi / 2.f);
327 
328  // Depending on which quadrant the pixel hit lies, we define the angleM by shifting them slightly differently
329  if (xp > 0 and yp > 0) {
330  angleM = absArctanSlope;
331  } else if (xp > 0 and yp < 0) {
332  angleM = kPi - absArctanSlope;
333  } else if (xp < 0 and yp < 0) {
334  angleM = kPi + absArctanSlope;
335  } else // if (xp < 0 and yp > 0)
336  {
337  angleM = 2.f * kPi - absArctanSlope;
338  }
339 
340  // Then since the angleM sign is taken care of properly
341  drprime_x = drprime * alpaka::math::sin(acc, angleM);
342  drprime_y = drprime * alpaka::math::cos(acc, angleM);
343 
344  // The new anchor position is
345  xa = xp + drprime_x;
346  ya = yp + drprime_y;
347 
348  // Compute the new strip hit position (if the slope value is in special condition take care of the exceptions)
349  if (slope ==
350  kVerticalModuleSlope) // Designated for tilted module when the slope is infinity (module lying along y-axis)
351  {
352  xn = xa; // New x point is simply where the anchor is
353  yn = yo; // No shift in y
354  } else if (slope == 0) {
355  xn = xo; // New x point is simply where the anchor is
356  yn = ya; // No shift in y
357  } else {
358  xn = (slope * xa + (1.f / slope) * xo - ya + yo) / (slope + (1.f / slope)); // new xn
359  yn = (xn - xa) * slope + ya; // new yn
360  }
361 
362  // Computing new Z position
363  absdzprime = alpaka::math::abs(
364  acc,
365  moduleSeparation / alpaka::math::sin(acc, angleA + angleB) *
367  acc,
368  angleA)); // module separation sign is for shifting in radial direction for z-axis direction take care of the sign later
369 
370  // Depending on which one as closer to the interactin point compute the new z wrt to the pixel properly
371  if (modules.moduleLayerType()[lowerModuleIndex] == Pixel) {
372  abszn = alpaka::math::abs(acc, zp) + absdzprime;
373  } else {
374  abszn = alpaka::math::abs(acc, zp) - absdzprime;
375  }
376 
377  zn = abszn * ((zp > 0) ? 1 : -1); // Apply the sign of the zn
378 
379  shiftedCoords[0] = xn;
380  shiftedCoords[1] = yn;
381  shiftedCoords[2] = zn;
382  }
383 
384  template <typename TAcc>
385  ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgoBarrel(TAcc const& acc,
387  uint16_t lowerModuleIndex,
388  uint16_t upperModuleIndex,
389  unsigned int lowerHitIndex,
390  unsigned int upperHitIndex,
391  float& dz,
392  float& dPhi,
393  float& dPhiChange,
394  float& shiftedX,
395  float& shiftedY,
396  float& shiftedZ,
397  float& noShiftedDphi,
398  float& noShiftedDphiChange,
399  float xLower,
400  float yLower,
401  float zLower,
402  float rtLower,
403  float xUpper,
404  float yUpper,
405  float zUpper,
406  float rtUpper) {
407  dz = zLower - zUpper;
408  const float dzCut = modules.moduleType()[lowerModuleIndex] == PS ? 2.f : 10.f;
409  const float sign = ((dz > 0) - (dz < 0)) * ((zLower > 0) - (zLower < 0));
410  const float invertedcrossercut = (alpaka::math::abs(acc, dz) > 2) * sign;
411 
412  if ((alpaka::math::abs(acc, dz) >= dzCut) || (invertedcrossercut > 0))
413  return false;
414 
415  float miniCut = 0;
416 
417  miniCut = modules.moduleLayerType()[lowerModuleIndex] == Pixel
418  ? dPhiThreshold(acc, rtLower, modules, lowerModuleIndex)
419  : dPhiThreshold(acc, rtUpper, modules, lowerModuleIndex);
420 
421  // Cut #2: dphi difference
422  // Ref to original code: https://github.com/slava77/cms-tkph2-ntuple/blob/184d2325147e6930030d3d1f780136bc2dd29ce6/doubletAnalysis.C#L3085
423  float xn = 0.f, yn = 0.f; // , zn = 0;
424  float shiftedRt2;
425  if (modules.sides()[lowerModuleIndex] != Center) // If barrel and not center it is tilted
426  {
427  // Shift the hits and calculate new xn, yn position
428  float shiftedCoords[3];
429  shiftStripHits(acc,
430  modules,
431  lowerModuleIndex,
432  upperModuleIndex,
433  lowerHitIndex,
434  upperHitIndex,
435  shiftedCoords,
436  xLower,
437  yLower,
438  zLower,
439  rtLower,
440  xUpper,
441  yUpper,
442  zUpper,
443  rtUpper);
444  xn = shiftedCoords[0];
445  yn = shiftedCoords[1];
446 
447  // Lower or the upper hit needs to be modified depending on which one was actually shifted
448  if (modules.moduleLayerType()[lowerModuleIndex] == Pixel) {
449  shiftedX = xn;
450  shiftedY = yn;
451  shiftedZ = zUpper;
452  shiftedRt2 = xn * xn + yn * yn;
453 
454  dPhi = deltaPhi(acc, xLower, yLower, shiftedX, shiftedY); //function from Hit.cc
455  noShiftedDphi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
456  } else {
457  shiftedX = xn;
458  shiftedY = yn;
459  shiftedZ = zLower;
460  shiftedRt2 = xn * xn + yn * yn;
461  dPhi = deltaPhi(acc, shiftedX, shiftedY, xUpper, yUpper);
462  noShiftedDphi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
463  }
464  } else {
465  shiftedX = 0;
466  shiftedY = 0;
467  shiftedZ = 0;
468  dPhi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
469  noShiftedDphi = dPhi;
470  }
471 
472  if (alpaka::math::abs(acc, dPhi) >= miniCut)
473  return false;
474 
475  // Cut #3: The dphi change going from lower Hit to upper Hit
476  // Ref to original code: https://github.com/slava77/cms-tkph2-ntuple/blob/184d2325147e6930030d3d1f780136bc2dd29ce6/doubletAnalysis.C#L3076
477  if (modules.sides()[lowerModuleIndex] != Center) {
478  // When it is tilted, use the new shifted positions
479  // TODO: This is somewhat of an mystery.... somewhat confused why this is the case
480  if (modules.moduleLayerType()[lowerModuleIndex] != Pixel) {
481  // dPhi Change should be calculated so that the upper hit has higher rt.
482  // In principle, this kind of check rt_lower < rt_upper should not be necessary because the hit shifting should have taken care of this.
483  // (i.e. the strip hit is shifted to be aligned in the line of sight from interaction point to pixel hit of PS module guaranteeing rt ordering)
484  // But I still placed this check for safety. (TODO: After checking explicitly if not needed remove later?)
485  // setdeltaPhiChange(lowerHit.rt() < upperHitMod.rt() ? lowerHit.deltaPhiChange(upperHitMod) : upperHitMod.deltaPhiChange(lowerHit));
486 
487  dPhiChange = (rtLower * rtLower < shiftedRt2) ? deltaPhiChange(acc, xLower, yLower, shiftedX, shiftedY)
488  : deltaPhiChange(acc, shiftedX, shiftedY, xLower, yLower);
489  noShiftedDphiChange = rtLower < rtUpper ? deltaPhiChange(acc, xLower, yLower, xUpper, yUpper)
490  : deltaPhiChange(acc, xUpper, yUpper, xLower, yLower);
491  } else {
492  // dPhi Change should be calculated so that the upper hit has higher rt.
493  // In principle, this kind of check rt_lower < rt_upper should not be necessary because the hit shifting should have taken care of this.
494  // (i.e. the strip hit is shifted to be aligned in the line of sight from interaction point to pixel hit of PS module guaranteeing rt ordering)
495  // But I still placed this check for safety. (TODO: After checking explicitly if not needed remove later?)
496 
497  dPhiChange = (shiftedRt2 < rtUpper * rtUpper) ? deltaPhiChange(acc, shiftedX, shiftedY, xUpper, yUpper)
498  : deltaPhiChange(acc, xUpper, yUpper, shiftedX, shiftedY);
499  noShiftedDphiChange = rtLower < rtUpper ? deltaPhiChange(acc, xLower, yLower, xUpper, yUpper)
500  : deltaPhiChange(acc, xUpper, yUpper, xLower, yLower);
501  }
502  } else {
503  // When it is flat lying module, whichever is the lowerSide will always have rt lower
504  dPhiChange = deltaPhiChange(acc, xLower, yLower, xUpper, yUpper);
505  noShiftedDphiChange = dPhiChange;
506  }
507 
508  return alpaka::math::abs(acc, dPhiChange) < miniCut;
509  }
510 
511  template <typename TAcc>
512  ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgoEndcap(TAcc const& acc,
514  uint16_t lowerModuleIndex,
515  uint16_t upperModuleIndex,
516  unsigned int lowerHitIndex,
517  unsigned int upperHitIndex,
518  float& drt,
519  float& dPhi,
520  float& dPhiChange,
521  float& shiftedX,
522  float& shiftedY,
523  float& shiftedZ,
524  float& noShiftedDphi,
525  float& noShiftedDphichange,
526  float xLower,
527  float yLower,
528  float zLower,
529  float rtLower,
530  float xUpper,
531  float yUpper,
532  float zUpper,
533  float rtUpper) {
534  // There are series of cuts that applies to mini-doublet in a "endcap" region
535  // Cut #1 : dz cut. The dz difference can't be larger than 1cm. (max separation is 4mm for modules in the endcap)
536  // Ref to original code: https://github.com/slava77/cms-tkph2-ntuple/blob/184d2325147e6930030d3d1f780136bc2dd29ce6/doubletAnalysis.C#L3093
537  // For PS module in case when it is tilted a different dz (after the strip hit shift) is calculated later.
538 
539  float dz = zLower - zUpper; // Not const since later it might change depending on the type of module
540 
541  const float dzCut = 1.f;
542 
543  if (alpaka::math::abs(acc, dz) >= dzCut)
544  return false;
545  // Cut #2 : drt cut. The dz difference can't be larger than 1cm. (max separation is 4mm for modules in the endcap)
546  // Ref to original code: https://github.com/slava77/cms-tkph2-ntuple/blob/184d2325147e6930030d3d1f780136bc2dd29ce6/doubletAnalysis.C#L3100
547  const float drtCut = modules.moduleType()[lowerModuleIndex] == PS ? 2.f : 10.f;
548  drt = rtLower - rtUpper;
549  if (alpaka::math::abs(acc, drt) >= drtCut)
550  return false;
551  // The new scheme shifts strip hits to be "aligned" along the line of sight from interaction point to the pixel hit (if it is PS modules)
552  float xn = 0, yn = 0, zn = 0;
553 
554  float shiftedCoords[3];
555  shiftStripHits(acc,
556  modules,
557  lowerModuleIndex,
558  upperModuleIndex,
559  lowerHitIndex,
560  upperHitIndex,
561  shiftedCoords,
562  xLower,
563  yLower,
564  zLower,
565  rtLower,
566  xUpper,
567  yUpper,
568  zUpper,
569  rtUpper);
570 
571  xn = shiftedCoords[0];
572  yn = shiftedCoords[1];
573  zn = shiftedCoords[2];
574 
575  if (modules.moduleType()[lowerModuleIndex] == PS) {
576  // Appropriate lower or upper hit is modified after checking which one was actually shifted
577  if (modules.moduleLayerType()[lowerModuleIndex] == Pixel) {
578  shiftedX = xn;
579  shiftedY = yn;
580  shiftedZ = zUpper;
581  dPhi = deltaPhi(acc, xLower, yLower, shiftedX, shiftedY);
582  noShiftedDphi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
583  } else {
584  shiftedX = xn;
585  shiftedY = yn;
586  shiftedZ = zLower;
587  dPhi = deltaPhi(acc, shiftedX, shiftedY, xUpper, yUpper);
588  noShiftedDphi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
589  }
590  } else {
591  shiftedX = xn;
592  shiftedY = yn;
593  shiftedZ = zUpper;
594  dPhi = deltaPhi(acc, xLower, yLower, xn, yn);
595  noShiftedDphi = deltaPhi(acc, xLower, yLower, xUpper, yUpper);
596  }
597 
598  // dz needs to change if it is a PS module where the strip hits are shifted in order to properly account for the case when a tilted module falls under "endcap logic"
599  // if it was an endcap it will have zero effect
600  if (modules.moduleType()[lowerModuleIndex] == PS) {
601  dz = modules.moduleLayerType()[lowerModuleIndex] == Pixel ? zLower - zn : zUpper - zn;
602  }
603 
604  float miniCut = 0;
605  miniCut = modules.moduleLayerType()[lowerModuleIndex] == Pixel
606  ? dPhiThreshold(acc, rtLower, modules, lowerModuleIndex, dPhi, dz)
607  : dPhiThreshold(acc, rtUpper, modules, lowerModuleIndex, dPhi, dz);
608 
609  if (alpaka::math::abs(acc, dPhi) >= miniCut)
610  return false;
611 
612  // Cut #4: Another cut on the dphi after some modification
613  // Ref to original code: https://github.com/slava77/cms-tkph2-ntuple/blob/184d2325147e6930030d3d1f780136bc2dd29ce6/doubletAnalysis.C#L3119-L3124
614 
615  float dzFrac = alpaka::math::abs(acc, dz) / alpaka::math::abs(acc, zLower);
616  dPhiChange = dPhi / dzFrac * (1.f + dzFrac);
617  noShiftedDphichange = noShiftedDphi / dzFrac * (1.f + dzFrac);
618 
619  return alpaka::math::abs(acc, dPhiChange) < miniCut;
620  }
621 
622  template <typename TAcc>
623  ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgo(TAcc const& acc,
625  uint16_t lowerModuleIndex,
626  uint16_t upperModuleIndex,
627  unsigned int lowerHitIndex,
628  unsigned int upperHitIndex,
629  float& dz,
630  float& dPhi,
631  float& dPhiChange,
632  float& shiftedX,
633  float& shiftedY,
634  float& shiftedZ,
635  float& noShiftedDphi,
636  float& noShiftedDphiChange,
637  float xLower,
638  float yLower,
639  float zLower,
640  float rtLower,
641  float xUpper,
642  float yUpper,
643  float zUpper,
644  float rtUpper) {
645  if (modules.subdets()[lowerModuleIndex] == Barrel) {
647  modules,
648  lowerModuleIndex,
649  upperModuleIndex,
650  lowerHitIndex,
651  upperHitIndex,
652  dz,
653  dPhi,
654  dPhiChange,
655  shiftedX,
656  shiftedY,
657  shiftedZ,
658  noShiftedDphi,
659  noShiftedDphiChange,
660  xLower,
661  yLower,
662  zLower,
663  rtLower,
664  xUpper,
665  yUpper,
666  zUpper,
667  rtUpper);
668  } else {
670  modules,
671  lowerModuleIndex,
672  upperModuleIndex,
673  lowerHitIndex,
674  upperHitIndex,
675  dz,
676  dPhi,
677  dPhiChange,
678  shiftedX,
679  shiftedY,
680  shiftedZ,
681  noShiftedDphi,
682  noShiftedDphiChange,
683  xLower,
684  yLower,
685  zLower,
686  rtLower,
687  xUpper,
688  yUpper,
689  zUpper,
690  rtUpper);
691  }
692  }
693 
695  template <typename TAcc>
696  ALPAKA_FN_ACC void operator()(TAcc const& acc,
698  HitsConst hits,
699  HitsRangesConst hitsRanges,
700  MiniDoublets mds,
701  MiniDoubletsOccupancy mdsOccupancy,
702  ObjectRangesConst ranges) const {
703  auto const globalThreadIdx = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc);
704  auto const gridThreadExtent = alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc);
705 
706  for (uint16_t lowerModuleIndex = globalThreadIdx[1]; lowerModuleIndex < modules.nLowerModules();
707  lowerModuleIndex += gridThreadExtent[1]) {
708  uint16_t upperModuleIndex = modules.partnerModuleIndices()[lowerModuleIndex];
709  int nLowerHits = hitsRanges.hitRangesnLower()[lowerModuleIndex];
710  int nUpperHits = hitsRanges.hitRangesnUpper()[lowerModuleIndex];
711  if (hitsRanges.hitRangesLower()[lowerModuleIndex] == -1)
712  continue;
713  unsigned int upHitArrayIndex = hitsRanges.hitRangesUpper()[lowerModuleIndex];
714  unsigned int loHitArrayIndex = hitsRanges.hitRangesLower()[lowerModuleIndex];
715  int limit = nUpperHits * nLowerHits;
716 
717  for (int hitIndex = globalThreadIdx[2]; hitIndex < limit; hitIndex += gridThreadExtent[2]) {
718  int lowerHitIndex = hitIndex / nUpperHits;
719  int upperHitIndex = hitIndex % nUpperHits;
720  if (upperHitIndex >= nUpperHits)
721  continue;
722  if (lowerHitIndex >= nLowerHits)
723  continue;
724  unsigned int lowerHitArrayIndex = loHitArrayIndex + lowerHitIndex;
725  float xLower = hits.xs()[lowerHitArrayIndex];
726  float yLower = hits.ys()[lowerHitArrayIndex];
727  float zLower = hits.zs()[lowerHitArrayIndex];
728  float rtLower = hits.rts()[lowerHitArrayIndex];
729  unsigned int upperHitArrayIndex = upHitArrayIndex + upperHitIndex;
730  float xUpper = hits.xs()[upperHitArrayIndex];
731  float yUpper = hits.ys()[upperHitArrayIndex];
732  float zUpper = hits.zs()[upperHitArrayIndex];
733  float rtUpper = hits.rts()[upperHitArrayIndex];
734 
735  float dz, dphi, dphichange, shiftedX, shiftedY, shiftedZ, noShiftedDphi, noShiftedDphiChange;
737  modules,
738  lowerModuleIndex,
739  upperModuleIndex,
740  lowerHitArrayIndex,
741  upperHitArrayIndex,
742  dz,
743  dphi,
744  dphichange,
745  shiftedX,
746  shiftedY,
747  shiftedZ,
748  noShiftedDphi,
749  noShiftedDphiChange,
750  xLower,
751  yLower,
752  zLower,
753  rtLower,
754  xUpper,
755  yUpper,
756  zUpper,
757  rtUpper);
758  if (success) {
759  int totOccupancyMDs = alpaka::atomicAdd(
760  acc, &mdsOccupancy.totOccupancyMDs()[lowerModuleIndex], 1u, alpaka::hierarchy::Threads{});
761  if (totOccupancyMDs >= (ranges.miniDoubletModuleOccupancy()[lowerModuleIndex])) {
762 #ifdef WARNINGS
763  printf("Mini-doublet excess alert! Module index = %d\n", lowerModuleIndex);
764 #endif
765  } else {
766  int mdModuleIndex =
767  alpaka::atomicAdd(acc, &mdsOccupancy.nMDs()[lowerModuleIndex], 1u, alpaka::hierarchy::Threads{});
768  unsigned int mdIndex = ranges.miniDoubletModuleIndices()[lowerModuleIndex] + mdModuleIndex;
769 
770  addMDToMemory(acc,
771  mds,
772  hits,
773  modules,
774  lowerHitArrayIndex,
775  upperHitArrayIndex,
776  lowerModuleIndex,
777  dz,
778  dphi,
779  dphichange,
780  shiftedX,
781  shiftedY,
782  shiftedZ,
783  noShiftedDphi,
784  noShiftedDphiChange,
785  mdIndex);
786  }
787  }
788  }
789  }
790  }
791  };
792 
794  template <typename TAcc>
795  ALPAKA_FN_ACC void operator()(TAcc const& acc, ModulesConst modules, ObjectRanges ranges) const {
796  // implementation is 1D with a single block
797  static_assert(std::is_same_v<TAcc, ALPAKA_ACCELERATOR_NAMESPACE::Acc1D>, "Should be Acc1D");
798  ALPAKA_ASSERT_ACC((alpaka::getWorkDiv<alpaka::Grid, alpaka::Blocks>(acc)[0] == 1));
799 
800  auto const globalThreadIdx = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc);
801  auto const gridThreadExtent = alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc);
802 
803  // Declare variables in shared memory and set to 0
804  int& nTotalMDs = alpaka::declareSharedVar<int, __COUNTER__>(acc);
806  nTotalMDs = 0;
807  }
808  alpaka::syncBlockThreads(acc);
809 
810  for (uint16_t i = globalThreadIdx[0]; i < modules.nLowerModules(); i += gridThreadExtent[0]) {
811  short module_rings = modules.rings()[i];
812  short module_layers = modules.layers()[i];
813  short module_subdets = modules.subdets()[i];
814  float module_eta = alpaka::math::abs(acc, modules.eta()[i]);
815 
816  int category_number;
817  if (module_layers <= 3 && module_subdets == 5)
818  category_number = 0;
819  else if (module_layers >= 4 && module_subdets == 5)
820  category_number = 1;
821  else if (module_layers <= 2 && module_subdets == 4 && module_rings >= 11)
822  category_number = 2;
823  else if (module_layers >= 3 && module_subdets == 4 && module_rings >= 8)
824  category_number = 2;
825  else if (module_layers <= 2 && module_subdets == 4 && module_rings <= 10)
826  category_number = 3;
827  else if (module_layers >= 3 && module_subdets == 4 && module_rings <= 7)
828  category_number = 3;
829  else
830  category_number = -1;
831 
832  int eta_number;
833  if (module_eta < 0.75f)
834  eta_number = 0;
835  else if (module_eta < 1.5f)
836  eta_number = 1;
837  else if (module_eta < 2.25f)
838  eta_number = 2;
839  else if (module_eta < 3.0f)
840  eta_number = 3;
841  else
842  eta_number = -1;
843 
844  int occupancy;
845  if (category_number == 0 && eta_number == 0)
846  occupancy = 49;
847  else if (category_number == 0 && eta_number == 1)
848  occupancy = 42;
849  else if (category_number == 0 && eta_number == 2)
850  occupancy = 37;
851  else if (category_number == 0 && eta_number == 3)
852  occupancy = 41;
853  else if (category_number == 1)
854  occupancy = 100;
855  else if (category_number == 2 && eta_number == 1)
856  occupancy = 16;
857  else if (category_number == 2 && eta_number == 2)
858  occupancy = 19;
859  else if (category_number == 3 && eta_number == 1)
860  occupancy = 14;
861  else if (category_number == 3 && eta_number == 2)
862  occupancy = 20;
863  else if (category_number == 3 && eta_number == 3)
864  occupancy = 25;
865  else {
866  occupancy = 0;
867 #ifdef WARNINGS
868  printf("Unhandled case in createMDArrayRangesGPU! Module index = %i\n", i);
869 #endif
870  }
871 
872  unsigned int nTotMDs = alpaka::atomicAdd(acc, &nTotalMDs, occupancy, alpaka::hierarchy::Threads{});
873 
874  ranges.miniDoubletModuleIndices()[i] = nTotMDs;
875  ranges.miniDoubletModuleOccupancy()[i] = occupancy;
876  }
877 
878  // Wait for all threads to finish before reporting final values
879  alpaka::syncBlockThreads(acc);
881  ranges.miniDoubletModuleIndices()[modules.nLowerModules()] = nTotalMDs;
882  ranges.nTotalMDs() = nTotalMDs;
883  }
884  }
885  };
886 
888  template <typename TAcc>
889  ALPAKA_FN_ACC void operator()(TAcc const& acc,
891  MiniDoubletsOccupancy mdsOccupancy,
893  HitsRangesConst hitsRanges) const {
894  // implementation is 1D with a single block
895  static_assert(std::is_same_v<TAcc, ALPAKA_ACCELERATOR_NAMESPACE::Acc1D>, "Should be Acc1D");
896  ALPAKA_ASSERT_ACC((alpaka::getWorkDiv<alpaka::Grid, alpaka::Blocks>(acc)[0] == 1));
897 
898  auto const globalThreadIdx = alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc);
899  auto const gridThreadExtent = alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc);
900 
901  for (uint16_t i = globalThreadIdx[0]; i < modules.nLowerModules(); i += gridThreadExtent[0]) {
902  if (mdsOccupancy.nMDs()[i] == 0 or hitsRanges.hitRanges()[i][0] == -1) {
903  ranges.mdRanges()[i][0] = -1;
904  ranges.mdRanges()[i][1] = -1;
905  } else {
906  ranges.mdRanges()[i][0] = ranges.miniDoubletModuleIndices()[i];
907  ranges.mdRanges()[i][1] = ranges.miniDoubletModuleIndices()[i] + mdsOccupancy.nMDs()[i] - 1;
908  }
909  }
910  }
911  };
912 } // namespace ALPAKA_ACCELERATOR_NAMESPACE::lst
913 
914 #endif
MiniDoubletsSoA::View MiniDoublets
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kMiniRminMeanEndcap[5]
Definition: Common.h:47
ALPAKA_FN_ACC constexpr bool once_per_block(TAcc const &acc)
ALPAKA_FN_ACC void operator()(TAcc const &acc, ModulesConst modules, ObjectRanges ranges) const
Definition: MiniDoublet.h:795
ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgoBarrel(TAcc const &acc, ModulesConst modules, uint16_t lowerModuleIndex, uint16_t upperModuleIndex, unsigned int lowerHitIndex, unsigned int upperHitIndex, float &dz, float &dPhi, float &dPhiChange, float &shiftedX, float &shiftedY, float &shiftedZ, float &noShiftedDphi, float &noShiftedDphiChange, float xLower, float yLower, float zLower, float rtLower, float xUpper, float yUpper, float zUpper, float rtUpper)
Definition: MiniDoublet.h:385
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kMiniMulsPtScaleBarrel[6]
Definition: Common.h:42
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float k2Rinv1GeVf
Definition: Common.h:49
ObjectRangesSoA::View ObjectRanges
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kMiniMulsPtScaleEndcap[5]
Definition: Common.h:44
static const double slope[3]
const std::vector< int > & module_rings()
Definition: LSTEff.cc:3384
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
ALPAKA_FN_ACC void operator()(TAcc const &acc, ModulesConst modules, MiniDoubletsOccupancy mdsOccupancy, ObjectRanges ranges, HitsRangesConst hitsRanges) const
Definition: MiniDoublet.h:889
ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgoEndcap(TAcc const &acc, ModulesConst modules, uint16_t lowerModuleIndex, uint16_t upperModuleIndex, unsigned int lowerHitIndex, unsigned int upperHitIndex, float &drt, float &dPhi, float &dPhiChange, float &shiftedX, float &shiftedY, float &shiftedZ, float &noShiftedDphi, float &noShiftedDphichange, float xLower, float yLower, float zLower, float rtLower, float xUpper, float yUpper, float zUpper, float rtUpper)
Definition: MiniDoublet.h:512
ALPAKA_FN_ACC bool runMiniDoubletDefaultAlgo(TAcc const &acc, ModulesConst modules, uint16_t lowerModuleIndex, uint16_t upperModuleIndex, unsigned int lowerHitIndex, unsigned int upperHitIndex, float &dz, float &dPhi, float &dPhiChange, float &shiftedX, float &shiftedY, float &shiftedZ, float &noShiftedDphi, float &noShiftedDphiChange, float xLower, float yLower, float zLower, float rtLower, float xUpper, float yUpper, float zUpper, float rtUpper)
Definition: MiniDoublet.h:623
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kMiniRminMeanBarrel[6]
Definition: Common.h:45
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kVerticalModuleSlope
Definition: Common.h:61
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float ptCut
Definition: Common.h:52
ALPAKA_FN_ACC ALPAKA_FN_INLINE void addMDToMemory(TAcc const &acc, MiniDoublets mds, HitsConst hits, ModulesConst modules, unsigned int lowerHitIdx, unsigned int upperHitIdx, uint16_t lowerModuleIdx, float dz, float dPhi, float dPhiChange, float shiftedX, float shiftedY, float shiftedZ, float noShiftedDphi, float noShiftedDPhiChange, unsigned int idx)
Definition: MiniDoublet.h:17
ALPAKA_FN_ACC ALPAKA_FN_INLINE float moduleGapSize(ModulesConst modules, uint16_t moduleIndex)
Definition: MiniDoublet.h:108
T sqrt(T t)
Definition: SSEVec.h:23
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
HitsSoA::ConstView HitsConst
Definition: HitsSoA.h:33
ModulesSoA::ConstView ModulesConst
Definition: ModulesSoA.h:47
HitsRangesSoA::ConstView HitsRangesConst
Definition: HitsSoA.h:35
bool isEndcap(GeomDetEnumerators::SubDetector m)
ALPAKA_FN_INLINE ALPAKA_FN_ACC void shiftStripHits(TAcc const &acc, ModulesConst modules, uint16_t lowerModuleIndex, uint16_t upperModuleIndex, unsigned int lowerHitIndex, unsigned int upperHitIndex, float *shiftedCoords, float xLower, float yLower, float zLower, float rtLower, float xUpper, float yUpper, float zUpper, float rtUpper)
Definition: MiniDoublet.h:219
const std::vector< int > & module_layers()
Definition: LSTEff.cc:3388
string ranges
Definition: diffTwoXMLs.py:79
MiniDoubletsOccupancySoA::View MiniDoubletsOccupancy
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kPixelPSZpitch
Definition: Common.h:54
const std::vector< int > & module_subdets()
Definition: LSTEff.cc:3288
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kPi
Definition: Common.h:39
ALPAKA_FN_ACC ALPAKA_FN_INLINE bool isTighterTiltedModules(ModulesConst modules, uint16_t moduleIndex)
Definition: MiniDoublet.h:88
ObjectRangesSoA::ConstView ObjectRangesConst
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kSinAlphaMax
Definition: Common.h:51
ALPAKA_FN_ACC ALPAKA_FN_INLINE float dPhiThreshold(TAcc const &acc, float rt, ModulesConst modules, uint16_t moduleIndex, float dPhi=0, float dz=0)
Definition: MiniDoublet.h:160
ALPAKA_STATIC_ACC_MEM_GLOBAL constexpr float kDeltaZLum
Definition: Common.h:53
ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE float deltaPhi(TAcc const &acc, float x1, float y1, float x2, float y2)
Definition: Hit.h:34
T1 atomicAdd(T1 *a, T2 b)
Definition: cudaCompat.h:61
ALPAKA_FN_ACC void operator()(TAcc const &acc, ModulesConst modules, HitsConst hits, HitsRangesConst hitsRanges, MiniDoublets mds, MiniDoubletsOccupancy mdsOccupancy, ObjectRangesConst ranges) const
Definition: MiniDoublet.h:696
ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE float deltaPhiChange(TAcc const &acc, float x1, float y1, float x2, float y2)
Definition: Hit.h:41
MPlex< T, D1, D2, N > atan2(const MPlex< T, D1, D2, N > &y, const MPlex< T, D1, D2, N > &x)
Definition: Matriplex.h:648