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-2018 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 "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/BoundarySurfaceFace.hpp"
0013 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Geometry/GeometryIdentifier.hpp"
0016 #include "Acts/Geometry/Layer.hpp"
0017 #include "Acts/Geometry/TrackingVolumeVisitorConcept.hpp"
0018 #include "Acts/Geometry/Volume.hpp"
0019 #include "Acts/Material/IVolumeMaterial.hpp"
0020 #include "Acts/Surfaces/BoundaryCheck.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Surfaces/SurfaceArray.hpp"
0023 #include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
0024 #include "Acts/Utilities/BinnedArray.hpp"
0025 #include "Acts/Utilities/BoundingBox.hpp"
0026 #include "Acts/Utilities/Concepts.hpp"
0027 #include "Acts/Utilities/Frustum.hpp"
0028 #include "Acts/Utilities/Intersection.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 #include "Acts/Utilities/Ray.hpp"
0031 #include "Acts/Utilities/TransformRange.hpp"
0032 
0033 #include <cstddef>
0034 #include <functional>
0035 #include <memory>
0036 #include <string>
0037 #include <unordered_map>
0038 #include <utility>
0039 #include <vector>
0040 
0041 #include <boost/container/small_vector.hpp>
0042 
0043 namespace Acts {
0044 
0045 class GlueVolumesDescriptor;
0046 class VolumeBounds;
0047 template <typename object_t>
0048 struct NavigationOptions;
0049 class GeometryIdentifier;
0050 class IMaterialDecorator;
0051 class ISurfaceMaterial;
0052 class IVolumeMaterial;
0053 class Surface;
0054 class TrackingVolume;
0055 struct GeometryIdentifierHook;
0056 
0057 /// Interface types of the Gen1 geometry model
0058 /// @note This interface is being replaced, and is subject to removal
0059 /// @{
0060 
0061 // master typedefs
0062 using TrackingVolumePtr = std::shared_ptr<const TrackingVolume>;
0063 using MutableTrackingVolumePtr = std::shared_ptr<TrackingVolume>;
0064 
0065 using TrackingVolumeBoundaryPtr =
0066     std::shared_ptr<const BoundarySurfaceT<TrackingVolume>>;
0067 using TrackingVolumeBoundaries = std::vector<TrackingVolumeBoundaryPtr>;
0068 
0069 // possible contained
0070 using TrackingVolumeArray = BinnedArray<TrackingVolumePtr>;
0071 using TrackingVolumeVector = std::vector<TrackingVolumePtr>;
0072 using MutableTrackingVolumeVector = std::vector<MutableTrackingVolumePtr>;
0073 using LayerArray = BinnedArray<LayerPtr>;
0074 using LayerVector = std::vector<LayerPtr>;
0075 
0076 /// Intersection with @c Layer
0077 using LayerIntersection = std::pair<SurfaceIntersection, const Layer*>;
0078 /// Multi-intersection with @c Layer
0079 using LayerMultiIntersection =
0080     std::pair<SurfaceMultiIntersection, const Layer*>;
0081 
0082 /// BoundarySurface of a volume
0083 using BoundarySurface = BoundarySurfaceT<TrackingVolume>;
0084 /// Intersection with a @c BoundarySurface
0085 using BoundaryIntersection =
0086     std::pair<SurfaceIntersection, const BoundarySurface*>;
0087 /// Multi-intersection with a @c BoundarySurface
0088 using BoundaryMultiIntersection =
0089     std::pair<SurfaceMultiIntersection, const BoundarySurface*>;
0090 
0091 /// @}
0092 
0093 /// @class TrackingVolume
0094 ///
0095 /// Full Volume description used in Tracking,
0096 /// it inherits from Volume to get the geometrical structure.
0097 ///
0098 ///     A TrackingVolume at navigation level can provide the (layer) material
0099 /// information / internal navigation with in
0100 ///     5 different ways:
0101 ///
0102 ///         --- a) Static confinement of Layers
0103 ///         --- b) detached sub volumes
0104 ///         --- b) unordered (arbitrarily oriented) layers
0105 ///         --- d) unordered sub volumes
0106 ///         --- e) unordered layers AND unordered subvolumes
0107 ///
0108 ///    The TrackingVolume can also be a simple container of other
0109 ///    TrackingVolumes
0110 ///
0111 /// In addition it is capable of holding a subarray of Layers and
0112 /// TrackingVolumes.
0113 ///
0114 class TrackingVolume : public Volume {
0115   friend class TrackingGeometry;
0116 
0117  public:
0118   TrackingVolume() = delete;
0119   ~TrackingVolume() override;
0120   TrackingVolume(const TrackingVolume&) = delete;
0121   TrackingVolume& operator=(const TrackingVolume&) = delete;
0122 
0123   /// Constructor for a container Volume
0124   /// - vacuum filled volume either as a for other tracking volumes
0125   ///
0126   /// @param transform is the global 3D transform to position the volume in
0127   /// space
0128   /// @param volbounds is the description of the volume boundaries
0129   /// @param containedVolumeArray are the static volumes that fill this volume
0130   /// @param volumeName is a string identifier
0131   TrackingVolume(const Transform3& transform,
0132                  std::shared_ptr<const VolumeBounds> volbounds,
0133                  const std::shared_ptr<const TrackingVolumeArray>&
0134                      containedVolumeArray = nullptr,
0135                  const std::string& volumeName = "undefined");
0136 
0137   /// Constructor for a full equipped Tracking Volume
0138   ///
0139   /// @param transform is the global 3D transform to position the volume in
0140   /// space
0141   /// @param volumeBounds is the description of the volume boundaries
0142   /// @param volumeMaterial is are materials of the tracking volume
0143   /// @param staticLayerArray is the confined layer array (optional)
0144   /// @param containedVolumeArray are the sub volumes if the volume is a
0145   /// container
0146   /// @param denseVolumeVector  The contained dense volumes
0147   /// @param volumeName is a string identifier
0148   TrackingVolume(
0149       const Transform3& transform,
0150       std::shared_ptr<const VolumeBounds> volumeBounds,
0151       std::shared_ptr<const IVolumeMaterial> volumeMaterial,
0152       std::unique_ptr<const LayerArray> staticLayerArray = nullptr,
0153       std::shared_ptr<const TrackingVolumeArray> containedVolumeArray = nullptr,
0154       MutableTrackingVolumeVector denseVolumeVector = {},
0155       const std::string& volumeName = "undefined");
0156 
0157   /// Constructor from a regular volume
0158   /// @param volume is the volume to be converted
0159   /// @param volumeName is a string identifier
0160   TrackingVolume(const Volume& volume,
0161                  const std::string& volumeName = "undefined");
0162 
0163   // @TODO: This needs to be refactored to include Gen3 volumes
0164   /// Return the associated sub Volume, returns THIS if no subVolume exists
0165   /// @param gctx The current geometry context object, e.g. alignment
0166   /// @param position is the global position associated with that search
0167   /// @param tol Search position tolerance for dense volumes
0168   ///
0169   /// @return plain pointer to associated with the position
0170   const TrackingVolume* lowestTrackingVolume(const GeometryContext& gctx,
0171                                              const Vector3& position,
0172                                              const double tol = 0.) const;
0173 
0174   /// @brief Visit all reachable surfaces
0175   ///
0176   /// @tparam visitor_t Type of the callable visitor
0177   ///
0178   /// @param visitor The callable. Will be called for each reachable surface
0179   /// that is found, a selection of the surfaces can be done in the visitor
0180   /// @param restrictToSensitives If true, only sensitive surfaces are visited
0181   ///
0182   /// @note If a context is needed for the visit, the vistitor has to provide
0183   /// this, e.g. as a private member
0184   template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
0185   void visitSurfaces(visitor_t&& visitor, bool restrictToSensitives) const {
0186     if (!restrictToSensitives) {
0187       // Visit the boundary surfaces
0188       for (const auto& bs : m_boundarySurfaces) {
0189         visitor(&(bs->surfaceRepresentation()));
0190       }
0191     }
0192 
0193     // Internal structure
0194     if (m_confinedVolumes == nullptr) {
0195       // no sub volumes => loop over the confined layers
0196       if (m_confinedLayers != nullptr) {
0197         for (const auto& layer : m_confinedLayers->arrayObjects()) {
0198           // Surfaces contained in the surface array
0199           if (layer->surfaceArray() != nullptr) {
0200             for (const auto& srf : layer->surfaceArray()->surfaces()) {
0201               visitor(srf);
0202               continue;
0203             }
0204           }
0205           if (!restrictToSensitives) {
0206             // Surfaces of the layer
0207             visitor(&layer->surfaceRepresentation());
0208             // Approach surfaces of the layer
0209             if (layer->approachDescriptor() != nullptr) {
0210               for (const auto& srf :
0211                    layer->approachDescriptor()->containedSurfaces()) {
0212                 visitor(srf);
0213               }
0214             }
0215           }
0216         }
0217       }
0218     } else {
0219       // contains sub volumes
0220       for (const auto& volume : m_confinedVolumes->arrayObjects()) {
0221         volume->visitSurfaces(visitor, restrictToSensitives);
0222       }
0223     }
0224   }
0225 
0226   /// @brief Visit all sensitive surfaces
0227   ///
0228   /// @tparam visitor_t Type of the callable visitor
0229   ///
0230   /// @param visitor The callable. Will be called for each sensitive surface
0231   /// that is found, a selection of the surfaces can be done in the visitor
0232   ///
0233   /// @note If a context is needed for the visit, the vistitor has to provide
0234   /// this, e.g. as a private member
0235   template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
0236   void visitSurfaces(visitor_t&& visitor) const {
0237     visitSurfaces(std::forward<visitor_t>(visitor), true);
0238   }
0239 
0240   /// @brief Visit all reachable tracking volumes
0241   ///
0242   /// @tparam visitor_t Type of the callable visitor
0243   ///
0244   /// @param visitor The callable. Will be called for each reachable volume
0245   /// that is found, a selection of the volumes can be done in the visitor
0246   ///
0247   /// @note If a context is needed for the visit, the vistitor has to provide
0248   /// this, e.g. as a private member
0249   template <ACTS_CONCEPT(TrackingVolumeVisitor) visitor_t>
0250   void visitVolumes(visitor_t&& visitor) const {
0251     visitor(this);
0252     if (m_confinedVolumes != nullptr) {
0253       // contains sub volumes
0254       for (const auto& volume : m_confinedVolumes->arrayObjects()) {
0255         volume->visitVolumes(visitor);
0256       }
0257     }
0258 
0259     for (const auto& volume : m_volumes) {
0260       volume->visitVolumes(visitor);
0261     }
0262   }
0263 
0264   /// Returns the VolumeName - for debug reason, might be depreciated later
0265   const std::string& volumeName() const;
0266 
0267   /// Return the material of the volume
0268   const IVolumeMaterial* volumeMaterial() const;
0269 
0270   /// Return the material of the volume as shared pointer
0271   const std::shared_ptr<const IVolumeMaterial>& volumeMaterialSharedPtr() const;
0272 
0273   /// Set the volume material description
0274   ///
0275   /// The material is usually derived in a complicated way and loaded from
0276   /// a framework given source. As various volumes could potentially share the
0277   /// the same material description, it is provided as a shared object
0278   ///
0279   /// @param material Material description of this volume
0280   void assignVolumeMaterial(std::shared_ptr<const IVolumeMaterial> material);
0281 
0282   /// Return the MotherVolume - if it exists
0283   const TrackingVolume* motherVolume() const;
0284 
0285   /// Return the MotherVolume - if it exists
0286   TrackingVolume* motherVolume();
0287 
0288   /// Set the MotherVolume
0289   ///
0290   /// @param mvol is the mother volume
0291   void setMotherVolume(TrackingVolume* mvol);
0292 
0293   using MutableVolumeRange =
0294       detail::TransformRange<detail::Dereference,
0295                              std::vector<std::unique_ptr<TrackingVolume>>>;
0296   using VolumeRange = detail::TransformRange<
0297       detail::ConstDereference,
0298       const std::vector<std::unique_ptr<TrackingVolume>>>;
0299 
0300   /// Return all volumes registered under this tracking volume
0301   /// @return the range of volumes
0302   VolumeRange volumes() const;
0303 
0304   /// Return mutable view of the registered volumes under this tracking volume
0305   /// @return the range of volumes
0306   MutableVolumeRange volumes();
0307 
0308   /// Add a child volume to this tracking volume
0309   /// @param volume The volume to add
0310   /// @note The @p volume will have its mother volume assigned to @p this.
0311   ///       It will throw if @p volume already has a mother volume set
0312   /// @return Reference to the added volume
0313   TrackingVolume& addVolume(std::unique_ptr<TrackingVolume> volume);
0314 
0315   /// Interface of @c TrackingVolume in the Gen1 geometry model
0316   /// @note This interface is being replaced, and is subject to removal
0317   ///
0318   /// @{
0319 
0320   /// Return the associated Layer to the global position
0321   ///
0322   /// @param gctx The current geometry context object, e.g. alignment
0323   /// @param position is the associated global position
0324   ///
0325   /// @return plain pointer to layer object
0326   const Layer* associatedLayer(const GeometryContext& gctx,
0327                                const Vector3& position) const;
0328 
0329   /// @brief Resolves the volume into (compatible) Layers
0330   ///
0331   /// This is the method for the propagator/extrapolator
0332   /// @tparam options_t Type of navigation options object for decomposition
0333   ///
0334   /// @param gctx The current geometry context object, e.g. alignment
0335   /// @param position Position for the search
0336   /// @param direction Direction for the search
0337   /// @param options The templated navigation options
0338   ///
0339   /// @return vector of compatible intersections with layers
0340   boost::container::small_vector<LayerIntersection, 10> compatibleLayers(
0341       const GeometryContext& gctx, const Vector3& position,
0342       const Vector3& direction, const NavigationOptions<Layer>& options) const;
0343 
0344   /// @brief Returns all boundary surfaces sorted by the user.
0345   ///
0346   /// @tparam options_t Type of navigation options object for decomposition
0347   /// @tparam sorter_t Type of the boundary surface sorter
0348   ///
0349   /// @param gctx The current geometry context object, e.g. alignment
0350   /// @param position The position for searching
0351   /// @param direction The direction for searching
0352   /// @param options The templated navigation options
0353   /// @param logger A @c Logger instance
0354   ///
0355   /// @return is the templated boundary intersection
0356   boost::container::small_vector<BoundaryIntersection, 4> compatibleBoundaries(
0357       const GeometryContext& gctx, const Vector3& position,
0358       const Vector3& direction, const NavigationOptions<Surface>& options,
0359       const Logger& logger = getDummyLogger()) const;
0360 
0361   /// Return the confined static layer array - if it exists
0362   /// @return the BinnedArray of static layers if exists
0363   const LayerArray* confinedLayers() const;
0364 
0365   /// Return the confined volumes of this container array - if it exists
0366   std::shared_ptr<const TrackingVolumeArray> confinedVolumes() const;
0367 
0368   /// Return the confined dense volumes
0369   const MutableTrackingVolumeVector denseVolumes() const;
0370 
0371   /// Method to return the BoundarySurfaces
0372   const TrackingVolumeBoundaries& boundarySurfaces() const;
0373 
0374   /// Set the boundary surface material description
0375   ///
0376   /// The material is usually derived in a complicated way and loaded from
0377   /// a framework given source. As various volumes could potentially share the
0378   /// the same material description, it is provided as a shared object
0379   ///
0380   /// @param surfaceMaterial Material description of this volume
0381   /// @param bsFace Specifies which boundary surface to assign the material to
0382   void assignBoundaryMaterial(
0383       std::shared_ptr<const ISurfaceMaterial> surfaceMaterial,
0384       BoundarySurfaceFace bsFace);
0385 
0386   /// Glue another tracking volume to this one
0387   ///  - if common face is set the glued volumes are sharing the boundary, down
0388   /// to the last navigation volume
0389   ///
0390   /// @param gctx The current geometry context object, e.g. alignment
0391   /// @param bsfMine is the boundary face indicater where to glue
0392   /// @param neighbor is the TrackingVolume to be glued
0393   /// @param bsfNeighbor is the boundary surface of the neighbor
0394   void glueTrackingVolume(const GeometryContext& gctx,
0395                           BoundarySurfaceFace bsfMine, TrackingVolume* neighbor,
0396                           BoundarySurfaceFace bsfNeighbor);
0397 
0398   /// Glue another tracking volume to this one
0399   ///  - if common face is set the glued volumes are sharing the boundary, down
0400   /// to the last navigation volume
0401   ///
0402   /// @param gctx The current geometry context object, e.g. alignment
0403   /// @param bsfMine is the boundary face indicater where to glue
0404   /// @param neighbors are the TrackingVolumes to be glued
0405   /// @param bsfNeighbor are the boundary surface of the neighbors
0406   void glueTrackingVolumes(
0407       const GeometryContext& gctx, BoundarySurfaceFace bsfMine,
0408       const std::shared_ptr<TrackingVolumeArray>& neighbors,
0409       BoundarySurfaceFace bsfNeighbor);
0410 
0411   /// Provide a new BoundarySurface from the glueing
0412   ///
0413   /// @param bsf is the boundary face indicater where to glue
0414   /// @param bs is the new boundary surface
0415   /// @param checkmaterial is a flag how to deal with material, if true:
0416   /// - if the old boundary surface had a material description
0417   ///   but the new one has not, keep the current one
0418   /// - in all other cases just assign the new boundary surface
0419   void updateBoundarySurface(
0420       BoundarySurfaceFace bsf,
0421       std::shared_ptr<const BoundarySurfaceT<TrackingVolume>> bs,
0422       bool checkmaterial = true);
0423 
0424   /// Register the outside glue volumes -
0425   /// ordering is in the TrackingVolume Frame:
0426   ///  - negativeFaceXY
0427   ///  - (faces YZ, ZY, radial faces)
0428   ///  - positiveFaceXY
0429   ///
0430   /// @param gvd register a new GlueVolumeDescriptor
0431   /// @todo update to shared/unique ptr
0432   void registerGlueVolumeDescriptor(GlueVolumesDescriptor* gvd);
0433 
0434   /// Register the outside glue volumes -
0435   /// ordering is in the TrackingVolume Frame:
0436   ///  - negativeFaceXY
0437   ///  - (faces YZ, ZY, radial faces)
0438   ///  - positiveFaceXY
0439   GlueVolumesDescriptor& glueVolumesDescriptor();
0440 
0441  private:
0442   void connectDenseBoundarySurfaces(
0443       MutableTrackingVolumeVector& confinedDenseVolumes);
0444 
0445   /// interlink the layers in this TrackingVolume
0446   void interlinkLayers();
0447 
0448   /// Create Boundary Surface
0449   void createBoundarySurfaces();
0450 
0451   /// method to synchronize the layers with potentially updated volume bounds:
0452   /// - adapts the layer dimensions to the new volumebounds + envelope
0453   ///
0454   /// @param envelope is the clearance between volume boundary and layer
0455   void synchronizeLayers(double envelope = 1.) const;
0456 
0457   // the boundary surfaces
0458   std::vector<TrackingVolumeBoundaryPtr> m_boundarySurfaces;
0459 
0460   ///(a) static configuration ordered by Binned arrays
0461   /// static layers
0462   std::unique_ptr<const LayerArray> m_confinedLayers = nullptr;
0463 
0464   /// Array of Volumes inside the Volume when actin as container
0465   std::shared_ptr<const TrackingVolumeArray> m_confinedVolumes = nullptr;
0466 
0467   /// confined dense
0468   MutableTrackingVolumeVector m_confinedDenseVolumes;
0469 
0470   /// Volumes to glue Volumes from the outside
0471   GlueVolumesDescriptor* m_glueVolumeDescriptor{nullptr};
0472 
0473   /// @}
0474 
0475  private:
0476   /// close the Geometry, i.e. set the GeometryIdentifier and assign material
0477   ///
0478   /// @param materialDecorator is a dedicated decorator for the
0479   ///        material to be assigned (surface, volume based)
0480   /// @param volumeMap is a map to find the a volume by identifier
0481   /// @param vol is the geometry id of the volume
0482   ///        as calculated by the TrackingGeometry
0483   /// @param hook Identifier hook to be applied to surfaces
0484   /// @param logger A @c Logger instance
0485   ///
0486   void closeGeometry(
0487       const IMaterialDecorator* materialDecorator,
0488       std::unordered_map<GeometryIdentifier, const TrackingVolume*>& volumeMap,
0489       std::size_t& vol, const GeometryIdentifierHook& hook,
0490       const Logger& logger = getDummyLogger());
0491 
0492   /// The volume based material the TrackingVolume consists of
0493   std::shared_ptr<const IVolumeMaterial> m_volumeMaterial{nullptr};
0494 
0495   /// Remember the mother volume
0496   TrackingVolume* m_motherVolume{nullptr};
0497 
0498   /// Volume name for debug reasons & screen output
0499   std::string m_name;
0500 
0501   std::vector<std::unique_ptr<TrackingVolume>> m_volumes;
0502 };
0503 
0504 }  // namespace Acts