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::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::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::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::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);
121 }
122 }
123}
124
125//________________________________________________________________________________
126void MatLayerCyl::populateFromTGeo(int ip, int iz, int ntrPerCell)
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);
139 auto bud = o2::base::GeometryManager::meanMaterialBudget(rMin * cs, rMin * sn, zs - dzt, rMax * cs, rMax * sn, zs + dzt);
140 if (bud.length > 0.) {
141 meanRho += bud.length * bud.meanRho;
142 meanX2X0 += bud.meanX2X0; // we store actually not X2X0 but 1./X0
143 lgt += bud.length;
144 }
145 }
146 }
147 if (lgt > 0.) {
148 auto& cell = mCells[getCellIDPhiBin(ip, iz)];
149 cell.meanRho = meanRho / lgt; // mean rho
150 cell.meanX2X0 = meanX2X0 / lgt; // mean 1./X0 seen in this cell
151 }
152}
153
154//________________________________________________________________________________
155bool MatLayerCyl::canMergePhiSlices(int i, int j, float maxRelDiff, int maxDifferent) const
156{
157 if (std::abs(i - j) > 1 || i == j || std::max(i, j) >= getNPhiSlices()) {
158 LOG(error) << "Only existing " << getNPhiSlices() << " slices with diff. of 1 can be merged, input is " << i << " and " << j;
159 return false;
160 }
161 int ndiff = 0; // number of different cells
162 for (int iz = getNZBins(); iz--;) {
163 const auto& cellI = getCellPhiBin(i, iz);
164 const auto& cellJ = getCellPhiBin(j, iz);
165 if (cellsDiffer(cellI, cellJ, maxRelDiff)) {
166 if (++ndiff > maxDifferent) {
167 return false;
168 }
169 }
170 }
171 return true;
172}
173
174//________________________________________________________________________________
175bool MatLayerCyl::cellsDiffer(const MatCell& cellA, const MatCell& cellB, float maxRelDiff) const
176{
178 float rav = 0.5 * (cellA.meanRho + cellB.meanRho), xav = 0.5 * (cellA.meanX2X0 + cellB.meanX2X0);
179 float rdf = 0.5 * (cellA.meanRho - cellB.meanRho), xdf = 0.5 * (cellA.meanX2X0 - cellB.meanX2X0);
180 if (rav > 0 && std::abs(rdf / rav) > maxRelDiff) {
181 return true;
182 }
183 if (xav > 0 && std::abs(xdf / xav) > maxRelDiff) {
184 return true;
185 }
186 return false;
187}
188
189//________________________________________________________________________________
190void MatLayerCyl::optimizePhiSlices(float maxRelDiff)
191{
192 // merge compatible phi slices
193 if (getNPhiSlices() < getNPhiBins()) {
194 LOG(error) << getNPhiBins() << " phi bins were already merged to " << getNPhiSlices() << " slices";
195 return;
196 }
197 int newSl = 0;
198 std::vector<int> phi2SlNew(getNPhiBins());
199 for (int i = 0; i < getNPhiBins(); i++) {
200 phi2SlNew[i] = mPhiBin2Slice[i];
201 }
202 for (int is = 1; is < getNPhiSlices(); is++) {
203 if (!canMergePhiSlices(is - 1, is, maxRelDiff)) {
204 newSl++;
205 } else {
206 mPhiBin2Slice[is] = mPhiBin2Slice[is - 1];
207 }
208 phi2SlNew[is] = newSl; // new numbering
209 }
210 if (newSl + 1 == getNPhiSlices()) {
211 return;
212 }
213 newSl = 0;
214 int slMin = 0, slMax = 0, is = 0;
215 while (is++ < getNPhiSlices()) {
216 while (is < getNPhiSlices() && phi2SlNew[is] == newSl) { // select similar slices
217 slMax++;
218 is++;
219 }
220 if (slMax > slMin || newSl != slMin) { // merge or shift slices
221 mSliceCos[newSl] = mSliceCos[slMin];
222 mSliceSin[newSl] = mSliceSin[slMin];
223 float norm = 1.f / (1.f + slMax - slMin);
224 for (int iz = getNZBins(); iz--;) {
225 int iDest = newSl * getNZBins() + iz, iSrc = slMin * getNZBins() + iz;
226 mCells[iDest] = mCells[iSrc];
227 for (int ism = slMin + 1; ism <= slMax; ism++) {
228 iSrc = ism * getNZBins() + iz;
229 mCells[iDest].meanX2X0 += mCells[iSrc].meanX2X0;
230 mCells[iDest].meanRho += mCells[iSrc].meanRho;
231 }
232 mCells[iDest].scale(norm);
233 }
234 LOG(info) << "mapping " << slMin << ":" << slMax << " to new slice " << newSl;
235 }
236 newSl++;
237 slMin = slMax = is;
238 }
239 for (int i = 0; i < getNPhiBins(); i++) {
240 mPhiBin2Slice[i] = phi2SlNew[i];
241 }
242 mNPhiSlices = newSl;
243
244 // relocate arrays to avoid spaces after optimization
245 // mSliceCos pointer does not change, but sliceSin needs to be relocated
246 auto offs = alignSize(newSl * sizeof(float), getBufferAlignmentBytes());
247 char* dst = ((char*)mSliceCos) + offs; // account for alignment
248 o2::gpu::resizeArray(mSliceSin, getNPhiBins(), newSl, reinterpret_cast<float*>(dst));
249 // adjust mCells array
250 dst = ((char*)mSliceSin) + offs; // account for alignment
251 o2::gpu::resizeArray(mCells, getNPhiBins() * getNZBins(), newSl * getNZBins(), reinterpret_cast<MatCell*>(dst));
253 LOG(info) << "Updated Nslices = " << getNPhiSlices();
254}
255
256//________________________________________________________________________________
258{
259 // mean and RMS over layer
260 mean.meanRho = rms.meanRho = 0.f;
261 mean.meanX2X0 = rms.meanX2X0 = 0.f;
262 for (int ip = getNPhiBins(); ip--;) {
263 for (int iz = getNZBins(); iz--;) {
264 const auto& cell = getCellPhiBin(ip, iz);
265 mean.meanRho += cell.meanRho;
266 mean.meanX2X0 += cell.meanX2X0;
267 rms.meanRho += cell.meanRho * cell.meanRho;
268 rms.meanX2X0 += cell.meanX2X0 * cell.meanX2X0;
269 }
270 }
271 int nc = getNPhiBins() * getNZBins();
272 mean.meanRho /= nc;
273 mean.meanX2X0 /= nc;
274 rms.meanRho /= nc;
275 rms.meanX2X0 /= nc;
276 rms.meanRho -= mean.meanRho * mean.meanRho;
277 rms.meanX2X0 -= mean.meanX2X0 * mean.meanX2X0;
278 rms.meanRho = rms.meanRho > 0.f ? o2::math_utils::sqrt(rms.meanRho) : 0.f;
279 rms.meanX2X0 = rms.meanX2X0 > 0.f ? o2::math_utils::sqrt(rms.meanX2X0) : 0.f;
280}
281
282//________________________________________________________________________________
283void MatLayerCyl::print(bool data) const
284{
286 float szkb = float(getFlatBufferSize()) / 1024;
287 printf("Cyl.Layer %.3f<r<%.3f %+.3f<Z<%+.3f | Nphi: %5d (%d slices) Nz: %5d Size: %.3f KB\n",
288 getRMin(), getRMax(), getZMin(), getZMax(), getNPhiBins(), getNPhiSlices(), getNZBins(), szkb);
289 if (!data) {
290 return;
291 }
292 for (int ip = 0; ip < getNPhiSlices(); ip++) {
293 int ib0, ib1;
294 int nb = getNPhiBinsInSlice(ip, ib0, ib1);
295 printf("phi slice: %d (%d bins %d-%d %.4f:%.4f) sn:%+.4f/cs:%+.4f ... [iz/<rho>/<x/x0>] \n",
296 ip, nb, ib0, ib1, getDPhi() * ib0, getDPhi() * (ib1 + 1), getSliceSin(ip), getSliceCos(ip));
297 for (int iz = 0; iz < getNZBins(); iz++) {
298 auto cell = getCellPhiBin(ib0, iz);
299 printf("%3d/%.2e/%.2e ", iz, cell.meanRho, cell.meanX2X0);
300 if (((iz + 1) % 5) == 0) {
301 printf("\n");
302 }
303 }
304 if (getNZBins() % 5) {
305 printf("\n");
306 }
307 }
308}
309
310//________________________________________________________________________________
311void MatLayerCyl::flatten(char* newPtr)
312{
313 // make object flat: move all content to single internally allocated buffer
314 assert(mConstructionMask == InProgress);
317 delete[] old;
318 mFlatBufferContainer = nullptr;
320}
321
322#endif // ! GPUCA_ALIGPUCODE
323
324#ifndef GPUCA_GPUCODE
325//________________________________________________________________________________
326void MatLayerCyl::fixPointers(char* oldPtr, char* newPtr)
327{
328 // fix pointers on the internal structure of the flat buffer after retrieving it from the file
332 mCells = flatObject::relocatePointer(oldPtr, newPtr, mCells);
333}
334#endif // ! GPUCA_GPUCODE
335
336//________________________________________________________________________________
337GPUd() int MatLayerCyl::getNPhiBinsInSlice(int iSlice, int& binMin, int& binMax) const
338{
339 // slow method to get number of phi bins for given phi slice
340 int nb = 0;
341 binMin = binMax = -1;
342 for (int ib = getNPhiBins(); ib--;) {
343 if (phiBin2Slice(ib) == iSlice) {
344 binMax < 0 ? binMin = binMax = ib : binMin = ib;
345 nb++;
346 continue;
347 }
348 if (binMax >= 0) {
349 break; // no more bins since they are consecutive
350 }
351 }
352 return nb;
353}
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)
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.
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)
short mNZBins
number of Z bins
float mRMax2
squared max r
void fixPointers(char *oldPtr, char *newPtr)
float mDPhiInv
phi slice thickness inverse
void populateFromTGeo(int ntrPerCell=10)
bool canMergePhiSlices(int i, int j, float maxRelDiff=0.05, int maxDifferent=1) const
GPUCA_GPUCODE.
Definition FlatObject.h:176
uint32_t mConstructionMask
mask for constructed object members, first two bytes are used by this class
Definition FlatObject.h:323
int32_t mFlatBufferSize
size of the flat buffer
Definition FlatObject.h:322
char * mFlatBufferContainer
Definition FlatObject.h:324
static size_t alignSize(size_t sizeBytes, size_t alignmentBytes)
_______________ Generic utilities _______________________________________________
Definition FlatObject.h:277
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:285
size_t getFlatBufferSize() const
Gives size of the flat buffer.
Definition FlatObject.h:256
@ InProgress
construction started: temporary memory is reserved
Definition FlatObject.h:319
@ NotConstructed
the object is not constructed
Definition FlatObject.h:317
@ Constructed
the object is constructed, temporary memory is released
Definition FlatObject.h:318
GLenum GLenum dst
Definition glcorearb.h:1767
GLboolean * data
Definition glcorearb.h:298
constexpr float TwoPI
constexpr float PI
T * resizeArray(T *&ptr, int32_t oldSize, int32_t newSize, T *newPtr=nullptr)
Definition FlatObject.h:121
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"