File indexing completed on 2026-07-26 09:28:20
0001
0002
0003
0004 #ifndef VECGEOM_BASE_SOA3D_H_
0005 #define VECGEOM_BASE_SOA3D_H_
0006
0007 #include "VecGeom/base/Cuda.h"
0008 #include "VecGeom/base/Global.h"
0009
0010 #include "VecGeom/base/Container3D.h"
0011 #include "VecGeom/backend/scalar/Backend.h"
0012 #ifdef VECGEOM_CUDA_INTERFACE
0013 #include "VecGeom/backend/cuda/Interface.h"
0014 #endif
0015
0016 #include <fstream>
0017
0018 namespace vecgeom {
0019
0020 VECGEOM_DEVICE_FORWARD_DECLARE(template <typename Type> class SOA3D;);
0021
0022 inline namespace VECGEOM_IMPL_NAMESPACE {
0023
0024
0025
0026
0027 #if __GNUC__ < 3 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)
0028
0029 #pragma GCC diagnostic push
0030 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
0031 #pragma GCC diagnostic ignored "-Weffc++"
0032 #define GCC_DIAG_POP_NEEDED
0033 #endif
0034
0035 template <typename T>
0036 class SOA3D : Container3D<SOA3D<T>> {
0037
0038 private:
0039 bool fAllocated = false;
0040 size_t fSize = 0, fCapacity = 0;
0041 T *fX = nullptr, *fY = nullptr, *fZ = nullptr;
0042
0043 public:
0044 typedef T value_type;
0045
0046 VECCORE_ATT_HOST_DEVICE
0047 SOA3D(T *x, T *y, T *z, size_t size);
0048
0049 VECCORE_ATT_HOST_DEVICE
0050 SOA3D(size_t size);
0051
0052
0053
0054
0055
0056 VECCORE_ATT_HOST_DEVICE
0057 SOA3D(size_t size, AlignedAllocator &a);
0058
0059 SOA3D(SOA3D<T> const &other);
0060
0061 SOA3D() = default;
0062
0063 VECCORE_ATT_HOST_DEVICE
0064 SOA3D &operator=(SOA3D<T> const &other);
0065
0066 VECCORE_ATT_HOST_DEVICE
0067 ~SOA3D();
0068
0069
0070
0071
0072 VECCORE_ATT_HOST_DEVICE
0073 VECGEOM_FORCE_INLINE
0074 static size_t aligned_sizeof_data(size_t initSize);
0075
0076 VECCORE_ATT_HOST_DEVICE
0077 VECGEOM_FORCE_INLINE
0078 size_t size() const;
0079
0080 VECCORE_ATT_HOST_DEVICE
0081 VECGEOM_FORCE_INLINE
0082 size_t capacity() const;
0083
0084 VECCORE_ATT_HOST_DEVICE
0085 VECGEOM_FORCE_INLINE
0086 void resize(size_t newSize);
0087
0088 VECCORE_ATT_HOST_DEVICE
0089 VECGEOM_FORCE_INLINE
0090 void reserve(size_t newCapacity);
0091
0092 VECGEOM_FORCE_INLINE
0093 void clear();
0094
0095
0096
0097 VECCORE_ATT_HOST_DEVICE
0098 VECGEOM_FORCE_INLINE
0099 Vector3D<T> operator[](size_t index) const;
0100
0101 VECCORE_ATT_HOST_DEVICE
0102 VECGEOM_FORCE_INLINE
0103 T x(size_t index) const;
0104
0105 VECCORE_ATT_HOST_DEVICE
0106 VECGEOM_FORCE_INLINE
0107 T &x(size_t index);
0108
0109 VECCORE_ATT_HOST_DEVICE
0110 VECGEOM_FORCE_INLINE
0111 T *x();
0112
0113 VECCORE_ATT_HOST_DEVICE
0114 VECGEOM_FORCE_INLINE
0115 T const *x() const;
0116
0117 VECCORE_ATT_HOST_DEVICE
0118 VECGEOM_FORCE_INLINE
0119 T y(size_t index) const;
0120
0121 VECCORE_ATT_HOST_DEVICE
0122 VECGEOM_FORCE_INLINE
0123 T &y(size_t index);
0124
0125 VECCORE_ATT_HOST_DEVICE
0126 VECGEOM_FORCE_INLINE
0127 T *y();
0128
0129 VECCORE_ATT_HOST_DEVICE
0130 VECGEOM_FORCE_INLINE
0131 T const *y() const;
0132
0133 VECCORE_ATT_HOST_DEVICE
0134 VECGEOM_FORCE_INLINE
0135 T z(size_t index) const;
0136
0137 VECCORE_ATT_HOST_DEVICE
0138 VECGEOM_FORCE_INLINE
0139 T &z(size_t index);
0140
0141 VECCORE_ATT_HOST_DEVICE
0142 VECGEOM_FORCE_INLINE
0143 T *z();
0144
0145 VECCORE_ATT_HOST_DEVICE
0146 VECGEOM_FORCE_INLINE
0147 T const *z() const;
0148
0149
0150
0151 VECCORE_ATT_HOST_DEVICE
0152 VECGEOM_FORCE_INLINE
0153 void set(size_t index, T x, T y, T z);
0154
0155 VECCORE_ATT_HOST_DEVICE
0156 VECGEOM_FORCE_INLINE
0157 void set(size_t index, Vector3D<T> const &vec);
0158
0159 VECCORE_ATT_HOST_DEVICE
0160 VECGEOM_FORCE_INLINE
0161 void push_back(T x, T y, T z);
0162
0163 VECCORE_ATT_HOST_DEVICE
0164 VECGEOM_FORCE_INLINE
0165 void push_back(Vector3D<T> const &vec);
0166
0167 #ifdef VECGEOM_CUDA_INTERFACE
0168 DevicePtr<cuda::SOA3D<T>> CopyToGpu(DevicePtr<T> xGpu, DevicePtr<T> yGpu, DevicePtr<T> zGpu) const;
0169 DevicePtr<cuda::SOA3D<T>> CopyToGpu(DevicePtr<T> xGpu, DevicePtr<T> yGpu, DevicePtr<T> zGpu, size_t size) const;
0170 #endif
0171
0172 void ToFile(std::string ) const;
0173 int FromFile(std::string );
0174
0175 private:
0176 VECCORE_ATT_HOST_DEVICE
0177 void Allocate();
0178
0179 VECCORE_ATT_HOST_DEVICE
0180 void Deallocate();
0181 };
0182
0183 #if defined(GCC_DIAG_POP_NEEDED)
0184
0185 #pragma GCC diagnostic pop
0186 #undef GCC_DIAG_POP_NEEDED
0187
0188 #endif
0189
0190 template <typename T>
0191 VECCORE_ATT_HOST_DEVICE SOA3D<T>::SOA3D(T *xval, T *yval, T *zval, size_t sz)
0192 : fAllocated(false), fSize(sz), fCapacity(fSize), fX(xval), fY(yval), fZ(zval)
0193 {
0194 }
0195
0196 template <typename T>
0197 VECCORE_ATT_HOST_DEVICE SOA3D<T>::SOA3D(size_t initSize, AlignedAllocator &a)
0198 : fAllocated(false), fSize(initSize), fCapacity(initSize)
0199 {
0200 fX = a.aligned_alloc<T>(initSize, kAlignmentBoundary);
0201 fY = a.aligned_alloc<T>(initSize, kAlignmentBoundary);
0202 fZ = a.aligned_alloc<T>(initSize, kAlignmentBoundary);
0203 }
0204
0205 template <typename T>
0206 VECCORE_ATT_HOST_DEVICE VECGEOM_FORCE_INLINE size_t SOA3D<T>::aligned_sizeof_data(size_t initSize)
0207 {
0208
0209 return 3 * AlignedAllocator::aligned_sizeof<T>(initSize, kAlignmentBoundary);
0210 }
0211
0212 template <typename T>
0213 VECCORE_ATT_HOST_DEVICE SOA3D<T>::SOA3D(size_t sz) : fSize(sz), fCapacity(sz)
0214 {
0215 Allocate();
0216 }
0217
0218 template <typename T>
0219 SOA3D<T>::SOA3D(SOA3D<T> const &rhs) : fAllocated(false), fSize(rhs.fSize), fCapacity(rhs.fCapacity)
0220 {
0221 if (rhs.fAllocated) {
0222 Allocate();
0223 copy(rhs.fX, rhs.fX + rhs.fSize, fX);
0224 copy(rhs.fY, rhs.fY + rhs.fSize, fY);
0225 copy(rhs.fZ, rhs.fZ + rhs.fSize, fZ);
0226 } else {
0227 fX = rhs.fX;
0228 fY = rhs.fY;
0229 fZ = rhs.fZ;
0230 }
0231 }
0232
0233 template <typename T>
0234 VECCORE_ATT_HOST_DEVICE SOA3D<T> &SOA3D<T>::operator=(SOA3D<T> const &rhs)
0235 {
0236 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0237 fSize = rhs.fSize;
0238 fCapacity = rhs.fCapacity;
0239 Deallocate();
0240 if (rhs.fAllocated && rhs.fSize > 0) {
0241 Allocate();
0242 copy(rhs.fX, rhs.fX + rhs.fSize, fX);
0243 copy(rhs.fY, rhs.fY + rhs.fSize, fY);
0244 copy(rhs.fZ, rhs.fZ + rhs.fSize, fZ);
0245 } else {
0246 fX = rhs.fX;
0247 fY = rhs.fY;
0248 fZ = rhs.fZ;
0249 }
0250 #else
0251 fAllocated = false;
0252 fSize = rhs.fSize;
0253 fCapacity = rhs.fCapacity;
0254 fX = rhs.fX;
0255 fY = rhs.fY;
0256 fZ = rhs.fZ;
0257 #endif
0258 return *this;
0259 }
0260
0261 template <typename T>
0262 VECCORE_ATT_HOST_DEVICE SOA3D<T>::~SOA3D()
0263 {
0264 #ifndef VECCORE_CUDA_DEVICE_COMPILATION
0265 Deallocate();
0266 #endif
0267 }
0268
0269 template <typename T>
0270 VECCORE_ATT_HOST_DEVICE size_t SOA3D<T>::size() const
0271 {
0272 return fSize;
0273 }
0274
0275 template <typename T>
0276 VECCORE_ATT_HOST_DEVICE size_t SOA3D<T>::capacity() const
0277 {
0278 return fCapacity;
0279 }
0280
0281 template <typename T>
0282 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::resize(size_t newSize)
0283 {
0284 VECGEOM_ASSERT(newSize <= fCapacity);
0285 fSize = newSize;
0286 }
0287
0288 template <typename T>
0289 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::reserve(size_t newCapacity)
0290 {
0291 fCapacity = newCapacity;
0292 T *xNew, *yNew, *zNew;
0293 xNew = AlignedAllocate<T>(fCapacity);
0294 yNew = AlignedAllocate<T>(fCapacity);
0295 zNew = AlignedAllocate<T>(fCapacity);
0296 fSize = (fSize > fCapacity) ? fCapacity : fSize;
0297 if (fX && fY && fZ) {
0298 copy(fX, fX + fSize, xNew);
0299 copy(fY, fY + fSize, yNew);
0300 copy(fZ, fZ + fSize, zNew);
0301 }
0302 Deallocate();
0303 fX = xNew;
0304 fY = yNew;
0305 fZ = zNew;
0306 fAllocated = true;
0307 }
0308
0309 template <typename T>
0310 void SOA3D<T>::clear()
0311 {
0312 Deallocate();
0313 fSize = 0;
0314 fCapacity = 0;
0315 }
0316
0317 template <typename T>
0318 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::Allocate()
0319 {
0320 if (fCapacity == 0) return;
0321
0322 fX = AlignedAllocate<T>(fCapacity);
0323 fY = AlignedAllocate<T>(fCapacity);
0324 fZ = AlignedAllocate<T>(fCapacity);
0325 fAllocated = true;
0326 }
0327
0328 template <typename T>
0329 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::Deallocate()
0330 {
0331 if (fAllocated) {
0332 AlignedFree(fX);
0333 AlignedFree(fY);
0334 AlignedFree(fZ);
0335 }
0336 fAllocated = false;
0337 }
0338
0339 template <typename T>
0340 VECCORE_ATT_HOST_DEVICE Vector3D<T> SOA3D<T>::operator[](size_t index) const
0341 {
0342 return Vector3D<T>(fX[index], fY[index], fZ[index]);
0343 }
0344
0345 template <typename T>
0346 VECCORE_ATT_HOST_DEVICE T SOA3D<T>::x(size_t index) const
0347 {
0348 return fX[index];
0349 }
0350
0351 template <typename T>
0352 VECCORE_ATT_HOST_DEVICE T &SOA3D<T>::x(size_t index)
0353 {
0354 return fX[index];
0355 }
0356
0357 template <typename T>
0358 VECCORE_ATT_HOST_DEVICE T *SOA3D<T>::x()
0359 {
0360 return fX;
0361 }
0362
0363 template <typename T>
0364 VECCORE_ATT_HOST_DEVICE T const *SOA3D<T>::x() const
0365 {
0366 return fX;
0367 }
0368
0369 template <typename T>
0370 VECCORE_ATT_HOST_DEVICE T SOA3D<T>::y(size_t index) const
0371 {
0372 return fY[index];
0373 }
0374
0375 template <typename T>
0376 VECCORE_ATT_HOST_DEVICE T &SOA3D<T>::y(size_t index)
0377 {
0378 return fY[index];
0379 }
0380
0381 template <typename T>
0382 VECCORE_ATT_HOST_DEVICE T *SOA3D<T>::y()
0383 {
0384 return fY;
0385 }
0386
0387 template <typename T>
0388 VECCORE_ATT_HOST_DEVICE T const *SOA3D<T>::y() const
0389 {
0390 return fY;
0391 }
0392
0393 template <typename T>
0394 VECCORE_ATT_HOST_DEVICE T SOA3D<T>::z(size_t index) const
0395 {
0396 return fZ[index];
0397 }
0398
0399 template <typename T>
0400 VECCORE_ATT_HOST_DEVICE T &SOA3D<T>::z(size_t index)
0401 {
0402 return fZ[index];
0403 }
0404
0405 template <typename T>
0406 VECCORE_ATT_HOST_DEVICE T *SOA3D<T>::z()
0407 {
0408 return fZ;
0409 }
0410
0411 template <typename T>
0412 VECCORE_ATT_HOST_DEVICE T const *SOA3D<T>::z() const
0413 {
0414 return fZ;
0415 }
0416
0417 template <typename T>
0418 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void SOA3D<T>::set(size_t index, T xval, T yval, T zval)
0419 {
0420
0421
0422 #ifndef VECCORE_CUDA
0423 VECGEOM_ASSERT(index < fCapacity);
0424 #endif
0425 fX[index] = xval;
0426 fY[index] = yval;
0427 fZ[index] = zval;
0428 }
0429
0430 template <typename T>
0431 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void SOA3D<T>::set(size_t index, Vector3D<T> const &vec)
0432 {
0433
0434
0435 #ifndef VECCORE_CUDA
0436 VECGEOM_ASSERT(index < fCapacity);
0437 #endif
0438 fX[index] = vec[0];
0439 fY[index] = vec[1];
0440 fZ[index] = vec[2];
0441 }
0442
0443 template <typename T>
0444 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::push_back(T xval, T yval, T zval)
0445 {
0446 fX[fSize] = xval;
0447 fY[fSize] = yval;
0448 fZ[fSize] = zval;
0449 ++fSize;
0450 }
0451
0452 template <typename T>
0453 VECCORE_ATT_HOST_DEVICE void SOA3D<T>::push_back(Vector3D<T> const &vec)
0454 {
0455 push_back(vec[0], vec[1], vec[2]);
0456 }
0457
0458 template <typename T>
0459 void SOA3D<T>::ToFile(std::string filename) const
0460 {
0461 std::ofstream outfile(filename, std::ios::binary);
0462 outfile.write(reinterpret_cast<const char *>(&fSize), sizeof(fSize));
0463 outfile.write(reinterpret_cast<const char *>(&fCapacity), sizeof(fCapacity));
0464 outfile.write(reinterpret_cast<char *>(fX), fCapacity * sizeof(T));
0465 outfile.write(reinterpret_cast<char *>(fY), fCapacity * sizeof(T));
0466 outfile.write(reinterpret_cast<char *>(fZ), fCapacity * sizeof(T));
0467 }
0468
0469
0470
0471 template <typename T>
0472 int SOA3D<T>::FromFile(std::string filename)
0473 {
0474
0475 decltype(fSize) s;
0476 decltype(fCapacity) cap;
0477 std::ifstream fin(filename, std::ios::binary);
0478 fin.read(reinterpret_cast<char *>(&s), sizeof(s));
0479 if (!fin) return -1;
0480 fin.read(reinterpret_cast<char *>(&cap), sizeof(cap));
0481 if (!fin) return -2;
0482
0483
0484
0485 fin.read(reinterpret_cast<char *>(fX), fCapacity * sizeof(T));
0486 if (!fin) return -3;
0487
0488 fin.read(reinterpret_cast<char *>(fY), fCapacity * sizeof(T));
0489 if (!fin) return -4;
0490
0491 fin.read(reinterpret_cast<char *>(fZ), fCapacity * sizeof(T));
0492 if (!fin) return -5;
0493
0494 return fCapacity;
0495 }
0496
0497 #ifdef VECGEOM_CUDA_INTERFACE
0498
0499 template <typename T>
0500 DevicePtr<cuda::SOA3D<T>> SOA3D<T>::CopyToGpu(DevicePtr<T> xGpu, DevicePtr<T> yGpu, DevicePtr<T> zGpu) const
0501 {
0502 xGpu.ToDevice(fX, fSize);
0503 yGpu.ToDevice(fY, fSize);
0504 zGpu.ToDevice(fZ, fSize);
0505
0506 DevicePtr<cuda::SOA3D<T>> gpu_ptr;
0507 gpu_ptr.Allocate();
0508 gpu_ptr.Construct(xGpu, yGpu, zGpu, fSize);
0509 }
0510
0511 template <typename T>
0512 DevicePtr<cuda::SOA3D<T>> SOA3D<T>::CopyToGpu(DevicePtr<T> xGpu, DevicePtr<T> yGpu, DevicePtr<T> zGpu,
0513 size_t count) const
0514 {
0515 xGpu.ToDevice(fX, count);
0516 yGpu.ToDevice(fY, count);
0517 zGpu.ToDevice(fZ, count);
0518
0519 DevicePtr<cuda::SOA3D<T>> gpu_ptr;
0520 gpu_ptr.Allocate();
0521 gpu_ptr.Construct(xGpu, yGpu, zGpu, fSize);
0522 }
0523
0524 #endif
0525 }
0526 }
0527
0528 #endif