103 int nlr = getNLayers();
105 LOG(error) <<
"The LUT is not yet initialized";
108 if (get()->mR2Intervals) {
109 LOG(error) <<
"The LUT is already populated";
117 using Clock = std::chrono::steady_clock;
118 auto seconds = [](Clock::time_point
a, Clock::time_point
b) {
119 return std::chrono::duration<double>(
b -
a).count();
123 for (
int i = 0;
i < nlr;
i++) {
124 LOG(info) <<
"Populating with " << ntrPerCell <<
" trials Lr " <<
i;
125 get()->mLayers[
i].print();
127 const auto tFillStart = Clock::now();
128 for (
int i = 0;
i < nlr;
i++) {
129 get()->mLayers[
i].populateFromTGeo(ntrPerCell);
131 const auto tFillEnd = Clock::now();
133 LOG(info) <<
"LUT fill: 1 thread, cells " << seconds(tFillStart, tFillEnd) <<
" s";
140 std::vector<size_t> layerOffsets(nlr + 1, 0);
141 for (
int i = 0;
i < nlr;
i++) {
142 LOG(info) <<
"Queuing " << ntrPerCell <<
" trials Lr " <<
i;
143 get()->mLayers[
i].print();
144 const auto& lr = get()->mLayers[
i];
145 layerOffsets[
i + 1] = layerOffsets[
i] + size_t(lr.getNZBins()) * lr.getNPhiBins();
147 const size_t totalCells = layerOffsets[nlr];
149 const auto tSetupStart = Clock::now();
156 gGeoManager->SetMaxThreads(nThreads);
158 tbb::enumerable_thread_specific<TGeoNavigator*> threadNavigators(
159 []() {
return gGeoManager->AddNavigator(); });
161 const auto tFillStart = Clock::now();
163 tbb::global_control threadControl(tbb::global_control::max_allowed_parallelism, nThreads);
164 tbb::parallel_for(tbb::blocked_range<size_t>(0, totalCells),
165 [
this, ntrPerCell, &layerOffsets, &threadNavigators](
const tbb::blocked_range<size_t>&
range) {
166 TGeoNavigator* nav = threadNavigators.local();
167 for (
size_t idx =
range.begin(); idx !=
range.end(); ++idx) {
168 auto it = std::upper_bound(layerOffsets.begin(), layerOffsets.end(), idx);
169 const int layerIdx =
int(std::distance(layerOffsets.begin(), it)) - 1;
170 const size_t cellInLayer = idx - layerOffsets[layerIdx];
171 auto&
layer = this->get()->mLayers[layerIdx];
172 const int nphi =
layer.getNPhiBins();
173 layer.populateFromTGeo(
int(cellInLayer % nphi),
int(cellInLayer / nphi), ntrPerCell, nav);
178 const auto tFillEnd = Clock::now();
180 for (TGeoNavigator* nav : threadNavigators) {
181 gGeoManager->RemoveNavigator(nav);
185 const auto tEnd = Clock::now();
189 LOG(info) <<
"LUT fill: " << nThreads <<
" threads, setup " << seconds(tSetupStart, tFillStart)
190 <<
" s, cells " << seconds(tFillStart, tFillEnd)
191 <<
" s, finalize " << seconds(tFillEnd, tEnd) <<
" s";
199 int nlr = getNLayers();
200 int nR2Int = 2 * (nlr + 1);
203 get()->mR2Intervals[0] = get()->mRMin2;
204 get()->mR2Intervals[1] = get()->mRMax2;
205 get()->mInterval2LrID[0] = 0;
206 auto& nRIntervals = get()->mNRIntervals;
209 for (
int i = 1;
i < nlr;
i++) {
211 if (o2::math_utils::sqrt(lr.getRMin2()) > o2::math_utils::sqrt(get()->mR2Intervals[nRIntervals] +
Ray::Tiny)) {
213 get()->mInterval2LrID[nRIntervals] = -1;
214 get()->mR2Intervals[++nRIntervals] = lr.getRMin2();
216 get()->mInterval2LrID[nRIntervals] =
i;
217 get()->mR2Intervals[++nRIntervals] = lr.getRMax2();
230 for (
int i = 0;
i < getNLayers();
i++) {
232 float r = 0.5 * (lr.getRMin() + lr.getRMax());
234 int nphib = lr.getNPhiBins();
235 for (
int ip = 0; ip < nphib; ip++) {
236 float phi = 0.5 * (lr.getPhiBinMin(ip) + lr.getPhiBinMax(ip));
238 int ips = lr.phiBin2Slice(ip);
240 if (ip + 1 < nphib) {
241 int ips1 = lr.phiBin2Slice(ip + 1);
242 merge = ips == ips1 ? -1 : lr.canMergePhiSlices(ips, ips1);
246 o2::math_utils::sincos(phi, sn, cs);
247 float x =
r * cs,
y =
r * sn;
248 for (
int iz = 0; iz < lr.getNZBins(); iz++) {
249 float z = 0.5 * (lr.getZBinMin(iz) + lr.getZBinMax(iz));
250 auto cell = lr.getCellPhiBin(ip, iz);
252 <<
"ilr=" <<
i <<
"r=" <<
r <<
"phi=" << phi <<
"x=" <<
x <<
"y=" <<
y <<
"z=" <<
z <<
"ip=" << ip <<
"ips=" << ips <<
"iz=" << iz
253 <<
"mrgnxt=" <<
merge <<
"val=" << cell <<
"\n";
259 lr.getMeanRMS(mean, rms);
261 <<
"ilr=" <<
i <<
"r=" <<
r <<
"mean=" << mean <<
"rms=" << rms <<
"\n";
412 if (ray.isTooShort() || !getLayersRange(ray, lmin, lmax)) {
413 rval.
length = ray.getDist();
417 while (lrID >= lmin) {
418 const auto& lr = getLayer(lrID);
419 int nphiSlices = lr.getNPhiSlices();
420 int nc = ray.crossLayer(lr);
421 for (
int ic = nc; ic--;) {
422 float cross1, cross2;
423 ray.getCrossParams(ic, cross1, cross2);
425 auto phi0 = ray.getPhi(cross1), phi1 = ray.getPhi(cross2), dPhi = phi0 - phi1;
426 auto phiID = lr.getPhiSliceID(phi0), phiIDLast = lr.getPhiSliceID(phi1);
430 phiIDLast += nphiSlices;
438 int stepPhiID = phiID > phiIDLast ? -1 : 1;
439 bool checkMorePhi =
true;
440 auto tStartPhi = cross1, tEndPhi = 0.f;
443 if (phiID == phiIDLast) {
445 checkMorePhi =
false;
447 tEndPhi = ray.crossRadial(lr, (stepPhiID > 0 ? phiID + 1 : phiID) % nphiSlices);
451 const auto tMarginPhi = 1.e-6f + 1.e-5f * (cross1 - cross2);
453 if (tEndPhi < cross2 - tMarginPhi || tEndPhi > cross1 + tMarginPhi) {
455 checkMorePhi =
false;
458 auto zID = lr.getZBinID(ray.getZ(tStartPhi));
459 auto zIDLast = lr.getZBinID(ray.getZ(tEndPhi));
463 printf(
"-- Zdiff (%3d : %3d) mode: t: %+e %+e\n", zID, zIDLast, tStartPhi, tEndPhi);
466 if (zID != zIDLast) {
467 auto stepZID = zID < zIDLast ? 1 : -1;
468 bool checkMoreZ =
true;
469 auto tStartZ = tStartPhi, tEndZ = 0.f;
471 if (zID == zIDLast) {
475 tEndZ = ray.crossZ(lr.getZBinMin(stepZID > 0 ? zID + 1 : zID));
481 float step = tEndZ > tStartZ ? tEndZ - tStartZ : tStartZ - tEndZ;
482 const auto& cell = lr.getCell(phiID % nphiSlices, zID);
483 rval.
meanRho += cell.meanRho * step;
484 rval.
meanX2X0 += cell.meanX2X0 * step;
488 float pos0[3] = {ray.getPos(tStartZ, 0), ray.getPos(tStartZ, 1), ray.getPos(tStartZ, 2)};
489 float pos1[3] = {ray.getPos(tEndZ, 0), ray.getPos(tEndZ, 1), ray.getPos(tEndZ, 2)};
491 "Lr#%3d / cross#%d : account %f<t<%f at phiSlice %d | Zbin: %3d (%3d) |[%+e %+e +%e]:[%+e %+e %+e] "
492 "Step: %.3e StrpCor: %.3e\n",
493 lrID, ic, tEndZ, tStartZ, phiID % nphiSlices, zID, zIDLast,
494 pos0[0], pos0[1], pos0[2], pos1[0], pos1[1], pos1[2], step, ray.getDist(step));
499 }
while (checkMoreZ);
501 float step = tEndPhi > tStartPhi ? tEndPhi - tStartPhi : tStartPhi - tEndPhi;
502 const auto& cell = lr.getCell(phiID % nphiSlices, zID);
503 rval.
meanRho += cell.meanRho * step;
504 rval.
meanX2X0 += cell.meanX2X0 * step;
508 float pos0[3] = {ray.getPos(tStartPhi, 0), ray.getPos(tStartPhi, 1), ray.getPos(tStartPhi, 2)};
509 float pos1[3] = {ray.getPos(tEndPhi, 0), ray.getPos(tEndPhi, 1), ray.getPos(tEndPhi, 2)};
511 "Lr#%3d / cross#%d : account %f<t<%f at phiSlice %d | Zbin: %3d ----- |[%+e %+e +%e]:[%+e %+e %+e]"
512 "Step: %.3e StrpCor: %.3e\n",
513 lrID, ic, tEndPhi, tStartPhi, phiID % nphiSlices, zID,
514 pos0[0], pos0[1], pos0[2], pos1[0], pos1[1], pos1[2], step, ray.getDist(step));
521 }
while (checkMorePhi);
530 rval.
length = ray.getDist();
545 ray.getMinMaxR2(rmin2, rmax2);
547 if (rmin2 >= getRMax2() || rmax2 <= getRMin2()) {
551 if (!mInitializedLayerVoxelLU) {
552 lmxInt = rmax2 < getRMax2() ? searchSegment(rmax2, 0) :
get()->mNRIntervals - 2;
553 lmnInt = rmin2 >= getRMin2() ? searchSegment(rmin2, 0, lmxInt + 1) : 0;
555 lmxInt = rmax2 < getRMax2() ? searchLayerFast(rmax2, 0) :
get()->mNRIntervals - 2;
556 lmnInt = rmin2 >= getRMin2() ? searchLayerFast(rmin2, 0, lmxInt + 1) : 0;
559 const auto* interval2LrID =
get()->mInterval2LrID;
560 lmax = interval2LrID[lmxInt];
561 lmin = interval2LrID[lmnInt];
564 lmax = interval2LrID[lmxInt - 1];
567 lmin = interval2LrID[lmnInt + 1];
575 const auto index = 2 *
int(o2::gpu::CAMath::Sqrt(r2) * InvVoxelRDelta);
576 const auto layersfirst = mLayerVoxelLU[
index];
577 const auto layerslast = mLayerVoxelLU[
index + 1];
578 if (layersfirst != layerslast) {
580 return searchSegment(r2, layersfirst, layerslast + 1);
592 high =
get()->mNRIntervals;
594 int mid = (low + high) >> 1;
595 const auto* r2Intervals =
get()->mR2Intervals;
597 if (
val < r2Intervals[mid]) {
602 mid = (low + high) >> 1;
608#ifndef GPUCA_ALIGPUCODE
620 int nLr = getNLayers();
626 for (
int i = nLr;
i--;) {
627 oldLayers[
i].clearInternalBufferPtr();
640 for (
int il = 0; il < nLr; il++) {
720 if (addTo && addTo->getNLayers() != getNLayers()) {
721 LOGP(fatal,
"addTo has {} layers, this has {}", addTo->getNLayers(), getNLayers());
723 Ray ray(std::max(getRMin(), rmin), 0., 0., std::min(getRMax(), rmax), 0., 0.);
725 if (!getLayersRange(ray,
lmin, lmax)) {
726 LOGP(warn,
"No layers found for {} < r < {}", rmin, rmax);
729 LOGP(info,
"Will extract layers {}:{} (out of {} layers) for {} < r < {}",
lmin, lmax, getNLayers(), rmin, rmax);
731 int lrCount = 0, lrCounOld = 0, lrCountTot = 0;
732 auto addLr = [copy, &lrCountTot](
const MatLayerCyl& lr) {
733 float drphi = lr.getDPhi() * (lr.getRMin() + lr.getRMax()) / 2. * 0.999;
734 copy->
addLayer(lr.getRMin(), lr.getRMax(), lr.getZMax(), lr.getDZ(), drphi);
735 auto& lrNew = copy->
getLayer(lrCountTot++);
736 for (
int iz = 0; iz < lrNew.getNZBins(); iz++) {
737 for (
int ip = 0; ip < lrNew.getNPhiBins(); ip++) {
743 for (
int il = 0; il <
lmin; il++) {
748 for (
int il =
lmin; il <= lmax; il++) {
753 for (
int il = lmax + 1; il < getNLayers(); il++) {
761 LOGP(info,
"Added layers {}:{} for {}<r<{} {}",
lmin, lmax, rmin, rmax, fmt::format(
", {} layers were transferred from additional set", lrCounOld));