Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-28 08:21:00

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/EventData/CompositeSpacePoint.hpp"
0013 #include "Acts/Geometry/GeometryIdentifier.hpp"
0014 #include "Acts/Utilities/detail/ContainerIterator.hpp"
0015 #include "ActsExamples/EventData/MuonSpacePoint.hpp"
0016 
0017 #include <array>
0018 #include <cstddef>
0019 #include <cstdint>
0020 #include <vector>
0021 
0022 #include <cuda_runtime.h>
0023 
0024 namespace ActsExamples {
0025 
0026 /// @brief Decode the detector layer from the raw MuonId representation, taken from MuonSpacePoint.
0027 ///
0028 /// This reproduces:
0029 ///
0030 ///   m_layer = ((rawRep >> 17) & fourBit);
0031 ///
0032 /// Bit layout relevant here:
0033 ///
0034 ///   bits 17..20 = encoded layer - 1
0035 ///
0036 /// Therefore:
0037 ///
0038 ///   stored value 0 -> layer 0
0039 ///   stored value 1 -> layer 1
0040 ///   ...
0041 ///   stored value 15 -> layer 15
0042 /// This function is used and we do not store layers to avoid repetition of
0043 /// memory storage
0044 ///
0045 /// @param rawId -> Muon ID as given to MuonSpacePoint
0046 /// @return Layer number in range of 0..31
0047 __host__ __device__ inline unsigned detLayer(std::uint32_t rawId) noexcept {
0048   static constexpr std::uint32_t fourBit = 0xFu;
0049   static constexpr std::uint32_t layerShift = 17u;
0050 
0051   return static_cast<unsigned>((rawId >> layerShift) & fourBit);
0052 }
0053 
0054 /// @brief Device-side raw structure-of-arrays view.
0055 ///
0056 /// This structure does not own memory. It only stores raw device pointers.
0057 /// CUDA kernels should receive this object by value.
0058 struct CudaMuonSpacePointArrays {
0059   Acts::GeometryIdentifier::Value* geometryId = nullptr;
0060   std::uint32_t* muonId = nullptr;
0061 
0062   double* localPositionX = nullptr;
0063   double* localPositionY = nullptr;
0064   double* localPositionZ = nullptr;
0065 
0066   double* sensorDirectionX = nullptr;
0067   double* sensorDirectionY = nullptr;
0068   double* sensorDirectionZ = nullptr;
0069 
0070   double* toNextSensorX = nullptr;
0071   double* toNextSensorY = nullptr;
0072   double* toNextSensorZ = nullptr;
0073 
0074   double* planeNormalX = nullptr;
0075   double* planeNormalY = nullptr;
0076   double* planeNormalZ = nullptr;
0077 
0078   double* covariance0 = nullptr;
0079   double* covariance1 = nullptr;
0080   double* covariance2 = nullptr;
0081 
0082   double* driftRadius = nullptr;
0083   double* time = nullptr;
0084 
0085   std::uint32_t* bucketStart = nullptr;
0086   std::uint32_t* bucketEnd = nullptr;
0087 };
0088 
0089 /// @brief This is the RAM copy of the data. The container copies this data to VRAM
0090 /// with moveToDevice() and copies it back with moveToHost().
0091 struct CudaMuonSpacePointHostData {
0092   std::vector<Acts::GeometryIdentifier::Value> geometryId;
0093   std::vector<std::uint32_t> muonId;
0094 
0095   std::vector<double> localPositionX;
0096   std::vector<double> localPositionY;
0097   std::vector<double> localPositionZ;
0098 
0099   std::vector<double> sensorDirectionX;
0100   std::vector<double> sensorDirectionY;
0101   std::vector<double> sensorDirectionZ;
0102 
0103   std::vector<double> toNextSensorX;
0104   std::vector<double> toNextSensorY;
0105   std::vector<double> toNextSensorZ;
0106 
0107   std::vector<double> planeNormalX;
0108   std::vector<double> planeNormalY;
0109   std::vector<double> planeNormalZ;
0110 
0111   std::vector<double> covariance0;
0112   std::vector<double> covariance1;
0113   std::vector<double> covariance2;
0114 
0115   std::vector<double> driftRadius;
0116   std::vector<double> time;
0117 
0118   std::vector<std::uint32_t> bucketStart;
0119   std::vector<std::uint32_t> bucketEnd;
0120 };
0121 
0122 class CudaMuonSpacePointContainer;
0123 
0124 /// @brief Host-side proxy representing one logical muon space point.
0125 /// As specified by CompositeSpacePoint concept.
0126 ///
0127 /// The proxy does not own data. It stores a pointer to the container and an
0128 /// index into the flat SoA columns.
0129 class CudaMuonSpacePointProxy {
0130  public:
0131   /// Empty default constructor.
0132   CudaMuonSpacePointProxy() = default;
0133 
0134   /// Constructor from container and space point index.
0135   /// @param container The container owning the data.
0136   /// @param index The index of the represented space point.
0137   CudaMuonSpacePointProxy(const CudaMuonSpacePointContainer& container,
0138                           std::size_t index) noexcept;
0139 
0140   /// Returns the muon identifier.
0141   const MuonSpacePoint::MuonId& id() const;
0142 
0143   /// Returns the geometry identifier.
0144   const Acts::GeometryIdentifier& geometryId() const;
0145 
0146   /// Returns the local measurement position.
0147   const Acts::Vector3& localPosition() const;
0148 
0149   /// Returns the local sensor direction.
0150   const Acts::Vector3& sensorDirection() const;
0151 
0152   /// Returns the normal vector to the measurement plane.
0153   const Acts::Vector3& planeNormal() const;
0154 
0155   /// Returns the vector pointing to the next wire / strip.
0156   const Acts::Vector3& toNextSensor() const;
0157 
0158   /// Returns the space point covariance values.
0159   const std::array<double, 3>& covariance() const;
0160 
0161   /// Returns the drift radius.
0162   double driftRadius() const;
0163 
0164   /// Returns the measurement time.
0165   double time() const;
0166 
0167   /// Returns whether the measurement is a straw measurement.
0168   bool isStraw() const;
0169 
0170   /// Returns whether the measurement provides time information.
0171   bool hasTime() const;
0172 
0173   /// Returns whether the measurement constrains local coordinate 0.
0174   bool measuresLoc0() const;
0175 
0176   /// Returns whether the measurement constrains local coordinate 1.
0177   bool measuresLoc1() const;
0178 
0179  private:
0180   const CudaMuonSpacePointContainer* m_container = nullptr;
0181   std::size_t m_index = 0;
0182 
0183   // Cache is needed because the data is returned as reference
0184   mutable MuonSpacePoint::MuonId m_idCache{};
0185   mutable Acts::GeometryIdentifier m_geometryIdCache{};
0186   mutable Acts::Vector3 m_localPositionCache{Acts::Vector3::Zero()};
0187   mutable Acts::Vector3 m_sensorDirectionCache{Acts::Vector3::Zero()};
0188   mutable Acts::Vector3 m_toNextSensorCache{Acts::Vector3::Zero()};
0189   mutable Acts::Vector3 m_planeNormalCache{Acts::Vector3::Zero()};
0190   mutable std::array<double, 3> m_covarianceCache{0.0, 0.0, 0.0};
0191 };
0192 
0193 /// @brief Pointer-like wrapper required by CompositeSpacePointContainer.
0194 ///
0195 /// The ACTS CompositeSpacePointContainer concept expects value_type to be
0196 /// pointer-like. This class provides operator-> and operator* over the proxy.
0197 class CudaMuonSpacePointPtr {
0198  public:
0199   /// Type alias for the pointed-to type.
0200   using element_type = CudaMuonSpacePointProxy;
0201 
0202   /// Empty default constructor.
0203   CudaMuonSpacePointPtr() = default;
0204 
0205   /// Constructor from container and space point index.
0206   /// @param container The container owning the data.
0207   /// @param index The index of the represented space point.
0208   CudaMuonSpacePointPtr(const CudaMuonSpacePointContainer& container,
0209                         std::size_t index) noexcept;
0210 
0211   /// Accesses the proxy.
0212   element_type* operator->() noexcept { return &m_proxy; }
0213 
0214   /// Dereferences the proxy.
0215   element_type& operator*() noexcept { return m_proxy; }
0216 
0217   /// Checks whether this pointer-like object is valid.
0218   explicit operator bool() noexcept { return m_valid; }
0219 
0220  private:
0221   element_type m_proxy{};
0222   bool m_valid = false;
0223 };
0224 
0225 /// @brief CUDA-backed flat SoA container for muon space points.
0226 ///
0227 /// The old MuonSpacePointContainer is a jagged vector of buckets. This class
0228 /// keeps all space points in one flat SoA and stores bucket ranges separately.
0229 class CudaMuonSpacePointContainer {
0230  public:
0231   /// Type alias for pointer-like value type.
0232   using value_type = CudaMuonSpacePointPtr;
0233   /// Type alias for container size type.
0234   using size_type = std::size_t;
0235 
0236   /// Iterator type over the flat space point container.
0237   template <bool read_only>
0238   using Iterator = Acts::detail::ContainerIterator<
0239       CudaMuonSpacePointContainer, CudaMuonSpacePointPtr, size_type, read_only>;
0240 
0241   /// Mutable iterator.
0242   using iterator = Iterator<false>;
0243   /// Const iterator.
0244   using const_iterator = Iterator<true>;
0245 
0246   /// Empty default constructor.
0247   CudaMuonSpacePointContainer() = default;
0248 
0249   /// Construct from MuonSpacePointContaier, implemented to avoid reader
0250   explicit CudaMuonSpacePointContainer(
0251       const MuonSpacePointContainer& spacePoints);
0252 
0253   /// Constructor with fixed number of space points.
0254   /// @param size The number of flat space points.
0255   explicit CudaMuonSpacePointContainer(size_type size);
0256 
0257   /// Deleted because the container owns CUDA device memory.
0258   CudaMuonSpacePointContainer(const CudaMuonSpacePointContainer&) = delete;
0259   CudaMuonSpacePointContainer& operator=(const CudaMuonSpacePointContainer&) =
0260       delete;
0261 
0262   /// Movable to transfer ownership of host/device storage.
0263   CudaMuonSpacePointContainer(CudaMuonSpacePointContainer&& other) noexcept;
0264   CudaMuonSpacePointContainer& operator=(
0265       CudaMuonSpacePointContainer&& other) noexcept;
0266 
0267   /// @brief Destructor releases VRAM pointer.
0268   ~CudaMuonSpacePointContainer() noexcept;
0269 
0270   /// @brief Returns the number of flat space points.
0271   size_type size() const noexcept { return m_size; }
0272 
0273   /// @brief Checks whether the container is empty.
0274   bool empty() const noexcept { return size() == 0; }
0275 
0276   /// @brief Returns the number of buckets.
0277   size_type bucketCount() const noexcept { return m_host.bucketStart.size(); }
0278 
0279   /// @brief Returns the first space point index of a bucket.
0280   /// @param bucket The bucket index.
0281   size_type bucketStart(size_type bucket) const;
0282 
0283   /// @brief Returns the past-the-end space point index of a bucket.
0284   /// @param bucket The bucket index.
0285   size_type bucketEnd(size_type bucket) const;
0286 
0287   /// @brief Adds a bucket range.
0288   /// @param start First space point index in the bucket.
0289   /// @param end Past-the-end space point index in the bucket.
0290   void addBucket(size_type start, size_type end);
0291 
0292   /// @brief Sets the geometry identifier.
0293   /// @param index The space point index.
0294   /// @param geometryId The raw geometry identifier.
0295   void setGeometryId(size_type index,
0296                      Acts::GeometryIdentifier::Value geometryId);
0297 
0298   /// @brief Sets the muon identifier.
0299   /// @param index The space point index.
0300   /// @param muonId The raw muon identifier.
0301   void setId(size_type index, std::uint32_t muonId);
0302 
0303   /// @brief Defines the coordinate system and computes the plane normal.
0304   /// @param index The space point index.
0305   /// @param position The local position.
0306   /// @param sensorDirection The sensor direction.
0307   /// @param toNextSensor The direction to the next sensor.
0308   void defineCoordinates(size_type index, const Acts::Vector3& position,
0309                          const Acts::Vector3& sensorDirection,
0310                          const Acts::Vector3& toNextSensor);
0311 
0312   /// @brief Sets the drift radius.
0313   /// @param index The space point index.
0314   /// @param radius The drift radius.
0315   void setRadius(size_type index, double radius);
0316 
0317   /// @brief Sets the measurement time.
0318   /// @param index The space point index.
0319   /// @param time The measurement time.
0320   void setTime(size_type index, double time);
0321 
0322   /// @brief Sets covariance values.
0323   /// @param index The space point index.
0324   /// @param cov0 First covariance component.
0325   /// @param cov1 Second covariance component.
0326   /// @param cov2 Time covariance component.
0327   void setCovariance(size_type index, double cov0, double cov1, double cov2);
0328 
0329   /// @brief Copies all host columns to device memory.
0330   void moveToDevice();
0331 
0332   /// @brief Copies all device columns back to host memory.
0333   void moveToHost();
0334 
0335   /// @brief Releases all device memory.
0336   void clearDevice() noexcept;
0337 
0338   /// @brief Checks whether device memory is currently allocated.
0339   bool isOnDevice() const noexcept { return m_onDevice; }
0340 
0341   /// @brief Returns raw device arrays for CUDA kernels.
0342   CudaMuonSpacePointArrays deviceArrays() const noexcept { return m_device; }
0343 
0344   /// @brief Returns a pointer-like proxy to a space point.
0345   /// @param index The space point index.
0346   value_type operator[](size_type index) noexcept {
0347     return value_type{*this, index};
0348   }
0349 
0350   /// @brief Returns a const pointer-like proxy to a space point.
0351   /// @param index The space point index.
0352   value_type operator[](size_type index) const noexcept {
0353     return value_type{*this, index};
0354   }
0355 
0356   value_type at(size_type index) const;
0357 
0358   iterator begin() noexcept { return {*this, 0}; }
0359 
0360   iterator end() noexcept { return {*this, size()}; }
0361 
0362   const_iterator begin() const noexcept { return {*this, 0}; }
0363 
0364   const_iterator end() const noexcept { return {*this, size()}; }
0365 
0366   // Returns raw muonId stored in space point
0367   std::uint32_t muonId(std::uint32_t idx) const noexcept {
0368     return m_host.muonId[idx];
0369   }
0370 
0371   // Write zero based layer into MuonId
0372   void setLogicalLayer(size_type index, std::uint32_t layer);
0373 
0374  private:
0375   /// Allow proxy to accesses private data
0376   friend class CudaMuonSpacePointProxy;
0377 
0378   size_type m_size = 0;
0379   CudaMuonSpacePointHostData m_host{};
0380   CudaMuonSpacePointArrays m_device{};
0381   bool m_onDevice = false;
0382 
0383   void checkIndex(size_type index) const;
0384   void checkBucket(size_type bucket) const;
0385 };
0386 
0387 /// Assert all concepts are fulfilled
0388 static_assert(Acts::Experimental::CompositeSpacePoint<CudaMuonSpacePointProxy>);
0389 static_assert(
0390     Acts::Experimental::CompositeSpacePointPtr<CudaMuonSpacePointPtr>);
0391 static_assert(Acts::Experimental::CompositeSpacePointContainer<
0392               CudaMuonSpacePointContainer>);
0393 
0394 }  // namespace ActsExamples