Skip to content

Commit

Permalink
feat: Gen 3 portal shells (#3564)
Browse files Browse the repository at this point in the history
Part of #3502

Blocked by: 
- #3673

---

This pull request introduces the new `PortalShell` classes to the Acts geometry module, along with corresponding unit tests. The changes are primarily focused on adding new functionality for handling portal shells in tracking volumes.

### New Functionality:

* [`Core/include/Acts/Geometry/PortalShell.hpp`](diffhunk://#diff-80595cf723b4c4b0a2cf3de28ac0da38793f2955a2e0ce1dc4fd87381fac79aeR1-R115): Introduced new `PortalShell` classes, including `PortalShellBase`, `CylinderPortalShell`, `SingleCylinderPortalShell`, and `CylinderStackPortalShell`. These classes provide interfaces and implementations for managing portals within cylindrical tracking volumes.
* [`Core/src/Geometry/PortalShell.cpp`](diffhunk://#diff-4d9e1b25351b7d20e1dbdc440060aa02eaab832aabfde0b621c44bf8241ca7b8R1-R387): Implemented the methods for the new `PortalShell` classes, including portal management and validation logic.

### Build System Updates:

* [`Core/src/Geometry/CMakeLists.txt`](diffhunk://#diff-5d46d063bba89d4f5042c2ba4cdfbdcb77335367cb0ce9800dd5d036011e2c56R45): Added the new `PortalShell.cpp` source file to the build system.
* [`Tests/UnitTests/Core/Geometry/CMakeLists.txt`](diffhunk://#diff-569c5da4fca89fb082a2e207221e8d00cde5d6352c26878d8df0e11ef9f148eeR37): Added a new unit test for `PortalShell` to ensure the new functionality is properly tested.
  • Loading branch information
paulgessinger authored Oct 4, 2024
1 parent 81e129b commit 68d0709
Show file tree
Hide file tree
Showing 5 changed files with 1,383 additions and 0 deletions.
225 changes: 225 additions & 0 deletions Core/include/Acts/Geometry/PortalShell.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Geometry/BoundarySurfaceFace.hpp"
#include "Acts/Utilities/BinningType.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <array>
#include <memory>

namespace Acts {

class Portal;
class TrackingVolume;
class GeometryContext;

/// @class PortalShellBase
/// The portal shell of a volume is the set of portals that describes
/// connections "outside" of the volume. Which boundary surfaces of a volume are
/// included in the shell depends on the volume. Portal shells are only used
/// during geometry construction, and are not part of the final geometry
/// description.
///
/// This class is the base class for all portal shells
class PortalShellBase {
public:
/// Virtusl destructor
virtual ~PortalShellBase() = default;

/// Connect a volume to the outer side of all portal shells. Which "side" is
/// "outer" depends on the volume type.
/// This method essentially creates a @c TrivialPortalLink on the unconnected
/// side of each portal that is part of the chell
/// @param volume The volume to connect
virtual void connectOuter(TrackingVolume& volume) = 0;

/// Get the number of portals in the shell. This number depends on the volume
/// type
/// @return The number of portals in the shell
virtual std::size_t size() const = 0;

/// Instruct the shell to register the portals with the volume, handing over
/// shared ownership in the process.
/// @note The target volume depends on the shell type, e.g. composite shells
/// like the @c CylinerStackPortalShell register portals to the *correct*
/// volumes.
virtual void applyToVolume() = 0;

/// Check if a portal is *valid*, e.g. if non of the portals has two
/// unconnected sides.
/// @return True if the shell is valid, false otherwise
virtual bool isValid() const = 0;

/// Get a label for the portal shell for debugging purposes
/// @return A label for the portal shell
virtual std::string label() const = 0;
};

/// @class CylinderPortalShell
/// Base class for cylinder shaped portal shells, e.g. shells for cylinder
/// volumes
class CylinderPortalShell : public PortalShellBase {
public:
/// Enum describing the possible faces of a cylinder portal shell
/// @note These values are synchronized with the BoundarySurfaceFace enum.
/// Once Gen1 is removed, this can be changed.
enum class Face : unsigned int {
PositiveDisc = BoundarySurfaceFace::positiveFaceXY,
NegativeDisc = BoundarySurfaceFace::negativeFaceXY,
OuterCylinder = BoundarySurfaceFace::tubeOuterCover,
InnerCylinder = BoundarySurfaceFace::tubeInnerCover,
NegativePhiPlane = BoundarySurfaceFace::tubeSectorNegativePhi,
PositivePhiPlane = BoundarySurfaceFace::tubeSectorPositivePhi
};

using enum Face;

/// Retrieve the portal associated to the given face. Can be nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual Portal* portal(Face face) = 0;

/// Retrieve a shared_ptr for the portal associated to the given face. Can be
/// nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual std::shared_ptr<Portal> portalPtr(Face face) = 0;

/// Set the portal associated to the given face.
/// @param portal The portal to set
/// @param face The face to set the portal
virtual void setPortal(std::shared_ptr<Portal> portal, Face face) = 0;

/// @copydoc PortalShellBase::connectOuter
void connectOuter(TrackingVolume& volume) override;
};

/// Output stream operator for the CylinderPortalShell::Face enum
/// @param os The output stream
/// @param face The face to output
/// @return The output stream
std::ostream& operator<<(std::ostream& os, CylinderPortalShell::Face face);

/// @class SingleCylinderPortalShell
/// This class describes a cylinder shell containing a single volume. The
/// available faces depend on the configuration of the cylinder volume bounds.
/// If a phi sector is configured, the shell will have corresponding portal
/// slots. If the inner radius is non-zero, the shell will have an inner
/// cylinder portal slot.
class SingleCylinderPortalShell : public CylinderPortalShell {
public:
/// Construct a single cylinder portal shell for the given volume
/// @param volume The volume to create the shell for
explicit SingleCylinderPortalShell(TrackingVolume& volume);

/// @copydoc PortalShellBase::size
std::size_t size() const final;

/// @copydoc CylinderPortalShell::portal
Portal* portal(Face face) final;

/// @copydoc CylinderPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) final;

/// @copydoc CylinderPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) final;

/// @copydoc PortalShellBase::applyToVolume
void applyToVolume() override;

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

private:
std::array<std::shared_ptr<Portal>, 6> m_portals{};

TrackingVolume* m_volume;
};

/// @class CylinderStackPortalShell
/// This class describes a cylinder shell containing multiple volumes. The
/// available faces depend on the configuration of the cylinder volume bounds.
/// @note The stack shell currently does not support phi sectors
/// The stack can be oriented along the (local) z or r direction, which drives
/// the stacking. Depending on the direction, portals on the shells of children
/// are merged or fused. Subsequently, portal access respects shared portals
/// between shells. Below is an illustration of a stack in the r direction:
///
/// Fused +-----------------+
/// portals ----+ | |
/// | | v OuterCylinder
/// | +------+------+
/// | | | |
/// | | | |<--+
/// +--+---+ v | |
/// +---+---------+ |
/// | | | | Shared portal
/// | | |<--+--- (grid)
/// | v | | PositiveDisc
/// +-------------+ |
/// r ^ | | |
/// | | |<--+
/// | | |
/// | +-------------+ InnerCylinder
/// +-----> ^ (if rMin>0)
/// z | |
/// +-----------------+
///
/// @note The shells must be ordered in the given direction
/// Depending on the stack direction, the portal lookup will return different
/// portals. In the illustration above, the `PositiveDisc` portal is shared
/// among all shells, while the `OuterCylinder` and `InnerCylinder` portals are
/// looked up from the innermost and outermost shell in the r direction.
class CylinderStackPortalShell : public CylinderPortalShell {
public:
/// Construct the portal shell stack from the given shells
/// @param gctx The geometry context
/// @param shells The shells to stack
/// @note The shells must be ordered in the given direction
/// @param direction The stacking direction
/// @param logger A logging instance for debugging
CylinderStackPortalShell(const GeometryContext& gctx,
std::vector<CylinderPortalShell*> shells,
BinningValue direction,
const Logger& logger = getDummyLogger());

/// @copydoc PortalShellBase::size
std::size_t size() const final;

/// @copydoc CylinderPortalShell::portal
Portal* portal(Face face) final;

/// @copydoc CylinderPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) final;

/// @copydoc CylinderPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) final;

void applyToVolume() override {
// No-op, because it's a composite portal shell
}

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

private:
BinningValue m_direction;
std::vector<CylinderPortalShell*> m_shells;
bool m_hasInnerCylinder{true};
};

} // namespace Acts
1 change: 1 addition & 0 deletions Core/src/Geometry/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ target_sources(
CompositePortalLink.cpp
PortalLinkBase.cpp
PortalError.cpp
PortalShell.cpp
)
Loading

0 comments on commit 68d0709

Please sign in to comment.