104 LOG(fatal) <<
"MatbudGeomBackend::VECGEOM requested but O2 was built without VecGeom support (TGeo2VecGeom not found at configure time)";
107 int nlr = getNLayers();
109 LOG(error) <<
"The LUT is not yet initialized";
112 if (get()->mR2Intervals) {
113 LOG(error) <<
"The LUT is already populated";
121 using Clock = std::chrono::steady_clock;
122 auto seconds = [](Clock::time_point
a, Clock::time_point
b) {
123 return std::chrono::duration<double>(
b -
a).count();
127 for (
int i = 0;
i < nlr;
i++) {
128 LOG(info) <<
"Populating with " << ntrPerCell <<
" trials Lr " <<
i;
129 get()->mLayers[
i].print();
131 const auto tSetupStart = Clock::now();
132#ifdef O2_WITH_VECGEOM
136 GeometryManager::vecGeomMaterialBudget(0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
139 const auto tFillStart = Clock::now();
140 for (
int i = 0;
i < nlr;
i++) {
141 get()->mLayers[
i].populateFromTGeo(ntrPerCell, backend);
143 const auto tFillEnd = Clock::now();
145 LOG(info) <<
"LUT fill: 1 thread, setup " << seconds(tSetupStart, tFillStart)
146 <<
" s, cells " << seconds(tFillStart, tFillEnd) <<
" s";
153 std::vector<size_t> layerOffsets(nlr + 1, 0);
154 for (
int i = 0;
i < nlr;
i++) {
155 LOG(info) <<
"Queuing " << ntrPerCell <<
" trials Lr " <<
i;
156 get()->mLayers[
i].print();
157 const auto& lr = get()->mLayers[
i];
158 layerOffsets[
i + 1] = layerOffsets[
i] + size_t(lr.getNZBins()) * lr.getNPhiBins();
160 const size_t totalCells = layerOffsets[nlr];
162 const auto tSetupStart = Clock::now();
164 auto fillRange = [
this, ntrPerCell, backend, &layerOffsets](
const tbb::blocked_range<size_t>&
range, TGeoNavigator* nav) {
165 for (
size_t idx =
range.begin(); idx !=
range.end(); ++idx) {
166 auto it = std::upper_bound(layerOffsets.begin(), layerOffsets.end(), idx);
167 const int layerIdx =
int(std::distance(layerOffsets.begin(), it)) - 1;
168 const size_t cellInLayer = idx - layerOffsets[layerIdx];
169 auto&
layer = this->get()->mLayers[layerIdx];
170 const int nphi =
layer.getNPhiBins();
171 layer.populateFromTGeo(
int(cellInLayer % nphi),
int(cellInLayer / nphi), ntrPerCell, nav, backend);
175 Clock::time_point tFillStart, tFillEnd;
182 gGeoManager->SetMaxThreads(nThreads);
184 tbb::enumerable_thread_specific<TGeoNavigator*> threadNavigators(
185 []() {
return gGeoManager->AddNavigator(); });
187 tFillStart = Clock::now();
189 tbb::global_control threadControl(tbb::global_control::max_allowed_parallelism, nThreads);
190 tbb::parallel_for(tbb::blocked_range<size_t>(0, totalCells),
191 [&fillRange, &threadNavigators](
const tbb::blocked_range<size_t>&
range) {
192 fillRange(
range, threadNavigators.local());
195 tFillEnd = Clock::now();
197 for (TGeoNavigator* nav : threadNavigators) {
198 gGeoManager->RemoveNavigator(nav);
203#ifdef O2_WITH_VECGEOM
204 GeometryManager::vecGeomMaterialBudget(0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
206 tFillStart = Clock::now();
208 tbb::global_control threadControl(tbb::global_control::max_allowed_parallelism, nThreads);
209 tbb::parallel_for(tbb::blocked_range<size_t>(0, totalCells),
210 [&fillRange](
const tbb::blocked_range<size_t>&
range) {
211 fillRange(
range,
nullptr);
214 tFillEnd = Clock::now();
218 const auto tEnd = Clock::now();
222 LOG(info) <<
"LUT fill: " << nThreads <<
" threads, setup " << seconds(tSetupStart, tFillStart)
223 <<
" s, cells " << seconds(tFillStart, tFillEnd)
224 <<
" s, finalize " << seconds(tFillEnd, tEnd) <<
" s";
448 if (ray.isTooShort() || !getLayersRange(ray, lmin, lmax)) {
449 rval.
length = ray.getDist();
453 while (lrID >= lmin) {
454 const auto& lr = getLayer(lrID);
455 int nphiSlices = lr.getNPhiSlices();
456 int nc = ray.crossLayer(lr);
457 for (
int ic = nc; ic--;) {
458 float cross1, cross2;
459 ray.getCrossParams(ic, cross1, cross2);
461 auto phi0 = ray.getPhi(cross1), phi1 = ray.getPhi(cross2), dPhi = phi0 - phi1;
462 auto phiID = lr.getPhiSliceID(phi0), phiIDLast = lr.getPhiSliceID(phi1);
466 phiIDLast += nphiSlices;
474 int stepPhiID = phiID > phiIDLast ? -1 : 1;
475 bool checkMorePhi =
true;
476 auto tStartPhi = cross1, tEndPhi = 0.f;
479 if (phiID == phiIDLast) {
481 checkMorePhi =
false;
483 const int boundaryPhiID = stepPhiID > 0 ? phiID + 1 : phiID;
485 const int wrappedBoundaryPhiID = boundaryPhiID < nphiSlices ? boundaryPhiID : boundaryPhiID - nphiSlices;
486 tEndPhi = ray.crossRadial(lr, wrappedBoundaryPhiID);
490 const auto tMarginPhi = 1.e-6f + 1.e-5f * (cross1 - cross2);
492 if (tEndPhi < cross2 - tMarginPhi || tEndPhi > cross1 + tMarginPhi) {
494 checkMorePhi =
false;
497 auto zID = lr.getZBinID(ray.getZ(tStartPhi));
498 auto zIDLast = lr.getZBinID(ray.getZ(tEndPhi));
499 const int wrappedPhiID = phiID < nphiSlices ? phiID : phiID - nphiSlices;
500 const auto* cellRow = lr.getCellRow(wrappedPhiID);
504 printf(
"-- Zdiff (%3d : %3d) mode: t: %+e %+e\n", zID, zIDLast, tStartPhi, tEndPhi);
507 if (zID != zIDLast) {
508 auto stepZID = zID < zIDLast ? 1 : -1;
509 bool checkMoreZ =
true;
510 auto tStartZ = tStartPhi, tEndZ = 0.f;
512 if (zID == zIDLast) {
516 tEndZ = ray.crossZ(lr.getZBinMin(stepZID > 0 ? zID + 1 : zID));
522 float step = tEndZ > tStartZ ? tEndZ - tStartZ : tStartZ - tEndZ;
523 const auto& cell = cellRow[zID];
524 rval.
meanRho += cell.meanRho * step;
525 rval.
meanX2X0 += cell.meanX2X0 * step;
529 float pos0[3] = {ray.getPos(tStartZ, 0), ray.getPos(tStartZ, 1), ray.getPos(tStartZ, 2)};
530 float pos1[3] = {ray.getPos(tEndZ, 0), ray.getPos(tEndZ, 1), ray.getPos(tEndZ, 2)};
532 "Lr#%3d / cross#%d : account %f<t<%f at phiSlice %d | Zbin: %3d (%3d) |[%+e %+e +%e]:[%+e %+e %+e] "
533 "Step: %.3e StrpCor: %.3e\n",
534 lrID, ic, tEndZ, tStartZ, wrappedPhiID, zID, zIDLast,
535 pos0[0], pos0[1], pos0[2], pos1[0], pos1[1], pos1[2], step, ray.getDist(step));
540 }
while (checkMoreZ);
542 float step = tEndPhi > tStartPhi ? tEndPhi - tStartPhi : tStartPhi - tEndPhi;
543 const auto& cell = cellRow[zID];
544 rval.
meanRho += cell.meanRho * step;
545 rval.
meanX2X0 += cell.meanX2X0 * step;
549 float pos0[3] = {ray.getPos(tStartPhi, 0), ray.getPos(tStartPhi, 1), ray.getPos(tStartPhi, 2)};
550 float pos1[3] = {ray.getPos(tEndPhi, 0), ray.getPos(tEndPhi, 1), ray.getPos(tEndPhi, 2)};
552 "Lr#%3d / cross#%d : account %f<t<%f at phiSlice %d | Zbin: %3d ----- |[%+e %+e +%e]:[%+e %+e %+e]"
553 "Step: %.3e StrpCor: %.3e\n",
554 lrID, ic, tEndPhi, tStartPhi, wrappedPhiID, zID,
555 pos0[0], pos0[1], pos0[2], pos1[0], pos1[1], pos1[2], step, ray.getDist(step));
562 }
while (checkMorePhi);
571 rval.
length = ray.getDist();
586 ray.getMinMaxR2(rmin2, rmax2);
588 if (rmin2 >= getRMax2() || rmax2 <= getRMin2()) {
592 if (!mInitializedLayerVoxelLU) {
593 lmxInt = rmax2 < getRMax2() ? searchSegment(rmax2, 0) :
get()->mNRIntervals - 2;
594 lmnInt = rmin2 >= getRMin2() ? searchSegment(rmin2, 0, lmxInt + 1) : 0;
597 const bool useMax = rmax2 < getRMax2();
598 const bool useMin = rmin2 >= getRMin2();
599 const int ixMax = useMax ? voxelIndex(rmax2) : NumVoxels - 1;
600 const int ixMin = useMin ? voxelIndex(rmin2) : 0;
601 const uint16_t eMax = mLayerVoxelLU[ixMax];
602 const uint16_t eMin = mLayerVoxelLU[ixMin];
603 lmxInt = useMax ? resolveLayerRange(rmax2, ixMax, eMax) :
get()->mNRIntervals - 2;
604 lmnInt = useMin ? resolveLayerRange(rmin2, ixMin, eMin) : 0;
607 const auto* interval2LrID =
get()->mInterval2LrID;
608 lmax = interval2LrID[lmxInt];
609 lmin = interval2LrID[lmnInt];
612 lmax = interval2LrID[lmxInt - 1];
615 lmin = interval2LrID[lmnInt + 1];
623 const auto index = voxelIndex(r2);
624 return resolveLayerRange(r2,
index, mLayerVoxelLU[
index]);
629 const int layersfirst =
entry & VoxelSegmentMask;
630 if (
entry & VoxelAmbiguousBit) {
632 const auto upperR = voxelRMax(voxel);
633 const auto layerslast = searchSegment(upperR * upperR);
634 return searchSegment(r2, layersfirst, layerslast + 1);
646 high =
get()->mNRIntervals;
648 int mid = (low + high) >> 1;
649 const auto* r2Intervals =
get()->mR2Intervals;
651 if (
val < r2Intervals[mid]) {
656 mid = (low + high) >> 1;
662#ifndef GPUCA_ALIGPUCODE
680 for (
int i = nLr;
i--;) {
681 oldLayers[
i].clearInternalBufferPtr();
687 const int nRBound =
get()->mNRIntervals;
695 for (
int il = 0; il < nLr; il++) {
780 if (addTo && addTo->getNLayers() != getNLayers()) {
781 LOGP(fatal,
"addTo has {} layers, this has {}", addTo->getNLayers(), getNLayers());
783 Ray ray(std::max(getRMin(), rmin), 0., 0., std::min(getRMax(), rmax), 0., 0.);
785 if (!getLayersRange(ray,
lmin, lmax)) {
786 LOGP(warn,
"No layers found for {} < r < {}", rmin, rmax);
789 LOGP(info,
"Will extract layers {}:{} (out of {} layers) for {} < r < {}",
lmin, lmax, getNLayers(), rmin, rmax);
791 int lrCount = 0, lrCounOld = 0, lrCountTot = 0;
792 auto addLr = [copy, &lrCountTot](
const MatLayerCyl& lr) {
793 float drphi = lr.getDPhi() * (lr.getRMin() + lr.getRMax()) / 2. * 0.999;
794 copy->
addLayer(lr.getRMin(), lr.getRMax(), lr.getZMax(), lr.getDZ(), drphi);
795 auto& lrNew = copy->
getLayer(lrCountTot++);
796 for (
int iz = 0; iz < lrNew.getNZBins(); iz++) {
797 for (
int ip = 0; ip < lrNew.getNPhiBins(); ip++) {
803 for (
int il = 0; il <
lmin; il++) {
808 for (
int il =
lmin; il <= lmax; il++) {
813 for (
int il = lmax + 1; il < getNLayers(); il++) {
821 LOGP(info,
"Added layers {}:{} for {}<r<{} {}",
lmin, lmax, rmin, rmax, fmt::format(
", {} layers were transferred from additional set", lrCounOld));