Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TripletSearch.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TripletSearch.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020-2021 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
11 // Local include(s).
13 
14 #include "../Utilities/Arrays.hpp"
15 #include "SpacePointType.hpp"
16 
17 // VecMem include(s).
18 #include "vecmem/containers/data/jagged_vector_view.hpp"
19 #include "vecmem/containers/data/vector_view.hpp"
20 #include "vecmem/containers/device_vector.hpp"
21 #include "vecmem/containers/jagged_device_vector.hpp"
22 #include "vecmem/memory/atomic.hpp"
23 
24 // SYCL include(s).
25 #include <CL/sycl.hpp>
26 
27 // System include(s).
28 #include <cstdint>
29 
30 namespace Acts::Sycl::detail {
31 
34  public:
37  vecmem::data::vector_view<uint32_t> sumBotTopCombView,
38  const uint32_t numTripletSearchThreads, const uint32_t firstMiddle,
39  const uint32_t lastMiddle,
40  vecmem::data::jagged_vector_view<const uint32_t> midTopDupletView,
41  vecmem::data::vector_view<uint32_t> sumBotMidView,
42  vecmem::data::vector_view<uint32_t> sumTopMidView,
43  vecmem::data::vector_view<detail::DeviceLinEqCircle> linearBotView,
44  vecmem::data::vector_view<detail::DeviceLinEqCircle> linearTopView,
45  vecmem::data::vector_view<const detail::DeviceSpacePoint> middleSPsView,
46  vecmem::data::vector_view<uint32_t> indTopDupletview,
47  vecmem::data::vector_view<uint32_t> countTripletsView,
49  vecmem::data::vector_view<detail::DeviceTriplet> curvImpactView)
50  : m_sumBotTopCombView(sumBotTopCombView),
51  m_numTripletSearchThreads(numTripletSearchThreads),
52  m_firstMiddle(firstMiddle),
53  m_lastMiddle(lastMiddle),
54  m_midTopDupletView(midTopDupletView),
55  m_sumBotMidView(sumBotMidView),
56  m_sumTopMidView(sumTopMidView),
57  m_linearBotView(linearBotView),
58  m_linearTopView(linearTopView),
59  m_middleSPsView(middleSPsView),
60  m_indTopDupletView(indTopDupletview),
61  m_countTripletsView(countTripletsView),
62  m_config(config),
63  m_curvImpactView(curvImpactView) {}
64 
66  void operator()(cl::sycl::nd_item<1> item) const {
67  // Get the index
68  const uint32_t idx = item.get_global_linear_id();
69  if (idx < m_numTripletSearchThreads) {
70  // Retrieve the index of the corresponding middle
71  // space point by binary search
72  vecmem::device_vector<uint32_t> sumBotTopCombPrefix(m_sumBotTopCombView);
73  const auto sumCombUptoFirstMiddle = sumBotTopCombPrefix[m_firstMiddle];
74  auto L = m_firstMiddle;
75  auto R = m_lastMiddle;
76  auto mid = L;
77  while (L < R - 1) {
78  mid = (L + R) / 2;
79  // To be able to search in sumBotTopCombPrefix, we need
80  // to use an offset (sumCombUptoFirstMiddle).
81  if (idx + sumCombUptoFirstMiddle < sumBotTopCombPrefix[mid]) {
82  R = mid;
83  } else {
84  L = mid;
85  }
86  }
87  mid = L;
88  vecmem::jagged_device_vector<const uint32_t> midTopDuplets(
90  const auto numT = midTopDuplets.at(mid).size();
91  const auto threadIdxForMiddleSP =
92  (idx - sumBotTopCombPrefix[mid] + sumCombUptoFirstMiddle);
93  /*
94  NOTES ON THREAD MAPPING TO SPACE POINTS
95 
96  We need to map bottom and top SP indices to this
97  thread.
98 
99  So we are mapping one bottom and one top SP to this thread
100  (we already have a middle SP) which gives us a tiplet.
101 
102  This is done in the following way: We
103  calculated the number of possible triplet
104  combinations for this middle SP (let it be
105  num_comp_bot*num_comp_top). Let num_comp_bot = 2
106  and num_comp_top=3 in this example. So we have 2
107  compatible bottom and 3 compatible top SP for this
108  middle SP.
109 
110  That gives us 6 threads altogether:
111  ===========================================
112  thread: | 0 | 1 | 2 | 3 | 4 | 5 |
113  bottom id: | bot0 | bot0 | bot0 | bot1 | bot1 | bot1 |
114  top id: | top0 | top1 | top2 | top0 | top1 | top2 |
115  ===========================================
116 
117  If we divide 6 by the number of compatible top SP
118  for this middle SP, or deviceNumTopDuplets[mid]
119  which is 3 now, we get the id for the bottom SP.
120  Similarly, if we take modulo
121  deviceNumTopDuplets[mid], we get the id for the
122  top SP.
123 
124  So if threadIdxForMiddleSP = 3, then ib = 1 and it = 0.
125 
126  We can use these ids together with
127  sumBotMidPrefix[mid] and deviceSumTop[mid] to be able
128  to index our other arrays.
129 
130  These other arrays are deviceIndBot and deviceIndTop.
131 
132  So to retrieve the bottom SP index for this thread, we'd
133  have to index the deviceIndBot array at
134  sumBotMidPrefix[mid] + ib
135  which is the id for the bottom SP that we just calculated
136  (ib = 1 in the example).
137  */
138 
139  vecmem::device_vector<uint32_t> sumBotMidPrefix(m_sumBotMidView),
140  sumTopMidPrefix(m_sumTopMidView);
141  const auto ib = sumBotMidPrefix[mid] + (threadIdxForMiddleSP / numT);
142  const auto it = sumTopMidPrefix[mid] + (threadIdxForMiddleSP % numT);
143  vecmem::device_vector<detail::DeviceLinEqCircle> deviceLinBot(
145  deviceLinTop(m_linearTopView);
146  const auto linBotEq = deviceLinBot[ib];
147  const auto linTopEq = deviceLinTop[it];
148  const vecmem::device_vector<const detail::DeviceSpacePoint> middleSPs(
150  const auto midSP = middleSPs[mid];
151 
152  const auto Vb = linBotEq.v;
153  const auto Ub = linBotEq.u;
154  const auto Erb = linBotEq.er;
155  const auto cotThetab = linBotEq.cotTheta;
156  const auto iDeltaRb = linBotEq.iDeltaR;
157 
158  const auto Vt = linTopEq.v;
159  const auto Ut = linTopEq.u;
160  const auto Ert = linTopEq.er;
161  const auto cotThetat = linTopEq.cotTheta;
162  const auto iDeltaRt = linTopEq.iDeltaR;
163 
164  const auto rM = midSP.r;
165  const auto varianceRM = midSP.varR;
166  const auto varianceZM = midSP.varZ;
167 
168  auto iSinTheta2 = (1.f + cotThetab * cotThetab);
169  auto scatteringInRegion2 = m_config.maxScatteringAngle2 * iSinTheta2;
170  scatteringInRegion2 *=
172  auto error2 = Ert + Erb +
173  2.f * (cotThetab * cotThetat * varianceRM + varianceZM) *
174  iDeltaRb * iDeltaRt;
175  auto deltaCotTheta = cotThetab - cotThetat;
176  auto deltaCotTheta2 = deltaCotTheta * deltaCotTheta;
177 
178  deltaCotTheta = cl::sycl::abs(deltaCotTheta);
179  auto error = cl::sycl::sqrt(error2);
180  auto dCotThetaMinusError2 =
181  deltaCotTheta2 + error2 - 2.f * deltaCotTheta * error;
182  auto dU = Ut - Ub;
183 
184  if ((!(deltaCotTheta2 - error2 > 0.f) ||
185  !(dCotThetaMinusError2 > scatteringInRegion2)) &&
186  !(dU == 0.f)) {
187  auto A = (Vt - Vb) / dU;
188  auto S2 = 1.f + A * A;
189  auto B = Vb - A * Ub;
190  auto B2 = B * B;
191 
192  auto iHelixDiameter2 = B2 / S2;
193  auto pT2scatter = 4.f * iHelixDiameter2 * m_config.pT2perRadius;
194  auto p2scatter = pT2scatter * iSinTheta2;
195  auto Im = cl::sycl::abs((A - B * rM) * rM);
196 
197  if (!(S2 < B2 * m_config.minHelixDiameter2) &&
198  !((deltaCotTheta2 - error2 > 0.f) &&
199  (dCotThetaMinusError2 > p2scatter * m_config.sigmaScattering *
201  !(Im > m_config.impactMax)) {
202  vecmem::device_vector<uint32_t> deviceIndTopDuplets(
204  const auto top = deviceIndTopDuplets[it];
205  // this will be the t-th top space point for
206  // fixed middle and bottom SP
207  vecmem::device_vector<uint32_t> deviceCountTriplets(
209  vecmem::atomic obj(&deviceCountTriplets[ib]);
210  auto t = obj.fetch_add(1);
211  /*
212  sumBotTopCombPrefix[mid] - sumCombUptoFirstMiddle:
213  gives the memory location reserved for this
214  middle SP
215 
216  (idx-sumBotTopCombPrefix[mid]+sumCombUptoFirstMiddle:
217  this is the nth thread for this middle SP
218 
219  (idx-sumBotTopCombPrefix[mid]+sumCombUptoFirstMiddle)/numT:
220  this is the mth bottom SP for this middle SP
221 
222  multiplying this by numT gives the memory
223  location for this middle and bottom SP
224 
225  and by adding t to it, we will end up storing
226  compatible triplet candidates for this middle
227  and bottom SP right next to each other
228  starting from the given memory
229  */
230  const auto tripletIdx =
231  sumBotTopCombPrefix[mid] - sumCombUptoFirstMiddle +
232  (((idx - sumBotTopCombPrefix[mid] + sumCombUptoFirstMiddle) /
233  numT) *
234  numT) +
235  t;
236 
238  T.curvature = B / cl::sycl::sqrt(S2);
239  T.impact = Im;
240  T.topSPIndex = top;
241  vecmem::device_vector<detail::DeviceTriplet> deviceCurvImpact(
243  deviceCurvImpact[tripletIdx] = T;
244  }
245  }
246  }
247  }
248 
249  private:
250  vecmem::data::vector_view<uint32_t> m_sumBotTopCombView;
252  const uint32_t m_firstMiddle;
253  const u_int32_t m_lastMiddle;
254  vecmem::data::jagged_vector_view<const uint32_t> m_midTopDupletView;
255  vecmem::data::vector_view<uint32_t> m_sumBotMidView;
256  vecmem::data::vector_view<uint32_t> m_sumTopMidView;
257  vecmem::data::vector_view<detail::DeviceLinEqCircle> m_linearBotView;
258  vecmem::data::vector_view<detail::DeviceLinEqCircle> m_linearTopView;
259  vecmem::data::vector_view<const detail::DeviceSpacePoint> m_middleSPsView;
260  vecmem::data::vector_view<uint32_t> m_indTopDupletView;
261  vecmem::data::vector_view<uint32_t> m_countTripletsView;
263  vecmem::data::vector_view<detail::DeviceTriplet> m_curvImpactView;
264 }; // struct TripletSearch
265 
266 } // namespace Acts::Sycl::detail