Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /acts/Core/include/Acts/Geometry/GeometryIdentifier.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 <cstdint>
0012 #include <functional>
0013 #include <iosfwd>
0014 #include <stdexcept>
0015 
0016 namespace Acts {
0017 
0018 class Surface;
0019 
0020 /// Identifier for geometry nodes within the geometry hierarchy.
0021 ///
0022 /// An identifier can be split into the following components. They define
0023 /// a hierarchy of objects starting from the high-level volumes:
0024 ///
0025 /// - Volume
0026 /// - Boundary surfaces (for a volume)
0027 /// - Layers (confined within a volume)
0028 /// - Approach surfaces (for a layer)
0029 /// - Sensitive surfaces (confined to a layer, also called modules)
0030 ///
0031 class GeometryIdentifier {
0032  public:
0033   using Value = std::uint64_t;
0034 
0035   /// Construct from an already encoded value.
0036   explicit constexpr GeometryIdentifier(Value encoded) : m_value(encoded) {}
0037   /// Construct default GeometryIdentifier with all values set to zero.
0038   GeometryIdentifier() = default;
0039   GeometryIdentifier(GeometryIdentifier&&) = default;
0040   GeometryIdentifier(const GeometryIdentifier&) = default;
0041   ~GeometryIdentifier() = default;
0042   GeometryIdentifier& operator=(GeometryIdentifier&&) = default;
0043   GeometryIdentifier& operator=(const GeometryIdentifier&) = default;
0044 
0045   /// Return the encoded value.
0046   constexpr Value value() const { return m_value; }
0047 
0048   /// Return the volume identifier.
0049   constexpr Value volume() const { return getBits(kVolumeMask); }
0050 
0051   /// Return the boundary identifier.
0052   constexpr Value boundary() const { return getBits(kBoundaryMask); }
0053 
0054   /// Return the layer identifier.
0055   constexpr Value layer() const { return getBits(kLayerMask); }
0056 
0057   /// Return the approach identifier.
0058   constexpr Value approach() const { return getBits(kApproachMask); }
0059 
0060   /// Return the approach identifier.
0061   constexpr Value passive() const { return getBits(kApproachMask); }
0062 
0063   /// Return the sensitive identifier.
0064   constexpr Value sensitive() const { return getBits(kSensitiveMask); }
0065 
0066   /// Return the extra identifier
0067   /// Usage can be experiment-specific, like tagging which kind of detector a
0068   /// surface object corresponds to, or which subsystem it belongs to
0069   constexpr Value extra() const { return getBits(kExtraMask); }
0070 
0071   /// Set the volume identifier.
0072   [[deprecated("Use withVolume() instead")]]
0073   constexpr GeometryIdentifier& setVolume(Value volume) {
0074     setBits(kVolumeMask, volume);
0075     return *this;
0076   }
0077 
0078   /// Set the boundary identifier.
0079   [[deprecated("Use withBoundary() instead")]]
0080   constexpr GeometryIdentifier& setBoundary(Value boundary) {
0081     setBits(kBoundaryMask, boundary);
0082     return *this;
0083   }
0084 
0085   /// Set the layer identifier.
0086   [[deprecated("Use withLayer() instead")]]
0087   constexpr GeometryIdentifier& setLayer(Value layer) {
0088     setBits(kLayerMask, layer);
0089     return *this;
0090   }
0091 
0092   /// Set the approach identifier.
0093   [[deprecated("Use withApproach() instead")]]
0094   constexpr GeometryIdentifier& setApproach(Value approach) {
0095     setBits(kApproachMask, approach);
0096     return *this;
0097   }
0098 
0099   /// Set the approach identifier - shared with Passive
0100   [[deprecated("Use withPassive() instead")]]
0101   constexpr GeometryIdentifier& setPassive(Value approach) {
0102     setBits(kApproachMask, approach);
0103     return *this;
0104   }
0105 
0106   /// Set the sensitive identifier.
0107   [[deprecated("Use withSensitive() instead")]]
0108   constexpr GeometryIdentifier& setSensitive(Value sensitive) {
0109     setBits(kSensitiveMask, sensitive);
0110     return *this;
0111   }
0112 
0113   /// Set the extra identifier
0114   [[deprecated("Use withExtra() instead")]]
0115   constexpr GeometryIdentifier& setExtra(Value extra) {
0116     return setBits(kExtraMask, extra);
0117     return *this;
0118   }
0119 
0120   /// Return a new identifier with the volume set to @p volume
0121   /// @param volume the new volume identifier
0122   /// @return a new identifier with the volume set to @p volume
0123   [[nodiscard]]
0124   constexpr GeometryIdentifier withVolume(Value volume) const {
0125     GeometryIdentifier id = *this;
0126     id.setBits(kVolumeMask, volume);
0127     return id;
0128   }
0129 
0130   /// Return a new identifier with the boundary set to @p boundary
0131   /// @param boundary the new boundary identifier
0132   /// @return a new identifier with the boundary set to @p boundary
0133   [[nodiscard]]
0134   constexpr GeometryIdentifier withBoundary(Value boundary) const {
0135     GeometryIdentifier id = *this;
0136     id.setBits(kBoundaryMask, boundary);
0137     return id;
0138   }
0139 
0140   /// Return a new identifier with the layer set to @p layer
0141   /// @param layer the new layer identifier
0142   /// @return a new identifier with the layer set to @p layer
0143   [[nodiscard]]
0144   constexpr GeometryIdentifier withLayer(Value layer) const {
0145     GeometryIdentifier id = *this;
0146     id.setBits(kLayerMask, layer);
0147     return id;
0148   }
0149 
0150   /// Return a new identifier with the approach set to @p approach
0151   /// @param approach the new approach identifier
0152   /// @return a new identifier with the approach set to @p approach
0153   [[nodiscard]]
0154   constexpr GeometryIdentifier withApproach(Value approach) const {
0155     GeometryIdentifier id = *this;
0156     id.setBits(kApproachMask, approach);
0157     return id;
0158   }
0159 
0160   /// Return a new identifier with the passive set to @p passive
0161   /// @param passive the new passive identifier
0162   /// @return a new identifier with the passive set to @p passive
0163   [[nodiscard]]
0164   constexpr GeometryIdentifier withPassive(Value passive) const {
0165     GeometryIdentifier id = *this;
0166     id.setBits(kApproachMask, passive);
0167     return id;
0168   }
0169 
0170   /// Return a new identifier with the sensitive set to @p sensitive
0171   /// @param sensitive the new sensitive identifier
0172   /// @return a new identifier with the sensitive set to @p sensitive
0173   [[nodiscard]]
0174   constexpr GeometryIdentifier withSensitive(Value sensitive) const {
0175     GeometryIdentifier id = *this;
0176     id.setBits(kSensitiveMask, sensitive);
0177     return id;
0178   }
0179 
0180   /// Return a new identifier with the extra set to @p extra
0181   /// @param extra the new extra identifier
0182   /// @return a new identifier with the extra set to @p extra
0183   [[nodiscard]]
0184   constexpr GeometryIdentifier withExtra(Value extra) const {
0185     GeometryIdentifier id = *this;
0186     id.setBits(kExtraMask, extra);
0187     return id;
0188   }
0189 
0190   /// Get the maximum value for the volume identifier.
0191   /// @return the maximum value for the volume identifier
0192   static constexpr Value getMaxVolume() { return getMaxValue(kVolumeMask); }
0193 
0194   /// Get the maximum value for the boundary identifier.
0195   /// @return the maximum value for the boundary identifier
0196   static constexpr Value getMaxBoundary() { return getMaxValue(kBoundaryMask); }
0197 
0198   /// Get the maximum value for the layer identifier.
0199   /// @return the maximum value for the layer identifier
0200   static constexpr Value getMaxLayer() { return getMaxValue(kLayerMask); }
0201 
0202   /// Get the maximum value for the approach identifier.
0203   /// @return the maximum value for the approach identifier
0204   static constexpr Value getMaxApproach() { return getMaxValue(kApproachMask); }
0205 
0206   /// Get the maximum value for the sensitive identifier.
0207   /// @return the maximum value for the sensitive identifier
0208   static constexpr Value getMaxSensitive() {
0209     return getMaxValue(kSensitiveMask);
0210   }
0211 
0212   /// Get the maximum value for the extra identifier.
0213   /// @return the maximum value for the extra identifier
0214   static constexpr Value getMaxExtra() { return getMaxValue(kExtraMask); }
0215 
0216  private:
0217   // clang-format off
0218   /// (2^8)-1 = 255 volumes
0219   static constexpr Value kVolumeMask    = 0xff00000000000000;
0220   /// (2^8)-1 = 255 boundaries
0221   static constexpr Value kBoundaryMask  = 0x00ff000000000000;
0222   /// (2^12)-1 = 4095 layers
0223   static constexpr Value kLayerMask     = 0x0000fff000000000;
0224   /// (2^8)-1 = 255 approach surfaces
0225   static constexpr Value kApproachMask  = 0x0000000ff0000000;
0226   /// (2^20)-1 = 1048575 sensitive surfaces
0227   static constexpr Value kSensitiveMask = 0x000000000fffff00;
0228   /// (2^8)-1 = 255 extra values
0229   static constexpr Value kExtraMask     = 0x00000000000000ff;
0230   // clang-format on
0231 
0232   Value m_value = 0;
0233 
0234   /// Extract the bit shift necessary to access the masked values.
0235   static constexpr int extractShift(Value mask) {
0236     // use compiler builtin to extract the number of trailing bits from the
0237     // mask. the builtin should be available on all supported compilers.
0238     // need unsigned long long version (...ll) to ensure std::uint64_t
0239     // compatibility.
0240     // WARNING undefined behaviour for mask == 0 which we should not have.
0241     return __builtin_ctzll(mask);
0242   }
0243 
0244   constexpr static Value getMaxValue(Value mask) {
0245     return mask >> extractShift(mask);
0246   }
0247 
0248   /// Extract the masked bits from the encoded value.
0249   constexpr Value getBits(Value mask) const {
0250     return (m_value & mask) >> extractShift(mask);
0251   }
0252   /// Set the masked bits to id in the encoded value.
0253   constexpr GeometryIdentifier& setBits(Value mask, Value id) {
0254     if (id > getMaxValue(mask)) {
0255       throw std::invalid_argument(
0256           "Value " + std::to_string(id) + " exceeds maximum value " +
0257           std::to_string(getMaxValue(mask)) + " for this field");
0258     }
0259 
0260     m_value = (m_value & ~mask) | ((id << extractShift(mask)) & mask);
0261     // return *this here that we need to write fewer lines in the setXXX
0262     // methods
0263     return *this;
0264   }
0265 
0266   friend constexpr bool operator==(GeometryIdentifier lhs,
0267                                    GeometryIdentifier rhs) {
0268     return lhs.m_value == rhs.m_value;
0269   }
0270 
0271   friend constexpr bool operator<(GeometryIdentifier lhs,
0272                                   GeometryIdentifier rhs) {
0273     return lhs.m_value < rhs.m_value;
0274   }
0275 };
0276 
0277 std::ostream& operator<<(std::ostream& os, GeometryIdentifier id);
0278 
0279 /// Base class for hooks that can be used to modify the Geometry Identifier
0280 /// during construction. Most common use case is setting the extra bit fields.
0281 struct GeometryIdentifierHook {
0282   virtual ~GeometryIdentifierHook() = default;
0283   virtual Acts::GeometryIdentifier decorateIdentifier(
0284       Acts::GeometryIdentifier identifier, const Acts::Surface& surface) const;
0285 };
0286 
0287 }  // namespace Acts
0288 // specialize std::hash so GeometryIdentifier can be used e.g. in an
0289 // unordered_map
0290 namespace std {
0291 template <>
0292 struct hash<Acts::GeometryIdentifier> {
0293   auto operator()(Acts::GeometryIdentifier gid) const noexcept {
0294     return std::hash<Acts::GeometryIdentifier::Value>()(gid.value());
0295   }
0296 };
0297 }  // namespace std