Project
Loading...
Searching...
No Matches
SplineSpec.h
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
16
17#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINESPEC_H
18#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINESPEC_H
19
20#include "Spline1D.h"
21#include "FlatObject.h"
22#include "GPUCommonDef.h"
23#include "SplineUtil.h"
24
25#if !defined(__ROOTCLING__) && !defined(GPUCA_GPUCODE) && !defined(GPUCA_NO_VC)
26#include <Vc/Vc>
27#include <Vc/SimdArray>
28#endif
29
30class TFile;
31
32namespace o2
33{
34namespace gpu
35{
36
46template <typename DataT>
48{
49 public:
51 typedef typename Spline1D<DataT>::Knot Knot;
52
54
56 GPUd() static constexpr int32_t getVersion() { return (1 << 16) + Spline1D<DataT>::getVersion(); }
57
59
61 SplineContainer() = default;
62
65
67 ~SplineContainer() = default;
68
70
71#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE)
73 void approximateFunction(const double xMin[/* mXdim */], const double xMax[/* mXdim */],
74 std::function<void(const double x[/* mXdim */], double f[/*mYdim*/])> F,
75 const int32_t nAuxiliaryDataPoints[/* mXdim */] = nullptr);
76#endif
77
79
80#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE)
82 int32_t writeToFile(TFile& outf, const char* name);
83
85 static SplineContainer* readFromFile(TFile& inpf, const char* name);
86#endif
87
89
91 GPUd() int32_t getXdimensions() const { return mXdim; }
92
94 GPUd() int32_t getYdimensions() const { return mYdim; }
95
97 GPUd() static constexpr size_t getParameterAlignmentBytes() { return 16; }
98
100 GPUd() int32_t getNumberOfParameters() const { return this->calcNumberOfParameters(mYdim); }
101
103 GPUd() size_t getSizeOfParameters() const { return sizeof(DataT) * this->getNumberOfParameters(); }
104
106 GPUd() int32_t getNumberOfKnots() const { return mNknots; }
107
109 GPUd() int32_t getNumberOfParametersPerKnot() const { return calcNumberOfParametersPerKnot(mYdim); }
110
112 GPUd() const Spline1D<DataT>& getGrid(int32_t dimX) const { return mGrid[dimX]; }
113
115 GPUd() void getKnotU(int32_t iKnot, int32_t u[/* mXdim */]) const;
116
118 GPUd() int32_t getKnotIndex(const int32_t iKnot[/* mXdim */]) const;
119
121 GPUd() DataT* getParameters() { return mParameters; }
122
124 GPUd() const DataT* getParameters() const { return mParameters; }
125
127
129 GPUd() size_t getGridOffset(int32_t dimX) const { return mGrid[dimX].getFlatBufferPtr() - mFlatBufferPtr; }
130
132 GPUd() void setXrange(const DataT xMin[/* mXdim */], const DataT xMax[/* mXdim */]);
133
135 void print() const;
136
138
140 GPUd() int32_t calcNumberOfParameters(int32_t nYdim) const
141 {
142 return calcNumberOfParametersPerKnot(nYdim) * getNumberOfKnots();
143 }
144
146 GPUd() int32_t calcNumberOfParametersPerKnot(int32_t nYdim) const
147 {
148 return (1 << mXdim) * nYdim; // 2^mXdim parameters per Y dimension
149 }
150
152
153#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE) // code invisible on GPU and in the standalone compilation
155 static int32_t test(const bool draw = 0, const bool drawDataPoints = 1);
156#endif
157
159
162
163#if !defined(GPUCA_GPUCODE)
164 void cloneFromObject(const SplineContainer& obj, char* newFlatBufferPtr);
165 void moveBufferTo(char* newBufferPtr);
166#endif
167
169
170 void destroy();
171 void setActualBufferAddress(char* actualFlatBufferPtr);
172 void setFutureBufferAddress(char* futureFlatBufferPtr);
173
174 protected:
175#if !defined(GPUCA_GPUCODE)
177 void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */]);
178
180 void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */], const int32_t* const knotU[/* nXdim */]);
181#endif
182
184
185 int32_t mXdim = 0;
186 int32_t mYdim = 0;
187 int32_t mNknots = 0;
188
190 DataT* mParameters;
191
193};
194
195template <typename DataT>
196GPUdi() void SplineContainer<DataT>::getKnotU(int32_t iKnot, int32_t u[/* mXdim */]) const
197{
199 for (int32_t dim = 0; dim < mXdim; dim++) {
200 int32_t n = mGrid[dim].getNumberOfKnots();
201 u[dim] = mGrid[dim].getKnot(iKnot % n).getU();
202 iKnot /= n;
203 }
204}
205
206template <typename DataT>
207GPUdi() int32_t SplineContainer<DataT>::getKnotIndex(const int32_t iKnot[/* mXdim */]) const
208{
210 int32_t ind = iKnot[0];
211 int32_t n = 1;
212 for (int32_t dim = 1; dim < mXdim; dim++) {
213 n *= mGrid[dim - 1].getNumberOfKnots();
214 ind += n * iKnot[dim];
215 }
216 return ind;
217}
218
219template <typename DataT>
220GPUdi() void SplineContainer<DataT>::
221 setXrange(const DataT xMin[/* mXdim */], const DataT xMax[/* mXdim */])
222{
224 for (int32_t i = 0; i < mXdim; i++) {
225 mGrid[i].setXrange(xMin[i], xMax[i]);
226 }
227}
228
251template <typename DataT, int32_t XdimT, int32_t YdimT, int32_t SpecT>
253
258template <typename DataT, int32_t XdimT, int32_t YdimT>
259class SplineSpec<DataT, XdimT, YdimT, 0> : public SplineContainer<DataT>
260{
262
263 public:
265 typedef typename TBase::Knot Knot;
266
268
270 GPUd() void interpolate(const DataT x[/*mXdim*/], GPUgeneric() DataT S[/*mYdim*/]) const
271 {
272 const auto nXdimTmp = SplineUtil::getNdim<XdimT>(mXdim);
273 const auto nXdim = nXdimTmp.get();
274 const auto maxXdimTmp = SplineUtil::getMaxNdim<XdimT>(mXdim);
275 DataT u[maxXdimTmp.get()];
276 for (int32_t i = 0; i < nXdim; i++) {
277 u[i] = mGrid[i].convXtoU(x[i]);
278 }
279 interpolateU<SafetyLevel::kSafe>(mXdim, mYdim, mParameters, u, S);
280 }
281
283 template <SafetyLevel SafeT = SafetyLevel::kSafe>
284 GPUd() void interpolateU(int32_t inpXdim, int32_t inpYdim, GPUgeneric() const DataT Parameters[],
285 const DataT u[/*inpXdim*/], GPUgeneric() DataT S[/*inpYdim*/]) const
286 {
287 const auto nXdimTmp = SplineUtil::getNdim<XdimT>(mXdim);
288 const auto nXdim = nXdimTmp.get();
289 const auto maxXdimTmp = SplineUtil::getMaxNdim<XdimT>(mXdim);
290 const auto maxXdim = maxXdimTmp.get();
291 const auto nYdimTmp = SplineUtil::getNdim<YdimT>(mYdim);
292 const auto nYdim = nYdimTmp.get();
293 const auto maxYdimTmp = SplineUtil::getMaxNdim<XdimT>(mYdim);
294 const auto maxYdim = maxYdimTmp.get();
295
296 // const auto nParameters = 1 << (2 * nXdim); //total Nr of Parameters necessary for one interpolation
297 const auto nKnotParametersPerY = 1 << nXdim; // Nr of Parameters per Knot per Y dimension
298 const auto nKnotParameters = (1 << nXdim) * nYdim; // Nr of Parameters per Knot
299
300 DataT iParameters[(1 << (2 * maxXdim)) * maxYdim]; // Array for all parameters
301
302 //get the indices of the "most left" Knot:
303
304 int32_t indices[maxXdim]; // indices of the 'most left' knot
305 for (int32_t i = 0; i < nXdim; i++) {
306 indices[i] = mGrid[i].getLeftKnotIndexForU(u[i]);
307 }
308 // get all the needed parameters into one array iParameters[nParameters]:
309 int32_t indicestmp[maxXdim];
310 for (int32_t i = 0; i < nKnotParametersPerY; i++) { // for every necessary Knot
311 for (int32_t k = 0; k < nXdim; k++) {
312 indicestmp[k] = indices[k] + (i / (1 << k)) % 2; //get the knot-indices in every dimension (mirrored order binary counting)
313 }
314 int32_t index = TBase::getKnotIndex(indicestmp); // get index of the current Knot
315
316 for (int32_t j = 0; j < nKnotParameters; j++) { // and fill the iparameter array with according parameters
317 iParameters[i * nKnotParameters + j] = Parameters[index * nKnotParameters + j];
318 }
319 }
320 //now start with the interpolation loop:
321
322 constexpr auto maxInterpolations = (1 << (2 * maxXdim - 2)) * maxYdim;
323
324 DataT S0[maxInterpolations];
325 DataT D0[maxInterpolations];
326 DataT S1[maxInterpolations];
327 DataT D1[maxInterpolations];
328
329 int32_t nInterpolations = (1 << (2 * nXdim - 2)) * nYdim;
330 int32_t nKnots = 1 << (nXdim);
331
332 for (int32_t d = 0; d < nXdim; d++) { // for every dimension
333 DataT* pointer[4] = {S0, D0, S1, D1}; // pointers for interpolation arrays S0, D0, S1, D1 point to Arraystart
334 for (int32_t i = 0; i < nKnots; i++) { // for every knot
335 for (int32_t j = 0; j < nKnots; j++) { // for every parametertype
336 int32_t pointernr = 2 * (i % 2) + (j % 2); // to which array should it be delivered
337 for (int32_t k = 0; k < nYdim; k++) {
338 pointer[pointernr][0] = iParameters[(i * nKnots + j) * nYdim + k];
339 pointer[pointernr]++;
340 }
341 } // end for j (every parametertype)
342 } // end for i (every knot)
343
344 const typename Spline1D<DataT>::Knot& knotL = mGrid[d].getKnot(indices[d]);
345 DataT coordinate = u[d];
346 typedef Spline1DSpec<DataT, 0, 0> TGridX;
347 const TGridX& gridX = *((const TGridX*)&(mGrid[d]));
348 gridX.interpolateU(nInterpolations, knotL, S0, D0, S1, D1, coordinate, iParameters);
349 nInterpolations /= 4;
350 nKnots /= 2;
351 } // end d (every dimension)
352
353 for (int32_t i = 0; i < nYdim; i++) {
354 S[i] = iParameters[i]; // write into result-array
355 // LOG(info)<<iParameters[i] <<", ";
356 }
357 } // end interpolateU
358
359 protected:
360 using TBase::mGrid;
361 using TBase::mParameters;
362 using TBase::mXdim;
363 using TBase::mYdim;
364 using TBase::TBase; // inherit constructors and hide them
365};
366
371template <typename DataT, int32_t XdimT, int32_t YdimT>
372class SplineSpec<DataT, XdimT, YdimT, 1>
373 : public SplineSpec<DataT, XdimT, YdimT, 0>
374{
377
378 public:
380
381#if !defined(GPUCA_GPUCODE)
383 SplineSpec() : SplineSpec(nullptr) {}
384
386 SplineSpec(const int32_t nKnots[/*XdimT*/]) : TBase()
387 {
388 recreate(nKnots);
389 }
391 SplineSpec(const int32_t nKnots[/*XdimT*/], const int32_t* const knotU[/*XdimT*/])
392 : TBase()
393 {
394 recreate(nKnots, knotU);
395 }
398 {
399 TBase::cloneFromObject(v, nullptr);
400 }
402 void recreate(const int32_t nKnots[/*XdimT*/])
403 {
404 TBase::recreate(XdimT, YdimT, nKnots);
405 }
406
408 void recreate(const int32_t nKnots[/*XdimT*/], const int32_t* const knotU[/*XdimT*/])
409 {
410 TBase::recreate(XdimT, YdimT, nKnots, knotU);
411 }
412#endif
413
415 GPUd() constexpr int32_t getXdimensions() const { return XdimT; }
416
418 GPUd() constexpr int32_t getYdimensions() const { return YdimT; }
419
421
423 template <SafetyLevel SafeT = SafetyLevel::kSafe>
424 GPUd() void interpolateU(GPUgeneric() const DataT Parameters[],
425 const DataT u[/*XdimT*/], GPUgeneric() DataT S[/*YdimT*/]) const
426 {
427 TBase::template interpolateU<SafeT>(XdimT, YdimT, Parameters, u, S);
428 }
429
431 private:
432#if !defined(GPUCA_GPUCODE)
433 using TBase::recreate;
434#endif
435 using TBase::interpolateU;
436};
437
442template <typename DataT, int32_t XdimT, int32_t YdimT>
443class SplineSpec<DataT, XdimT, YdimT, 2>
444 : public SplineSpec<DataT, XdimT, YdimT, 0>
445{
448
449 public:
451
452#if !defined(GPUCA_GPUCODE)
454 SplineSpec() : SplineSpec((XdimT > 0 ? XdimT : 0), (YdimT > 0 ? YdimT : 0), nullptr) {}
455
457 SplineSpec(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */]) : TBase()
458 {
459 this->recreate(nXdim, nYdim, nKnots);
460 }
461
463 SplineSpec(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */], const int32_t* const knotU[/* nXdim */])
464 : TBase()
465 {
466 this->recreate(nXdim, nYdim, nKnots, knotU);
467 }
468
471 {
472 cloneFromObject(v, nullptr);
473 }
474
476 void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */])
477 {
478 checkDimensions(nXdim, nYdim);
479 TBase::recreate(nXdim, nYdim, nKnots);
480 }
481
483 void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[/* nXdim */], const int32_t* const knotU[/* nXdim */])
484 {
485 checkDimensions(nXdim, nYdim);
486 TBase::recreate(nXdim, nYdim, nKnots, knotU);
487 }
488
489#endif
490
492
493 using TBase::interpolateU;
494
496 void checkDimensions(int32_t& nXdim, int32_t& nYdim)
497 {
498 if (XdimT > 0 && nXdim != XdimT) {
499 assert(0);
500 nXdim = XdimT;
501 }
502 if (XdimT < 0 && nXdim > abs(XdimT)) {
503 assert(0);
504 nXdim = abs(XdimT);
505 }
506 if (nXdim < 0) {
507 assert(0);
508 nXdim = 0;
509 }
510 if (YdimT > 0 && nYdim != YdimT) {
511 assert(0);
512 nYdim = YdimT;
513 }
514 if (YdimT < 0 && nYdim > abs(YdimT)) {
515 assert(0);
516 nYdim = abs(YdimT);
517 }
518 if (nYdim < 0) {
519 assert(0);
520 nYdim = 0;
521 }
522 }
523};
524
528template <typename DataT, int32_t XdimT>
529class SplineSpec<DataT, XdimT, 1, 3>
530 : public SplineSpec<DataT, XdimT, 1, SplineUtil::getSpec(XdimT, 999)>
531{
532 typedef SplineSpec<DataT, XdimT, 1, SplineUtil::getSpec(XdimT, 999)> TBase;
533
534 public:
535 using TBase::TBase; // inherit constructors
536
538 GPUd() DataT interpolate(const DataT x[]) const
539 {
540 DataT S = 0.;
541 TBase::interpolate(x, &S);
542 return S;
543 }
544
545 // this parent method should be public anyhow,
546 // but the compiler gets confused w/o this extra declaration
547 using TBase::interpolate;
548};
549
550} // namespace gpu
551} // namespace o2
552
553#endif
Definition of FlatObject class.
int32_t i
#define GPUgeneric()
uint32_t j
Definition RawData.h:0
Definition of Spline1D class.
GPUCA_GPUCODE.
Definition FlatObject.h:176
char * releaseInternalBuffer()
_____________ Methods for making the data buffer external __________________________
Definition FlatObject.h:526
static constexpr size_t getBufferAlignmentBytes()
Gives minimal alignment in bytes required for the flat buffer.
Definition FlatObject.h:197
static constexpr size_t getClassAlignmentBytes()
_____________ Memory alignment __________________________
Definition FlatObject.h:194
SafetyLevel
Named enumeration for the safety level used by some methods.
GPUd() void setXrange(const DataT xMin[]
Set X range.
SplineContainer()=default
_____________ C++ constructors / destructors __________________________
GPUd() int32_t getXdimensions() const
_______________ Getters ________________________
Definition SplineSpec.h:91
int32_t mYdim
dimentionality of Y
Definition SplineSpec.h:186
GPUd() size_t getGridOffset(int32_t dimX) const
_______________ Technical stuff ________________________
Definition SplineSpec.h:129
~SplineContainer()=default
Destructor.
GPUd() int32_t getNumberOfKnots() const
Get a number of knots.
Definition SplineSpec.h:106
int32_t mNknots
number of spline knots
Definition SplineSpec.h:187
Spline1D< DataT >::SafetyLevel SafetyLevel
Definition SplineSpec.h:50
GPUd() size_t getSizeOfParameters() const
Size of the parameter array in bytes.
Definition SplineSpec.h:103
int32_t writeToFile(TFile &outf, const char *name)
_______________ IO ________________________
void cloneFromObject(const SplineContainer &obj, char *newFlatBufferPtr)
static SplineContainer * readFromFile(TFile &inpf, const char *name)
read a class object from the file
ClassDefNV(SplineContainer, 1)
(transient!!) F-dependent parameters of the spline
void moveBufferTo(char *newBufferPtr)
GPUd() static const expr int32_t getVersion()
_____________ Version control __________________________
Definition SplineSpec.h:56
void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[])
Constructor for a regular spline.
Spline1D< DataT > * mGrid
Definition SplineSpec.h:189
void setActualBufferAddress(char *actualFlatBufferPtr)
void setFutureBufferAddress(char *futureFlatBufferPtr)
GPUd() int32_t getNumberOfParametersPerKnot() const
Number of parameters per knot.
Definition SplineSpec.h:109
int32_t mXdim
_____________ Data members ____________
Definition SplineSpec.h:185
GPUd() const Spline1D< DataT > &getGrid(int32_t dimX) const
Get 1-D grid for dimX dimension.
Definition SplineSpec.h:112
DataT * mParameters
(transient!!) mXdim grids
Definition SplineSpec.h:190
GPUd() int32_t getNumberOfParameters() const
Number of parameters.
Definition SplineSpec.h:100
void print() const
Print method.
GPUd() int32_t getYdimensions() const
Get number of Y dimensions.
Definition SplineSpec.h:94
SplineContainer(const SplineContainer &)=delete
Disable all other constructors.
void approximateFunction(const double xMin[], const double xMax[], std::function< void(const double x[], double f[])> F, const int32_t nAuxiliaryDataPoints[]=nullptr)
_______________ Construction interface ________________________
GPUd() const DataT *getParameters() const
Get spline parameters const.
Definition SplineSpec.h:124
Spline1D< DataT >::Knot Knot
Definition SplineSpec.h:51
GPUd() int32_t calcNumberOfParametersPerKnot(int32_t nYdim) const
Number of parameters per knot.
Definition SplineSpec.h:146
GPUd() static const expr size_t getParameterAlignmentBytes()
Get minimal required alignment for the spline parameters.
Definition SplineSpec.h:97
GPUd() DataT interpolate(const DataT x[]) const
Simplified interface for 1D: return the interpolated value.
Definition SplineSpec.h:538
GPUd() void interpolate(const DataT x[]
_______________ Interpolation math ________________________
GPUd() void interpolateU(int32_t inpXdim
Get interpolated value for S(u):inpXdim->inpYdim using spline parameters Parameters.
GPUd() const expr int32_t getYdimensions() const
Get number of Y dimensions.
Definition SplineSpec.h:418
GPUd() void interpolateU(GPUgeneric() const DataT Parameters[]
_______ Expert tools: interpolation with given nYdim and external Parameters _______
void recreate(const int32_t nKnots[], const int32_t *const knotU[])
Constructor for an irregular spline.
Definition SplineSpec.h:408
GPUd() const expr int32_t getXdimensions() const
Get number of X dimensions.
Definition SplineSpec.h:415
SplineSpec(const int32_t nKnots[])
Constructor for a regular spline.
Definition SplineSpec.h:386
SplineSpec(const SplineSpec &v)
Copy constructor.
Definition SplineSpec.h:397
void recreate(const int32_t nKnots[])
Constructor for a regular spline.
Definition SplineSpec.h:402
SplineSpec(const int32_t nKnots[], const int32_t *const knotU[])
Constructor for an irregular spline.
Definition SplineSpec.h:391
SplineSpec(int32_t nXdim, int32_t nYdim, const int32_t nKnots[])
Constructor for a regular spline.
Definition SplineSpec.h:457
SplineSpec(const SplineSpec &v)
Copy constructor.
Definition SplineSpec.h:470
void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[], const int32_t *const knotU[])
Constructor for an irregular spline.
Definition SplineSpec.h:483
SplineSpec(int32_t nXdim, int32_t nYdim, const int32_t nKnots[], const int32_t *const knotU[])
Constructor for an irregular spline.
Definition SplineSpec.h:463
void recreate(int32_t nXdim, int32_t nYdim, const int32_t nKnots[])
Constructor for a regular spline.
Definition SplineSpec.h:476
void checkDimensions(int32_t &nXdim, int32_t &nYdim)
Check dimensions.
Definition SplineSpec.h:496
static constexpr int32_t getSpec(int32_t nXdim, int32_t nYdim)
Definition SplineUtil.h:33
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum void ** pointer
Definition glcorearb.h:805
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLsizei GLenum const void * indices
Definition glcorearb.h:400
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GPUdi() o2
Definition TrackTRD.h:38
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...