Project
Loading...
Searching...
No Matches
MatLayerCyl.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include "MathUtils/Utils.h"
18#ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version
20#include "GPUCommonLogger.h"
21#endif
22
23using namespace o2::base;
25
26#ifndef GPUCA_GPUCODE
27//________________________________________________________________________________
28MatLayerCyl::MatLayerCyl() : mNZBins(0), mNPhiBins(0), mNPhiSlices(0), mZHalf(0.f), mRMin2(0.f), mRMax2(0.f), mDZ(0.f), mDZInv(0.f), mDPhi(0.f), mDPhiInv(0.f), mPhiBin2Slice(nullptr), mSliceCos(nullptr), mSliceSin(nullptr), mCells(nullptr)
29{
30}
31#endif
32
33#ifndef GPUCA_ALIGPUCODE // this part is unvisible on GPU version
34//________________________________________________________________________________
35MatLayerCyl::MatLayerCyl(float rMin, float rMax, float zHalfSpan, float dzMin, float drphiMin)
36{
37 // main constructor
38 initSegmentation(rMin, rMax, zHalfSpan, dzMin, drphiMin);
39}
40
41//________________________________________________________________________________
42void MatLayerCyl::initSegmentation(float rMin, float rMax, float zHalfSpan, float dzMin, float drphiMin)
43{
44 // init and precalculate aux parameters. The initialization is done in the own memory.
45 if (dzMin < 0.001f) {
46 dzMin = 0.001f;
47 }
48 if (drphiMin < 0.001f) {
49 drphiMin = 0.001f;
50 }
51 float peri = (rMax + rMin) * o2::constants::math::PI;
52 int nz = 2 * zHalfSpan / dzMin, nphi = peri / drphiMin;
53 initSegmentation(rMin, rMax, zHalfSpan, nz < 1 ? 1 : nz, nphi < 1 ? 1 : nphi);
54}
55
56//________________________________________________________________________________
57void MatLayerCyl::initSegmentation(float rMin, float rMax, float zHalfSpan, int nz, int nphi)
58{
59 // Init and precalculate aux parameters. The initialization is done in the own memory.
61 assert(rMin < rMax);
62 assert(nz > 0);
63 assert(nphi > 0);
64
65 // book local storage
66 auto sz = estimateFlatBufferSize(nphi, nphi, nz);
67
68 //--------------????
69 mFlatBufferPtr = mFlatBufferContainer = new char[sz];
70 mFlatBufferSize = sz;
71 //--------------????
72
73 mRMin2 = rMin * rMin;
74 mRMax2 = rMax * rMax;
75 mZHalf = zHalfSpan;
76 mNZBins = nz;
77
78 mDZ = 2. * zHalfSpan / nz;
79 mDZInv = 1.f / mDZ;
80
82 mDPhiInv = 1.f / mDPhi;
83 //
84 int offs = 0;
85
86 o2::gpu::FlatObject::FlatObject::resizeArray(mPhiBin2Slice, 0, nphi, reinterpret_cast<short*>(mFlatBufferPtr + offs));
87 mNPhiSlices = mNPhiBins = nphi;
88
89 for (int i = nphi; i--;) {
90 mPhiBin2Slice[i] = i; // fill with trivial mapping
91 }
92
93 offs = alignSize(offs + nphi * sizeof(short), getBufferAlignmentBytes()); // account for alignment
94
95 o2::gpu::FlatObject::resizeArray(mSliceCos, 0, nphi, reinterpret_cast<float*>(mFlatBufferPtr + offs)); // in the beginning nslice = nphi
96 offs = alignSize(offs + nphi * sizeof(float), getBufferAlignmentBytes()); // account for alignment
97
98 o2::gpu::FlatObject::resizeArray(mSliceSin, 0, nphi, reinterpret_cast<float*>(mFlatBufferPtr + offs)); // in the beginning nslice = nphi
99 offs = alignSize(offs + nphi * sizeof(float), getBufferAlignmentBytes()); // account for alignment
100
101 for (int i = nphi; i--;) {
102 mSliceCos[i] = o2::math_utils::cos(getPhiBinMin(i));
103 mSliceSin[i] = o2::math_utils::sin(getPhiBinMin(i));
104 }
105
106 o2::gpu::FlatObject::resizeArray(mCells, 0, getNCells(), reinterpret_cast<MatCell*>(mFlatBufferPtr + offs));
107
109}
110
111//________________________________________________________________________________
113{
117 ntrPerCell = ntrPerCell > 1 ? ntrPerCell : 1;
118 for (int iz = getNZBins(); iz--;) {
119 for (int ip = getNPhiBins(); ip--;) {
120 populateFromTGeo(ip, iz, ntrPerCell, nullptr, backend);
121 }
122 }
123}
124
125//________________________________________________________________________________
126void MatLayerCyl::populateFromTGeo(int ip, int iz, int ntrPerCell, TGeoNavigator* nav, MatbudGeomBackend backend)
127{
129
130 float zmn = getZBinMin(iz), phmn = getPhiBinMin(ip), sn, cs, rMin = getRMin(), rMax = getRMax();
131 double meanRho = 0., meanX2X0 = 0., lgt = 0.;
132 ;
133 float dz = getDZ() / ntrPerCell;
134 for (int isz = ntrPerCell; isz--;) {
135 float zs = zmn + (isz + 0.5) * dz;
136 float dzt = zs > 0.f ? 0.25 * dz : -0.25 * dz; // to avoid 90 degree polar angle
137 for (int isp = ntrPerCell; isp--;) {
138 o2::math_utils::sincos(phmn + (isp + 0.5) * getDPhi() / ntrPerCell, sn, cs);
140 if (backend == MatbudGeomBackend::ROOT) {
141 bud = o2::base::GeometryManager::meanMaterialBudget(rMin * cs, rMin * sn, zs - dzt, rMax * cs, rMax * sn, zs + dzt, nav);
142 } else {
143#ifdef O2_WITH_VECGEOM
144 bud = o2::base::GeometryManager::vecGeomMaterialBudget(rMin * cs, rMin * sn, zs - dzt, rMax * cs, rMax * sn, zs + dzt);
145#else
146 LOG(fatal) << "MatbudGeomBackend::VECGEOM requested but O2 was built without VecGeom support (TGeo2VecGeom not found at configure time)";
147#endif
148 }
149 if (bud.length > 0.) {
150 meanRho += bud.length * bud.meanRho;
151 meanX2X0 += bud.meanX2X0; // we store actually not X2X0 but 1./X0
152 lgt += bud.length;
153 }
154 }
155 }
156 if (lgt > 0.) {
157 auto& cell = mCells[getCellIDPhiBin(ip, iz)];
158 cell.meanRho = meanRho / lgt; // mean rho
159 cell.meanX2X0 = meanX2X0 / lgt; // mean 1./X0 seen in this cell
160 }
161}
162
163//________________________________________________________________________________
164bool MatLayerCyl::canMergePhiSlices(int i, int j, float maxRelDiff, int maxDifferent) const
165{
166 if (std::abs(i - j) > 1 || i == j || std::max(i, j) >= getNPhiSlices()) {
167 LOG(error) << "Only existing " << getNPhiSlices() << " slices with diff. of 1 can be merged, input is " << i << " and " << j;
168 return false;
169 }
170 int ndiff = 0; // number of different cells
171 for (int iz = getNZBins(); iz--;) {
172 const auto& cellI = getCellPhiBin(i, iz);
173 const auto& cellJ = getCellPhiBin(j, iz);
174 if (cellsDiffer(cellI, cellJ, maxRelDiff)) {
175 if (++ndiff > maxDifferent) {
176 return false;
177 }
178 }
179 }
180 return true;
181}
182
183//________________________________________________________________________________
184bool MatLayerCyl::cellsDiffer(const MatCell& cellA, const MatCell& cellB, float maxRelDiff) const
185{
187 float rav = 0.5 * (cellA.meanRho + cellB.meanRho), xav = 0.5 * (cellA.meanX2X0 + cellB.meanX2X0);
188 float rdf = 0.5 * (cellA.meanRho - cellB.meanRho), xdf = 0.5 * (cellA.meanX2X0 - cellB.meanX2X0);
189 if (rav > 0 && std::abs(rdf / rav) > maxRelDiff) {
190 return true;
191 }
192 if (xav > 0 && std::abs(xdf / xav) > maxRelDiff) {
193 return true;
194 }
195 return false;
196}
197
198//________________________________________________________________________________
199void MatLayerCyl::optimizePhiSlices(float maxRelDiff)
200{
201 // merge compatible phi slices
202 if (getNPhiSlices() < getNPhiBins()) {
203 LOG(error) << getNPhiBins() << " phi bins were already merged to " << getNPhiSlices() << " slices";
204 return;
205 }
206 int newSl = 0;
207 std::vector<int> phi2SlNew(getNPhiBins());
208 for (int i = 0; i < getNPhiBins(); i++) {
209 phi2SlNew[i] = mPhiBin2Slice[i];
210 }
211 for (int is = 1; is < getNPhiSlices(); is++) {
212 if (!canMergePhiSlices(is - 1, is, maxRelDiff)) {
213 newSl++;
214 } else {
215 mPhiBin2Slice[is] = mPhiBin2Slice[is - 1];
216 }
217 phi2SlNew[is] = newSl; // new numbering
218 }
219 if (newSl + 1 == getNPhiSlices()) {
220 return;
221 }
222 newSl = 0;
223 int slMin = 0, slMax = 0, is = 0;
224 while (is++ < getNPhiSlices()) {
225 while (is < getNPhiSlices() && phi2SlNew[is] == newSl) { // select similar slices
226 slMax++;
227 is++;
228 }
229 if (slMax > slMin || newSl != slMin) { // merge or shift slices
230 mSliceCos[newSl] = mSliceCos[slMin];
231 mSliceSin[newSl] = mSliceSin[slMin];
232 float norm = 1.f / (1.f + slMax - slMin);
233 for (int iz = getNZBins(); iz--;) {
234 int iDest = newSl * getNZBins() + iz, iSrc = slMin * getNZBins() + iz;
235 mCells[iDest] = mCells[iSrc];
236 for (int ism = slMin + 1; ism <= slMax; ism++) {
237 iSrc = ism * getNZBins() + iz;
238 mCells[iDest].meanX2X0 += mCells[iSrc].meanX2X0;
239 mCells[iDest].meanRho += mCells[iSrc].meanRho;
240 }
241 mCells[iDest].scale(norm);
242 }
243 LOG(info) << "mapping " << slMin << ":" << slMax << " to new slice " << newSl;
244 }
245 newSl++;
246 slMin = slMax = is;
247 }
248 for (int i = 0; i < getNPhiBins(); i++) {
249 mPhiBin2Slice[i] = phi2SlNew[i];
250 }
251 mNPhiSlices = newSl;
252
253 // relocate arrays to avoid spaces after optimization
254 // mSliceCos pointer does not change, but sliceSin needs to be relocated
255 auto offs = alignSize(newSl * sizeof(float), getBufferAlignmentBytes());
256 char* dst = ((char*)mSliceCos) + offs; // account for alignment
257 o2::gpu::FlatObject::resizeArray(mSliceSin, getNPhiBins(), newSl, reinterpret_cast<float*>(dst));
258 // adjust mCells array
259 dst = ((char*)mSliceSin) + offs; // account for alignment
260 o2::gpu::FlatObject::resizeArray(mCells, getNPhiBins() * getNZBins(), newSl * getNZBins(), reinterpret_cast<MatCell*>(dst));
262 LOG(info) << "Updated Nslices = " << getNPhiSlices();
263}
264
265//________________________________________________________________________________
267{
268 // mean and RMS over layer
269 mean.meanRho = rms.meanRho = 0.f;
270 mean.meanX2X0 = rms.meanX2X0 = 0.f;
271 for (int ip = getNPhiBins(); ip--;) {
272 for (int iz = getNZBins(); iz--;) {
273 const auto& cell = getCellPhiBin(ip, iz);
274 mean.meanRho += cell.meanRho;
275 mean.meanX2X0 += cell.meanX2X0;
276 rms.meanRho += cell.meanRho * cell.meanRho;
277 rms.meanX2X0 += cell.meanX2X0 * cell.meanX2X0;
278 }
279 }
280 int nc = getNPhiBins() * getNZBins();
281 mean.meanRho /= nc;
282 mean.meanX2X0 /= nc;
283 rms.meanRho /= nc;
284 rms.meanX2X0 /= nc;
285 rms.meanRho -= mean.meanRho * mean.meanRho;
286 rms.meanX2X0 -= mean.meanX2X0 * mean.meanX2X0;
287 rms.meanRho = rms.meanRho > 0.f ? o2::math_utils::sqrt(rms.meanRho) : 0.f;
288 rms.meanX2X0 = rms.meanX2X0 > 0.f ? o2::math_utils::sqrt(rms.meanX2X0) : 0.f;
289}
290
291//________________________________________________________________________________
292void MatLayerCyl::print(bool data) const
293{
295 float szkb = float(getFlatBufferSize()) / 1024;
296 printf("Cyl.Layer %.3f<r<%.3f %+.3f<Z<%+.3f | Nphi: %5d (%d slices) Nz: %5d Size: %.3f KB\n",
297 getRMin(), getRMax(), getZMin(), getZMax(), getNPhiBins(), getNPhiSlices(), getNZBins(), szkb);
298 if (!data) {
299 return;
300 }
301 for (int ip = 0; ip < getNPhiSlices(); ip++) {
302 int ib0, ib1;
303 int nb = getNPhiBinsInSlice(ip, ib0, ib1);
304 printf("phi slice: %d (%d bins %d-%d %.4f:%.4f) sn:%+.4f/cs:%+.4f ... [iz/<rho>/<x/x0>] \n",
305 ip, nb, ib0, ib1, getDPhi() * ib0, getDPhi() * (ib1 + 1), getSliceSin(ip), getSliceCos(ip));
306 for (int iz = 0; iz < getNZBins(); iz++) {
307 auto cell = getCellPhiBin(ib0, iz);
308 printf("%3d/%.2e/%.2e ", iz, cell.meanRho, cell.meanX2X0);
309 if (((iz + 1) % 5) == 0) {
310 printf("\n");
311 }
312 }
313 if (getNZBins() % 5) {
314 printf("\n");
315 }
316 }
317}
318
319//________________________________________________________________________________
320void MatLayerCyl::flatten(char* newPtr)
321{
322 // make object flat: move all content to single internally allocated buffer
323 assert(mConstructionMask == InProgress);
325 auto old = o2::gpu::FlatObject::resizeArray(mFlatBufferPtr, getFlatBufferSize(), getFlatBufferSize(), newPtr);
326 delete[] old;
327 mFlatBufferContainer = nullptr;
329}
330
331//________________________________________________________________________________
332void MatLayerCyl::scale(float factor, bool _x2x0, bool _rho)
333{
334 LOGP(info, "Scaling layer {:.3f}<r<{:.3f} by {:.3f}", getRMin(), getRMax(), factor);
335 for (int i = 0; i < mNPhiSlices * mNZBins; i++) {
336 if (_x2x0) {
337 mCells[i].meanX2X0 *= factor;
338 }
339 if (_rho) {
340 mCells[i].meanRho *= factor;
341 }
342 }
343}
344
345#endif // ! GPUCA_ALIGPUCODE
346
347#ifndef GPUCA_GPUCODE
348
349//________________________________________________________________________________
350void MatLayerCyl::fixPointers(char* oldPtr, char* newPtr)
351{
352 // fix pointers on the internal structure of the flat buffer after retrieving it from the file
356 mCells = flatObject::relocatePointer(oldPtr, newPtr, mCells);
357}
358#endif // ! GPUCA_GPUCODE
359
360//________________________________________________________________________________
361GPUd() int MatLayerCyl::getNPhiBinsInSlice(int iSlice, int& binMin, int& binMax) const
362{
363 // slow method to get number of phi bins for given phi slice
364 int nb = 0;
365 binMin = binMax = -1;
366 for (int ib = getNPhiBins(); ib--;) {
367 if (phiBin2Slice(ib) == iSlice) {
368 binMax < 0 ? binMin = binMax = ib : binMin = ib;
369 nb++;
370 continue;
371 }
372 if (binMax >= 0) {
373 break; // no more bins since they are consecutive
374 }
375 }
376 return nb;
377}
General auxilliary methods.
Definition of the GeometryManager class.
int32_t i
#define GPUd()
Declarations for single cylindrical material layer class.
useful math constants
uint32_t j
Definition RawData.h:0
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1, TGeoNavigator *nav=nullptr)
short mNPhiSlices
actual number of phi slices
MatCell * mCells
cached sin each phi slice
float mZHalf
Z half span.
short mNPhiBins
number of phi bins (logical)
void optimizePhiSlices(float maxRelDiff=0.05)
float mRMin2
squared min r
std::size_t estimateFlatBufferSize() const
float mDZ
Z slice thickness.
void populateFromTGeo(int ntrPerCell=10, MatbudGeomBackend backend=MatbudGeomBackend::ROOT)
float mDPhi
phi slice thickness
static constexpr size_t getBufferAlignmentBytes()
Gives minimal alignment in bytes required for the flat buffer.
void print(bool data=false) const
float * mSliceSin
cached cos each phi slice
void initSegmentation(float rMin, float rMax, float zHalfSpan, int nz, int nphi)
bool cellsDiffer(const MatCell &cellA, const MatCell &cellB, float maxRelDiff) const
float mDZInv
Z slice thickness inverse.
void getMeanRMS(MatCell &mean, MatCell &rms) const
float * mSliceCos
mapping from analytical phi bin ID to real slice ID
void flatten(char *newPtr)
void scale(float factor, bool _x2x0=true, bool _rho=true)
short mNZBins
number of Z bins
MatCell & getCellPhiBin(int iphi, int iz)
float mRMax2
squared max r
void fixPointers(char *oldPtr, char *newPtr)
float mDPhiInv
phi slice thickness inverse
bool canMergePhiSlices(int i, int j, float maxRelDiff=0.05, int maxDifferent=1) const
uint32_t mConstructionMask
mask for constructed object members, first two bytes are used by this class
Definition FlatObject.h:321
int32_t mFlatBufferSize
size of the flat buffer
Definition FlatObject.h:320
char * mFlatBufferContainer
Definition FlatObject.h:322
static T * relocatePointer(const char *oldBase, char *newBase, const T *ptr)
Relocates a pointer inside a buffer to the new buffer address.
Definition FlatObject.h:283
static constexpr size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
_______________ Generic utilities _______________________________________________
Definition FlatObject.h:275
T * resizeArray(T *&ptr, int32_t oldSize, int32_t newSize, T *newPtr=nullptr)
Definition FlatObject.h:135
@ InProgress
construction started: temporary memory is reserved
Definition FlatObject.h:317
@ NotConstructed
the object is not constructed
Definition FlatObject.h:315
@ Constructed
the object is constructed, temporary memory is released
Definition FlatObject.h:316
GLenum GLenum dst
Definition glcorearb.h:1767
GLboolean * data
Definition glcorearb.h:298
constexpr float TwoPI
constexpr float PI
float length
length in material
Definition MatCell.h:55
float meanRho
mean density, g/cm^3
Definition MatCell.h:30
float meanX2X0
fraction of radiaton lenght
Definition MatCell.h:31
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"