Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 07:52:24

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/Geometry/BlueprintOptions.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/Geometry/NavigationPolicyFactory.hpp"
0017 #include "Acts/Utilities/AxisDefinitions.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include "Acts/Utilities/TransformRange.hpp"
0020 
0021 #include <iosfwd>
0022 #include <memory>
0023 #include <string>
0024 #include <vector>
0025 
0026 namespace Acts {
0027 
0028 class Volume;
0029 class TrackingVolume;
0030 class VolumeBounds;
0031 class PortalShellBase;
0032 
0033 namespace Experimental {
0034 
0035 class MaterialDesignatorBlueprintNode;
0036 class StaticBlueprintNode;
0037 class LayerBlueprintNode;
0038 class GeometryIdentifierBlueprintNode;
0039 
0040 class CylinderContainerBlueprintNode;
0041 class CuboidContainerBlueprintNode;
0042 
0043 /// Base class for all nodes in the blueprint tree. This class defines the
0044 /// three-phase construction process. The three phases are
0045 ///
0046 /// -# **Build**: Construct volume representation + compute final sizing
0047 /// -# **Connect**: Create and connect portals at volume boundaries
0048 /// -# **Finalize**: Register portals with volumes + create acceleration
0049 ///    structures
0050 ///
0051 /// During the *build* phase, the `build` method of all nodes in the tree are
0052 /// called recursively. Some nodes, like @ref Acts::Experimental::ContainerBlueprintNode,
0053 /// will take action on the volumes returns from its children, and perform
0054 /// sizing to connect them. See the @ref Acts::Experimental::ContainerBlueprintNode
0055 /// and @ref Acts::CylinderVolumeStack documentation for details on how the
0056 /// sizing is carried out.
0057 class BlueprintNode {
0058  public:
0059   /// Virtual destructor to ensure correct cleanup
0060   virtual ~BlueprintNode() = default;
0061 
0062   /// Get the name of this node
0063   virtual const std::string& name() const = 0;
0064 
0065   /// @anchor construction
0066   /// @name Construction methods
0067   /// These methods constitute the primary interface of the node that
0068   /// participates in the geometry construction.
0069   /// @{
0070 
0071   /// This method is called during the *build* phase of the blueprint tree
0072   /// construction. It returns a single @ref Acts::Volume which represents transform
0073   /// and bounds of the entire subtree. This does not have to correspond to the
0074   /// final @ref Acts::TrackingVolume, some node types will produce temporary volume
0075   /// representations. Lifetime of the returned volume is managed by the source
0076   /// node!
0077   /// Nodes higher in the hierarchy will issue resizes down the tree hierarchy.
0078   /// This is not done through a direct hierarchy, but coordinated by the
0079   /// respective node type, by internally consulting its children.
0080   ///
0081   /// @note Generally, you should not need to to call this method directly.
0082   ///       The construction should usually be done through the special
0083   ///       @ref Acts::Experimental::Blueprint class.
0084   ///
0085   /// @param options The global construction options
0086   /// @param gctx The geometry context for construction (usually nominal)
0087   /// @param logger The logger to use for output during construction
0088   /// @return The volume used for communicating transform and size up the hierarchy
0089   virtual Volume& build(const BlueprintOptions& options,
0090                         const GeometryContext& gctx,
0091                         const Logger& logger = Acts::getDummyLogger()) = 0;
0092 
0093   /// This method is called during the *connect* phase. This phase handles the
0094   /// creation and connection of *portals* (instances of @ref Acts::PortalLinkBase).
0095   /// After the build-phase has completed, the volume sizes are **final**. Each
0096   /// node will consult its fully sized volume to produce *boundary surfaces*.
0097   /// Each boundary surface is then turned into a @ref Acts::TrivialPortalLink, which
0098   /// in turn produces a one-sided portal (see @ref Acts::Portal documentation)
0099   ///
0100   /// Some nodes (like @ref Acts::Experimental::ContainerBlueprintNode) will take action on
0101   /// their children, and unify the connected portals.
0102   ///
0103   /// After a node's processing has completed, it returns a reference to a @ref
0104   /// Acts::PortalShellBase, which represents a set of portals in a specific
0105   /// geometry arrangement. The returned object lifetime is managed by the
0106   /// returning node.
0107   ///
0108   /// @param options The global construction options
0109   /// @param gctx The geometry context for construction (usually nominal)
0110   /// @param logger The logger to use for output during construction
0111   virtual PortalShellBase& connect(
0112       const BlueprintOptions& options, const GeometryContext& gctx,
0113       const Logger& logger = Acts::getDummyLogger()) = 0;
0114 
0115   /// This method is called during the *finalize* phase. This phase handles:
0116   ///
0117   /// - Registering portals into their final volumes
0118   /// - Registering volumes into their parents
0119   /// - Creating navigation policies
0120   /// - (In future) Handle geometry identification assignment
0121   ///
0122   /// At the end of this phase, each node will have transferred any temporary
0123   /// resources created during the build, that need to be retained, into the
0124   /// final @ref Acts::TrackingGeometry, and can be safely destroyed.
0125   ///
0126   /// @note The @p parent for volumes, portals, etc to be registered in is passed in **as an
0127   ///       argument**, rather than being implicitly determined from the
0128   ///       **parent node**. This is done so that nodes can remove themselves
0129   ///       from the final volume hierarchy, like container nodes or the
0130   ///       @ref Acts::Experimental::MaterialDesignatorBlueprintNode.
0131   ///
0132   /// @param options The global construction options
0133   /// @param gctx The geometry context for construction (usually nominal)
0134   /// @param parent The parent volume to register in
0135   /// @param logger The logger to use for output during construction
0136   virtual void finalize(const BlueprintOptions& options,
0137                         const GeometryContext& gctx, TrackingVolume& parent,
0138                         const Logger& logger = Acts::getDummyLogger()) = 0;
0139 
0140   /// @}
0141 
0142   /// @anchor convenience
0143   /// @name Convenience methods
0144   /// These methods are meant to make the construction of a blueprint tree in
0145   /// code more ergonomic.
0146   /// They usually take an optional `callback` parameter. The primary use for
0147   /// this parameter is structural, as it facilitates introducing scopes to
0148   /// indicate in code that objects are nested.
0149   ///
0150   /// ```cpp
0151   /// Blueprint::Config cfg;
0152   /// auto root = std::make_unique<Blueprint>(cfg);
0153   /// root->addStaticVolume(
0154   ///     base, std::make_shared<CylinderVolumeBounds>(50_mm, 400_mm, 1000_mm),
0155   ///     "PixelWrapper", [&](auto& wrapper) {
0156   ///         // This scope can be used to equip `wrapper`
0157   ///     });
0158   /// ```
0159   ///
0160   /// Alternatively, they can also be used without a callback, as the newly
0161   /// created node is also returned by reference:
0162   ///
0163   /// ```
0164   /// auto& wrapper = root->addStaticVolume(
0165   ///     base, std::make_shared<CylinderVolumeBounds>(50_mm, 400_mm, 1000_mm),
0166   ///     "PixelWrapper");
0167   /// ```
0168   ///
0169   /// In both cases, it's not necessary to register the newly created node
0170   /// with a parent node.
0171   ///
0172   /// @{
0173 
0174   /// This method creates a new @ref Acts::Experimental::StaticBlueprintNode wrapping @p
0175   /// volume and adds it to this node as a child.
0176   /// @param volume The volume to add
0177   /// @param callback An optional callback that receives the node as an argument
0178   /// @return A reference to the created node
0179   StaticBlueprintNode& addStaticVolume(
0180       std::unique_ptr<TrackingVolume> volume,
0181       const std::function<void(StaticBlueprintNode& cylinder)>& callback = {});
0182 
0183   /// Alternative overload for creating a @ref Acts::Experimental::StaticBlueprintNode. This
0184   /// overload will invoke the constructor of @ref Acts::TrackingVolume and use
0185   /// that volume to create the node.
0186   /// @param transform The transform of the volume
0187   /// @param volumeBounds The bounds of the volume
0188   /// @param volumeName The name of the volume
0189   /// @param callback An optional callback that receives the node as an argument
0190   StaticBlueprintNode& addStaticVolume(
0191       const Transform3& transform, std::shared_ptr<VolumeBounds> volumeBounds,
0192       const std::string& volumeName = "undefined",
0193       const std::function<void(StaticBlueprintNode& cylinder)>& callback = {});
0194 
0195   /// Convenience method for creating a cylinder specialization of @ref Acts::Experimental::ContainerBlueprintNode.
0196   /// @param name The name of the container node. This name is only reflected
0197   ///             in the node tree for debugging, as no extra volumes is created
0198   ///             for the container.
0199   /// @param direction The direction of the stack configuration. See
0200   ///                  @ref Acts::CylinderVolumeStack for details.
0201   /// @param callback An optional callback that receives the node as an argument
0202   CylinderContainerBlueprintNode& addCylinderContainer(
0203       const std::string& name, AxisDirection direction,
0204       const std::function<void(CylinderContainerBlueprintNode& cylinder)>&
0205           callback = {});
0206 
0207   /// Convenience method for creating a cuboid specialization of @ref Acts::Experimental::ContainerBlueprintNode.
0208   /// @param name The name of the container node. This name is only reflected
0209   ///             in the node tree for debugging, as no extra volumes is created
0210   ///             for the container.
0211   /// @param direction The direction of the stack configuration. See
0212   ///                  @ref Acts::CuboidVolumeStack for details.
0213   /// @param callback An optional callback that receives the node as an argument
0214   CuboidContainerBlueprintNode& addCuboidContainer(
0215       const std::string& name, AxisDirection direction,
0216       const std::function<void(CuboidContainerBlueprintNode& cylinder)>&
0217           callback = {});
0218 
0219   /// Convenience method for creating a @ref Acts::Experimental::MaterialDesignatorBlueprintNode.
0220   /// @param name The name of the material designator node. Used for debugging
0221   ///             the node tree only.
0222   /// @param callback An optional callback that receives the node as an argument
0223   MaterialDesignatorBlueprintNode& addMaterial(
0224       const std::string& name,
0225       const std::function<void(MaterialDesignatorBlueprintNode& material)>&
0226           callback = {});
0227 
0228   /// Convenience method for creating a @ref Acts::Experimental::LayerBlueprintNode.
0229   /// @param name The name of the layer node.
0230   /// @param callback An optional callback that receives the node as an argument
0231   LayerBlueprintNode& addLayer(
0232       const std::string& name,
0233       const std::function<void(LayerBlueprintNode& layer)>& callback = {});
0234 
0235   /// Convenience method for creating a @ref Acts::Experimental::GeometryIdentifierBlueprintNode.
0236   /// @param callback An optional callback that receives the node as an argument
0237   GeometryIdentifierBlueprintNode& withGeometryIdentifier(
0238       const std::function<void(
0239           GeometryIdentifierBlueprintNode& geometryIdentifier)>& callback = {});
0240 
0241   /// @}
0242 
0243   /// Register a @p child to this node.
0244   /// @warning This method throws if adding the child would create a
0245   ///          cycle in the blueprint tree!
0246   /// @param child The child node to add
0247   /// @return A reference this node (not the child!)
0248   BlueprintNode& addChild(std::shared_ptr<BlueprintNode> child);
0249 
0250   /// A range-like object that allows range based for loops and index access.
0251   /// This type's iterators and accessors return mutable references when
0252   /// dereferenced.
0253   using MutableChildRange =
0254       detail::TransformRange<detail::Dereference,
0255                              std::vector<std::shared_ptr<BlueprintNode>>>;
0256 
0257   /// A range-like object that allows range based for loops and index access.
0258   /// This type's iterators and accessors return const references when
0259   /// dereferenced.
0260   using ChildRange =
0261       detail::TransformRange<detail::ConstDereference,
0262                              const std::vector<std::shared_ptr<BlueprintNode>>>;
0263 
0264   /// Return a @ref MutableChildRange to the children of this node.
0265   /// @return A range-like object to the children
0266   MutableChildRange children();
0267 
0268   /// Return a @ref ChildRange to the children of this node.
0269   /// @return A range-like object to the children
0270   ChildRange children() const;
0271 
0272   /// Remove all children from this node
0273   void clearChildren();
0274 
0275   /// Return the depth of this node in the blueprint tree. A depth of zero means
0276   /// this node does not have a parent.
0277   /// @return The depth of this node
0278   std::size_t depth() const;
0279 
0280   /// Print the node tree starting from this node to graphviz format
0281   /// @param os The stream to print to
0282   void graphviz(std::ostream& os) const;
0283 
0284   /// Method that writes a representatiohn of **this node only** to graphviz.
0285   /// This should generally not be called on its own, but through the @ref
0286   /// BlueprintNode::graphviz method.
0287   /// @param os The stream to print to
0288   virtual void addToGraphviz(std::ostream& os) const;
0289 
0290   /// Print a representation of this node to the stream
0291   /// @param os The stream to print to
0292   /// @param node The node to print
0293   /// @return The output stream
0294   friend std::ostream& operator<<(std::ostream& os, const BlueprintNode& node) {
0295     node.toStream(os);
0296     return os;
0297   }
0298 
0299  protected:
0300   /// Virtual method to determine stream representation.
0301   /// @note This method is called by the stream operator.
0302   virtual void toStream(std::ostream& os) const;
0303 
0304   /// Set the depth to @p depth and update children recursively
0305   void setDepth(std::size_t depth);
0306 
0307   /// Printing helper returning a prefix including an indent depending on the
0308   /// depth.
0309   /// @return The prefix string
0310   std::string prefix() const;
0311 
0312   /// An indentation depending on the depth of this node.
0313   /// @return The indentation string
0314   std::string indent() const;
0315 
0316  private:
0317   std::size_t m_depth{0};
0318   std::vector<std::shared_ptr<BlueprintNode>> m_children{};
0319 };
0320 
0321 }  // namespace Experimental
0322 }  // namespace Acts