Skip to content

Commit

Permalink
feat: adapt visitor concept (#2901)
Browse files Browse the repository at this point in the history
This PR enhances the visitor pattern for the Acts geometry.

It adds a non-const visitor pattern which will allow  to also use the visitor pattern to set the material to the new detector geometry and will replace this `IMaterialProvider` mechanism and will rely on the same recursive visiting.

The unit tests show how this can be used to assign material to a pre-built geometry instance.

Note: The new `visitSurfaces` method of the `TrackingGeometry` will now visit all reachable surfaces, and not only the sensitive ones. This allows it to e.g. extract material surfaces and will remove a lot of duplicated code in `SurfaceMaterialMapper` and `VolumeMaterialMapper` that manually walk through the `TrackingGeometry` hierarchy.
  • Loading branch information
asalzburger authored Jan 29, 2024
1 parent 6aeeeda commit 5166de1
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 60 deletions.
71 changes: 70 additions & 1 deletion Core/include/Acts/Detector/Detector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Common.hpp"
#include "Acts/Detector/DetectorVolume.hpp"
#include "Acts/Detector/DetectorVolumeVisitorConcept.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/SurfaceVisitorConcept.hpp"
#include "Acts/Navigation/NavigationDelegates.hpp"
#include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
#include "Acts/Utilities/Concepts.hpp"
#include "Acts/Utilities/Delegate.hpp"

Expand Down Expand Up @@ -109,13 +110,81 @@ class Detector : public std::enable_shared_from_this<Detector> {
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
///
/// @note due to the fact that portals can be shared between volumes, multiple
/// visits may occur, duplicated addressing needs to be taken care of by the
/// visitor
template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
void visitSurfaces(visitor_t&& visitor) const {
for (const auto& v : rootVolumes()) {
v->template visitSurfaces<visitor_t>(std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable surfaces of the detector - non-const
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
///
/// @note due to the fact that this doesn't run over root volumes, and
/// due to the fact that portals can be shared between volumes, multiple
/// visits may occur, duplicated addressing needs to be taken care of by the
template <ACTS_CONCEPT(MutableSurfaceVisitor) visitor_t>
void visitMutableSurfaces(visitor_t&& visitor) {
for (auto& v : volumePtrs()) {
v->template visitMutableSurfaces<visitor_t>(
std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable detector volumes of the detector
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
template <ACTS_CONCEPT(DetectorVolumeVisitor) visitor_t>
void visitVolumes(visitor_t&& visitor) const {
for (const auto& v : rootVolumes()) {
v->template visitVolumes<visitor_t>(std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable detector volumes of the detector - non-const
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
///
/// @note that due to non running over root volumes, multiple visits
/// may occur, duplicated addressing needs to be taken care of by the
/// visitor
template <ACTS_CONCEPT(MutableDetectorVolumeVisitor) visitor_t>
void visitMutableVolumes(visitor_t&& visitor) {
for (const auto& v : volumePtrs()) {
v->template visitMutableVolumes<visitor_t>(
std::forward<visitor_t>(visitor));
}
}

/// Update the current volume of a given navigation state
///
/// @param gctx is the Geometry context of the call
Expand Down
60 changes: 58 additions & 2 deletions Core/include/Acts/Detector/DetectorVolume.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Common.hpp"
#include "Acts/Detector/DetectorVolumeVisitorConcept.hpp"
#include "Acts/Detector/Portal.hpp"
#include "Acts/Detector/PortalGenerators.hpp"
#include "Acts/Geometry/Extent.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/SurfaceVisitorConcept.hpp"
#include "Acts/Geometry/VolumeBounds.hpp"
#include "Acts/Material/IVolumeMaterial.hpp"
#include "Acts/Navigation/NavigationDelegates.hpp"
#include "Acts/Navigation/NavigationState.hpp"
#include "Acts/Surfaces/BoundaryCheck.hpp"
#include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
#include "Acts/Utilities/BoundingBox.hpp"
#include "Acts/Utilities/Concepts.hpp"
#include "Acts/Utilities/Delegate.hpp"
Expand Down Expand Up @@ -296,13 +297,68 @@ class DetectorVolume : public std::enable_shared_from_this<DetectorVolume> {
visitor(s);
}
for (const auto& p : portals()) {
p->visitSurfaces(std::forward<visitor_t>(visitor));
p->visitSurface(std::forward<visitor_t>(visitor));
}
for (const auto& v : volumes()) {
v->visitSurfaces(std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable surfaces of the detector - non-const
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be called for each found surface,
/// it will be handed down to contained volumes and portals
template <ACTS_CONCEPT(MutableSurfaceVisitor) visitor_t>
void visitMutableSurfaces(visitor_t&& visitor) {
for (auto& s : surfacePtrs()) {
visitor(s.get());
}
for (auto& p : portalPtrs()) {
p->visitMutableSurface(std::forward<visitor_t>(visitor));
}
for (auto& v : volumePtrs()) {
v->visitMutableSurfaces(std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable detector volumes of the detector
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
template <ACTS_CONCEPT(DetectorVolumeVisitor) visitor_t>
void visitVolumes(visitor_t&& visitor) const {
visitor(this);
for (const auto& v : volumes()) {
v->visitVolumes(std::forward<visitor_t>(visitor));
}
}

/// @brief Visit all reachable detector volumes of the detector - non-const
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be handed to each root volume,
/// eventually contained volumes within the root volumes are
/// handled by the root volume
///
/// @note if a context is needed for the visit, the vistitor has to provide
/// it, e.g. as a private member
template <ACTS_CONCEPT(MutableDetectorVolumeVisitor) visitor_t>
void visitMutableVolumes(visitor_t&& visitor) {
visitor(this);
for (auto& v : volumePtrs()) {
v->visitMutableVolumes(std::forward<visitor_t>(visitor));
}
}

/// This method allows to udate the navigation state updator
/// module.
///
Expand Down
32 changes: 32 additions & 0 deletions Core/include/Acts/Detector/DetectorVolumeVisitorConcept.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/.

#pragma once

#if defined(__cpp_concepts)
#include <concepts>

namespace Acts {

namespace Experimental {
class DetectorVolume;
}

template <typename T>
concept DetectorVolumeVisitor = requires(T v) {
{v(std::declval<const Experimental::DetectorVolume*>())};
};

template <typename T>
concept MutableDetectorVolumeVisitor = requires(T v) {
{v(std::declval<Experimental::DetectorVolume*>())};
};

} // namespace Acts

#endif
14 changes: 12 additions & 2 deletions Core/include/Acts/Detector/Portal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
#include "Acts/Definitions/Direction.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/SurfaceVisitorConcept.hpp"
#include "Acts/Navigation/NavigationDelegates.hpp"
#include "Acts/Navigation/NavigationState.hpp"
#include "Acts/Surfaces/BoundaryCheck.hpp"
#include "Acts/Surfaces/RegularSurface.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
#include "Acts/Utilities/Concepts.hpp"

#include <array>
Expand Down Expand Up @@ -75,7 +75,17 @@ class Portal {
///
/// @param visitor will be called with the represented surface
template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
void visitSurfaces(visitor_t&& visitor) const {
void visitSurface(visitor_t&& visitor) const {
visitor(m_surface.get());
}

/// @brief Visit all reachable surfaces of the detector - non-const
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor will be called with the represented surface
template <ACTS_CONCEPT(MutableSurfaceVisitor) visitor_t>
void visitMutableSurface(visitor_t&& visitor) {
visitor(m_surface.get());
}

Expand Down
40 changes: 37 additions & 3 deletions Core/include/Acts/Geometry/TrackingGeometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/SurfaceVisitorConcept.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Geometry/TrackingVolumeVisitorConcept.hpp"
#include "Acts/Surfaces/SurfaceVisitorConcept.hpp"
#include "Acts/Utilities/Concepts.hpp"
#include "Acts/Utilities/Logger.hpp"

Expand Down Expand Up @@ -100,15 +101,48 @@ class TrackingGeometry {
/// (could be a null pointer)
const Surface* getBeamline() const;

/// @brief Visit all reachable surfaces
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor The callable. Will be called for each reachable surface
/// that is found, a selection of the surfaces can be done in the visitor
/// @param restrictToSensitives If true, only sensitive surfaces are visited
///
/// @note If a context is needed for the visit, the vistitor has to provide
/// this, e.g. as a private member
template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
void visitSurfaces(visitor_t&& visitor, bool restrictToSensitives) const {
highestTrackingVolume()->template visitSurfaces<visitor_t>(
std::forward<visitor_t>(visitor), restrictToSensitives);
}

/// @brief Visit all sensitive surfaces
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor The callable. Will be called for each sensitive surface
/// that is found
/// that is found, a selection of the surfaces can be done in the visitor
///
/// @note If a context is needed for the visit, the vistitor has to provide
/// this, e.g. as a private member
template <ACTS_CONCEPT(SurfaceVisitor) visitor_t>
void visitSurfaces(visitor_t&& visitor) const {
highestTrackingVolume()->template visitSurfaces<visitor_t>(
visitSurfaces(std::forward<visitor_t>(visitor), true);
}

/// @brief Visit all reachable tracking volumes
///
/// @tparam visitor_t Type of the callable visitor
///
/// @param visitor The callable. Will be called for each reachable volume
/// that is found, a selection of the volumes can be done in the visitor
///
/// @note If a context is needed for the visit, the vistitor has to provide
/// this, e.g. as a private member
template <ACTS_CONCEPT(TrackingVolumeVisitor) visitor_t>
void visitVolumes(visitor_t&& visitor) const {
highestTrackingVolume()->template visitVolumes<visitor_t>(
std::forward<visitor_t>(visitor));
}

Expand Down
Loading

0 comments on commit 5166de1

Please sign in to comment.