Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:15

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2016-2020 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <cstdint>
0012 #include <functional>
0013 #include <iosfwd>
0014 #include <utility>
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 = uint64_t;
0034 
0035   /// Construct from an already encoded value.
0036   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   /// Return the boundary identifier.
0051   constexpr Value boundary() const { return getBits(kBoundaryMask); }
0052   /// Return the layer identifier.
0053   constexpr Value layer() const { return getBits(kLayerMask); }
0054   /// Return the approach identifier.
0055   constexpr Value approach() const { return getBits(kApproachMask); }
0056   /// Return the approach identifier.
0057   constexpr Value passive() const { return getBits(kApproachMask); }
0058   /// Return the sensitive identifier.
0059   constexpr Value sensitive() const { return getBits(kSensitiveMask); }
0060   /// Return the extra identifier
0061   /// Usage can be experiment-specific, like tagging which kind of detector a
0062   /// surface object corresponds to, or which subsystem it belongs to
0063   constexpr Value extra() const { return getBits(kExtraMask); }
0064 
0065   /// Set the volume identifier.
0066   constexpr GeometryIdentifier& setVolume(Value volume) {
0067     return setBits(kVolumeMask, volume);
0068   }
0069   /// Set the boundary identifier.
0070   constexpr GeometryIdentifier& setBoundary(Value boundary) {
0071     return setBits(kBoundaryMask, boundary);
0072   }
0073   /// Set the layer identifier.
0074   constexpr GeometryIdentifier& setLayer(Value layer) {
0075     return setBits(kLayerMask, layer);
0076   }
0077   /// Set the approach identifier.
0078   constexpr GeometryIdentifier& setApproach(Value approach) {
0079     return setBits(kApproachMask, approach);
0080   }
0081   /// Set the approach identifier - shared with Passive
0082   constexpr GeometryIdentifier& setPassive(Value approach) {
0083     return setBits(kApproachMask, approach);
0084   }
0085   /// Set the sensitive identifier.
0086   constexpr GeometryIdentifier& setSensitive(Value sensitive) {
0087     return setBits(kSensitiveMask, sensitive);
0088   }
0089   /// Set the extra identifier
0090   constexpr GeometryIdentifier& setExtra(Value extra) {
0091     return setBits(kExtraMask, extra);
0092   }
0093 
0094  private:
0095   // clang-format off
0096   /// (2^8)-1 = 255 volumes
0097   static constexpr Value kVolumeMask    = 0xff00000000000000;
0098   /// (2^8)-1 = 255 boundaries
0099   static constexpr Value kBoundaryMask  = 0x00ff000000000000;
0100   /// (2^12)-1 = 4095 layers
0101   static constexpr Value kLayerMask     = 0x0000fff000000000;
0102   /// (2^8)-1 = 255 approach surfaces
0103   static constexpr Value kApproachMask  = 0x0000000ff0000000;
0104   static constexpr Value kPassiveMask   = kApproachMask;
0105   /// (2^20)-1 = 1048575 sensitive surfaces
0106   static constexpr Value kSensitiveMask = 0x000000000fffff00;
0107   /// (2^8)-1 = 255 extra values
0108   static constexpr Value kExtraMask     = 0x00000000000000ff;
0109   // clang-format on
0110 
0111   Value m_value = 0;
0112 
0113   /// Extract the bit shift necessary to access the masked values.
0114   static constexpr int extractShift(Value mask) {
0115     // use compiler builtin to extract the number of trailing bits from the
0116     // mask. the builtin should be available on all supported compilers.
0117     // need unsigned long long version (...ll) to ensure uint64_t compatibility.
0118     // WARNING undefined behaviour for mask == 0 which we should not have.
0119     return __builtin_ctzll(mask);
0120   }
0121   /// Extract the masked bits from the encoded value.
0122   constexpr Value getBits(Value mask) const {
0123     return (m_value & mask) >> extractShift(mask);
0124   }
0125   /// Set the masked bits to id in the encoded value.
0126   constexpr GeometryIdentifier& setBits(Value mask, Value id) {
0127     m_value = (m_value & ~mask) | ((id << extractShift(mask)) & mask);
0128     // return *this here so we need to write less lines in the set... methods
0129     return *this;
0130   }
0131 
0132   friend constexpr bool operator==(GeometryIdentifier lhs,
0133                                    GeometryIdentifier rhs) {
0134     return lhs.m_value == rhs.m_value;
0135   }
0136   friend constexpr bool operator!=(GeometryIdentifier lhs,
0137                                    GeometryIdentifier rhs) {
0138     return lhs.m_value != rhs.m_value;
0139   }
0140   friend constexpr bool operator<(GeometryIdentifier lhs,
0141                                   GeometryIdentifier rhs) {
0142     return lhs.m_value < rhs.m_value;
0143   }
0144 };
0145 
0146 std::ostream& operator<<(std::ostream& os, GeometryIdentifier id);
0147 
0148 /// Base class for hooks that can be used to modify the Geometry Identifier
0149 /// during construction. Most common use case is setting the extra bit fields.
0150 struct GeometryIdentifierHook {
0151   virtual ~GeometryIdentifierHook() = default;
0152   virtual Acts::GeometryIdentifier decorateIdentifier(
0153       Acts::GeometryIdentifier identifier, const Acts::Surface& surface) const;
0154 };
0155 
0156 }  // namespace Acts
0157 
0158 // specialize std::hash so GeometryIdentifier can be used e.g. in an
0159 // unordered_map
0160 namespace std {
0161 template <>
0162 struct hash<Acts::GeometryIdentifier> {
0163   auto operator()(Acts::GeometryIdentifier gid) const noexcept {
0164     return std::hash<Acts::GeometryIdentifier::Value>()(gid.value());
0165   }
0166 };
0167 }  // namespace std