Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-05 08:29:29

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2024 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/Definitions/Direction.hpp"
0013 #include "Acts/Utilities/BinningType.hpp"
0014 #include "Acts/Utilities/Logger.hpp"
0015 #include "Acts/Utilities/Result.hpp"
0016 
0017 #include <memory>
0018 
0019 namespace Acts {
0020 
0021 class RegularSurface;
0022 class GeometryContext;
0023 class TrackingVolume;
0024 class CylinderSurface;
0025 class PlaneSurface;
0026 class DiscSurface;
0027 class Surface;
0028 
0029 class PortalLinkBase;
0030 
0031 /// Exception thrown when portals cannot be merged
0032 class PortalMergingException : public std::exception {
0033   const char* what() const noexcept override;
0034 };
0035 
0036 /// Exception thrown when portals cannot be fused
0037 class PortalFusingException : public std::exception {
0038   const char* what() const noexcept override;
0039 };
0040 
0041 /// A portal connects two or more neighboring volumes. Each volume has a set of
0042 /// portals that describes which volumes lie behind the portal in that
0043 /// direction. Portals use associated portal links to perform lookups of target
0044 /// volumes.
0045 /// Each portal has two links, and a corresponding surface. One link is
0046 /// associated with the direction along the surface's normal vector, and one
0047 /// with the opposite direction.
0048 class Portal {
0049  public:
0050   /// Constructor for a portal from a single link
0051   /// @param direction The direction of the link
0052   /// @param link The portal link
0053   Portal(Direction direction, std::unique_ptr<PortalLinkBase> link);
0054 
0055   /// Constructor for a portal from a surface and volume, where a trivial portal
0056   /// link is automatically constructed.
0057   /// @param direction The direction of the link
0058   /// @param surface The surface from which to create the portal link
0059   /// @param volume The volume this portal connects to in the @p direction
0060   ///               relative to the normal of @p surface.
0061   Portal(Direction direction, std::shared_ptr<RegularSurface> surface,
0062          TrackingVolume& volume);
0063 
0064   /// Constructor for a portal from two links. One of the links can be
0065   /// `nullptr`, but at least one of them needs to be set. If both are set, they
0066   /// need to be valid compatible links that can be fused.
0067   /// @param gctx The geometry context
0068   /// @param alongNormal The link along the normal of the surface
0069   /// @param oppositeNormal The link opposite to the normal of the
0070   Portal(const GeometryContext& gctx,
0071          std::unique_ptr<PortalLinkBase> alongNormal,
0072          std::unique_ptr<PortalLinkBase> oppositeNormal);
0073 
0074   /// Helper struct for the arguments to the portal constructor below using
0075   /// designated initializers.
0076   struct Arguments {
0077     /// Aggregate over a surface and a volume with optional semantics
0078     struct Link {
0079       Link() = default;
0080       /// Constructor from a surface and a volume
0081       Link(std::shared_ptr<RegularSurface> surfaceIn, TrackingVolume& volumeIn)
0082           : surface(std::move(surfaceIn)), volume(&volumeIn) {}
0083 
0084       /// The associated surface
0085       std::shared_ptr<RegularSurface> surface = nullptr;
0086       /// The associated volume
0087       TrackingVolume* volume = nullptr;
0088     };
0089 
0090     /// Entry for the link along normal
0091     /// Entry for the link opposite normal
0092     Link alongNormal{};
0093     Link oppositeNormal{};
0094   };
0095 
0096   /// Constructor that takes a geometry context and an rvalue reference to a
0097   /// helper struct from above. This pattern allows you to use designated
0098   /// initializers to construct this object like:
0099   /// ```cpp
0100   /// Portal{gctx, {.oppositeNormal = {cyl1, *vol1}}};
0101   /// Portal{gctx, {.alongNormal = {cyl2, *vol2}}};
0102   /// ```
0103   /// @param gctx The geometry context
0104   /// @param args The struct containing the arguments
0105   Portal(const GeometryContext& gctx, Arguments&& args);
0106 
0107   /// Fuse two portals together. Fusing is the combination of two portal links
0108   /// on the same logical surfaces. The actual surface instances can be
0109   /// different, as long as they are geometrically equivalent (within numerical
0110   /// precision). The resulting portal will have one portal along the shared
0111   /// surface's normal vector, and one opposite that vector.
0112   ///
0113   ///    portal1   portal2
0114   ///      +---+   +---+
0115   ///      |   |   |   |
0116   ///      |   |   |   |
0117   /// <----+   | + |   +---->
0118   ///      |   |   |   |
0119   ///      |   |   |   |
0120   ///      +---+   +---+
0121   ///
0122   /// @note The input portals need to have compatible link loadaout, e.g. one
0123   ///       portal needs to have the *along normal* slot filled, and the
0124   ///       otherone one needs to have the *opposite normal* slot filled. If
0125   ///       portals share a filled slot, the function throws an exception.
0126   /// @note This is a destructive operation on the portals involved
0127   /// @param gctx The geometry context
0128   /// @param aPortal The first portal
0129   /// @param bPortal The second portal
0130   /// @param logger The logger to push output to
0131   static Portal fuse(const GeometryContext& gctx, Portal& aPortal,
0132                      Portal& bPortal, const Logger& logger = getDummyLogger());
0133 
0134   /// Merge two adjacent portals with each other to produce a new portal that
0135   /// encompasses both inputs. It is the complementary operation to the fusing
0136   /// of portals. To be able to merge portals, the surfaces of their associated
0137   /// links need to be *mergeable*, and the portal links need to be compatible.
0138   /// This means that both portals need to have a link along the portal surface
0139   /// normal, opposite the normal, or both. If the equipped links are opposite
0140   /// relative to one another (e.g. one along one opposite), the function will
0141   /// throw an exception.
0142   ///
0143   ///         ^                     ^
0144   ///         |                     |
0145   ///  portal1|              portal2|
0146   /// +-------+-------+     +-------+-------+
0147   /// |               |  +  |               |
0148   /// +-------+-------+     +-------+-------+
0149   ///         |                     |
0150   ///         |                     |
0151   ///         v                     v
0152   ///
0153   /// @note This is a destructive operation on both portals, their
0154   ///       links will be moved to produce merged links, which can fail
0155   ///       if the portal links are not compatible
0156   /// @param gctx The geometry context
0157   /// @param aPortal The first portal
0158   /// @param bPortal The second portal
0159   /// @param direction The direction of the merge (e.g. along z)
0160   /// @param logger The logger to push output to
0161   static Portal merge(const GeometryContext& gctx, Portal& aPortal,
0162                       Portal& bPortal, BinningValue direction,
0163                       const Logger& logger = getDummyLogger());
0164 
0165   /// Resolve the volume for a 3D position and a direction
0166   /// The @p direction is used to select the right portal link, if it is set.
0167   /// In case no link is found in the specified direction, a `nullptr` is
0168   /// returned.
0169   /// @param gctx The geometry context
0170   /// @param position The 3D position
0171   /// @param direction The direction
0172   /// @return The target volume (can be `nullptr`)
0173   Result<const TrackingVolume*> resolveVolume(const GeometryContext& gctx,
0174                                               const Vector3& position,
0175                                               const Vector3& direction) const;
0176 
0177   /// Set a link on the portal into the slot specified by the direction.
0178   /// @note The surface associated with @p link must be logically equivalent
0179   ///       to the one of the link that's already set on the portal.
0180   /// @param gctx The geometry context
0181   /// @param direction The direction
0182   /// @param link The link to set
0183   void setLink(const GeometryContext& gctx, Direction direction,
0184                std::unique_ptr<PortalLinkBase> link);
0185 
0186   /// Helper function create a trivial portal link based on a surface.
0187   /// @param gctx The geometry context
0188   /// @param direction The direction of the link to create
0189   /// @param surface The surface
0190   /// @note The @p surface must be logically equivalent
0191   ///       to the one of the link that's already set on the portal.
0192   /// @param volume The target volume
0193   void setLink(const GeometryContext& gctx, Direction direction,
0194                std::shared_ptr<RegularSurface> surface, TrackingVolume& volume);
0195 
0196   /// Get the link associated with the @p direction. Can be null if the associated link is unset.
0197   /// @param direction The direction
0198   /// @return The link (can be null)
0199   const PortalLinkBase* getLink(Direction direction) const;
0200 
0201   /// Returns true if the portal is valid, that means it has at least one
0202   /// non-null link associated.Portals can be in an invalid state after they get
0203   /// merged or fused with other portals.
0204   /// @return True if the portal is valid
0205   bool isValid() const;
0206 
0207   /// Create and attach a trivial portal link to the empty slot of this portal
0208   /// @param volume The target volume to connect to
0209   void fill(TrackingVolume& volume);
0210 
0211   /// Access the portal surface that is shared between the two links
0212   /// @return The portal surface
0213   const RegularSurface& surface() const;
0214 
0215  private:
0216   /// Helper to check surface equivalence without checking material status. This
0217   /// is needed because we allow fusing portals with surfaces that are
0218   /// equivalent but one of them has material while the other does not. The
0219   /// normal surface comparison would determine these surfaces as not
0220   /// equivalent.
0221   /// @param gctx The geometry context
0222   /// @param a The first surface
0223   /// @param b The second surface
0224   /// @return True if the surfaces are equivalent
0225   static bool isSameSurface(const GeometryContext& gctx, const Surface& a,
0226                             const Surface& b);
0227 
0228   std::shared_ptr<RegularSurface> m_surface;
0229 
0230   std::unique_ptr<PortalLinkBase> m_alongNormal;
0231   std::unique_ptr<PortalLinkBase> m_oppositeNormal;
0232 };
0233 
0234 }  // namespace Acts