Skip to content

Commit

Permalink
refactor: Add param., navigator, stepper concepts
Browse files Browse the repository at this point in the history
This concept replaces the previously existing concepts for track
parameters, navigators, and steppers with C++20 concepts.
  • Loading branch information
stephenswat committed Aug 26, 2024
1 parent 2cfa5f7 commit 117e606
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 411 deletions.
39 changes: 11 additions & 28 deletions Core/include/Acts/Detector/GeometryCompatibilityConcept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,23 @@

#include "Acts/Detector/DetectorVolume.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Utilities/TypeTraits.hpp"
#include "Acts/Utilities/Concepts.hpp"

namespace Acts::Concepts {

// Types to check compatibility of
template <typename propagator_state_t, typename navigator_t>
using ReturnTypeCurrentVolume =
decltype(std::declval<navigator_t>().currentVolume(
std::declval<propagator_state_t>().navigation));
namespace Acts {

/// @brief Concept ensuring compatibility TrackingGeometry
/// and Detector navigation interfaces with the client code
/// @tparam propagator_state_t Type of the object for navigation state
/// @tparam navigator_t Type of the navigator object
template <typename propagator_state_t, typename navigator_t>
struct NavigationCompatibilityConceptImpl {
/// @brief Ensure that the currentVolume method
/// returns one of the known volume types
constexpr static bool isCurrentVolumePtr =
(Acts::Concepts::identical_to<const TrackingVolume*,
ReturnTypeCurrentVolume, propagator_state_t,
navigator_t> ||
Acts::Concepts::identical_to<const Acts::Experimental::DetectorVolume*,
ReturnTypeCurrentVolume, propagator_state_t,
navigator_t>);

static_assert(isCurrentVolumePtr,
"Return type is not a known volume pointer type");

constexpr static bool value = Acts::Concepts::require<isCurrentVolumePtr>;
concept NavigationCompatibleConcept = requires(propagator_state_t &p,
navigator_t &n) {
requires requires {
{
n.currentVolume(p.navigation)
} -> Concepts::same_as_any_of<const TrackingVolume *,
const Acts::Experimental::DetectorVolume *>;
};
};

template <typename propagator_state_t, typename navigator_t>
constexpr bool NavigationCompatibilityConcept =
NavigationCompatibilityConceptImpl<propagator_state_t, navigator_t>::value;

} // namespace Acts::Concepts
} // namespace Acts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ class GenericCurvilinearTrackParameters
template <typename other_track_parameter_t>
static GenericCurvilinearTrackParameters create(
const other_track_parameter_t& other) {
static_assert(
Concepts::BoundTrackParametersConcept<other_track_parameter_t>);
static_assert(BoundTrackParametersConcept<other_track_parameter_t>);

return GenericCurvilinearTrackParameters(
other.fourPosition(), other.particleHypothesis(), other.covariance());
Expand Down
3 changes: 1 addition & 2 deletions Core/include/Acts/EventData/GenericFreeTrackParameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ class GenericFreeTrackParameters {
template <typename other_track_parameter_t>
static GenericFreeTrackParameters create(
const other_track_parameter_t& other) {
static_assert(
Concepts::FreeTrackParametersConcept<other_track_parameter_t>);
static_assert(FreeTrackParametersConcept<other_track_parameter_t>);

return GenericFreeTrackParameters(
other.parameters(), other.particleHypothesis(), other.covariance());
Expand Down
195 changes: 46 additions & 149 deletions Core/include/Acts/EventData/TrackParametersConcept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Utilities/TypeTraits.hpp"

#include <concepts>
#include <optional>
#include <type_traits>

Expand All @@ -21,155 +22,51 @@ namespace Acts {
class Surface;

namespace Concepts {

// nested types that must be available
template <typename T>
using TypeScalar = typename T::Scalar;
template <typename T>
using TypeParametersVector = typename T::ParametersVector;
template <typename T>
using TypeCovarianceMatrix = typename T::CovarianceMatrix;

template <typename T>
using ReturnTypeParameters = decltype(std::declval<T>().parameters());
template <typename T>
using ReturnTypeCovariance = decltype(std::declval<T>().covariance());
template <typename T>
using ReturnTypeFourPositionFromContext =
decltype(std::declval<T>().fourPosition(std::declval<GeometryContext>()));
template <typename T>
using ReturnTypeFourPosition = decltype(std::declval<T>().fourPosition());
template <typename T>
using ReturnTypePositionFromContext =
decltype(std::declval<T>().position(std::declval<GeometryContext>()));
template <typename T>
using ReturnTypePosition = decltype(std::declval<T>().position());
template <typename T>
using ReturnTypeTime = decltype(std::declval<T>().time());
template <typename T>
using ReturnTypeDirection = decltype(std::declval<T>().direction());
template <typename T>
using ReturnTypeAbsoluteMomentum =
decltype(std::declval<T>().absoluteMomentum());
template <typename T>
using ReturnTypeCharge = decltype(std::declval<T>().charge());
template <typename T>
using ReturnTypeReferenceSurface =
decltype(std::declval<T>().referenceSurface());

template <typename T>
struct BoundTrackParametersConceptImpl {
// check for required nested types
constexpr static bool hasTypeScalar = exists<TypeScalar, const T>;
constexpr static bool hasTypeParametersVector =
exists<TypeParametersVector, const T>;
constexpr static bool hasTypeCovarianceMatrix =
exists<TypeCovarianceMatrix, const T>;

// check for required methods
constexpr static bool hasMethodParameters =
std::is_convertible_v<ReturnTypeParameters<T>, BoundVector>;
constexpr static bool hasMethodCovariance =
std::is_convertible_v<ReturnTypeCovariance<T>,
std::optional<BoundSquareMatrix>>;
constexpr static bool hasMethodFourPositionFromContext =
identical_to<Vector4, ReturnTypeFourPositionFromContext, const T>;
constexpr static bool hasMethodPositionFromContext =
identical_to<Vector3, ReturnTypePositionFromContext, const T>;
constexpr static bool hasMethodTime =
identical_to<TypeScalar<T>, ReturnTypeTime, const T>;
constexpr static bool hasMethodDirection =
identical_to<Vector3, ReturnTypeDirection, const T>;
constexpr static bool hasMethodAbsoluteMomentum =
identical_to<TypeScalar<T>, ReturnTypeAbsoluteMomentum, const T>;
constexpr static bool hasMethodCharge =
identical_to<TypeScalar<T>, ReturnTypeCharge, const T>;
constexpr static bool hasMethodReferenceSurface =
identical_to<const Surface&, ReturnTypeReferenceSurface, const T>;

// provide meaningful error messages in case of non-compliance
static_assert(hasTypeScalar, "Scalar type is missing");
static_assert(hasTypeParametersVector, "Parameters vector type is missing");
static_assert(hasTypeCovarianceMatrix, "Covariance matrix type is missing");
static_assert(hasMethodParameters, "Missing or invalid 'parameters' method");
static_assert(hasMethodCovariance, "Missing or invalid 'covariance' method");
static_assert(hasMethodFourPositionFromContext,
"Missing or invalid 'fourPosition' method");
static_assert(hasMethodPositionFromContext,
"Missing or invalid 'position' method");
static_assert(hasMethodTime, "Missing or invalid 'time' method");
static_assert(hasMethodDirection, "Missing or invalid 'direction' method");
static_assert(hasMethodAbsoluteMomentum,
"Missing or invalid 'absoluteMomentum' method");
static_assert(hasMethodCharge, "Missing or invalid 'charge' method");
static_assert(hasMethodReferenceSurface,
"Missing or invalid 'referenceSurface' method");

constexpr static bool value =
require<hasTypeScalar, hasTypeParametersVector, hasTypeCovarianceMatrix,
hasMethodParameters, hasMethodCovariance,
hasMethodFourPositionFromContext, hasMethodPositionFromContext,
hasMethodTime, hasMethodDirection, hasMethodAbsoluteMomentum,
hasMethodCharge, hasMethodReferenceSurface>;
template <typename Parameters>
concept BasicTrackParameters = requires {
typename Parameters::Scalar;
typename Parameters::ParametersVector;
typename Parameters::CovarianceMatrix;

requires requires(const Parameters &p) {
{ p.time() } -> std::floating_point;
{ p.direction() } -> std::same_as<Vector3>;
{ p.absoluteMomentum() } -> std::floating_point;
{ p.charge() } -> std::floating_point;
};
};

template <typename T>
struct FreeTrackParametersConceptImpl {
// check for required nested types
constexpr static bool hasTypeScalar = exists<TypeScalar, const T>;
constexpr static bool hasTypeParametersVector =
exists<TypeParametersVector, const T>;
constexpr static bool hasTypeCovarianceMatrix =
exists<TypeCovarianceMatrix, const T>;

// check for required methods
constexpr static bool hasMethodParameters =
std::is_convertible_v<ReturnTypeParameters<T>, FreeVector>;
constexpr static bool hasMethodCovariance =
std::is_convertible_v<ReturnTypeCovariance<T>,
std::optional<FreeSquareMatrix>>;
constexpr static bool hasMethodFourPosition =
identical_to<Vector4, ReturnTypeFourPosition, const T>;
constexpr static bool hasMethodPosition =
identical_to<Vector3, ReturnTypePosition, const T>;
constexpr static bool hasMethodTime =
identical_to<TypeScalar<T>, ReturnTypeTime, const T>;
constexpr static bool hasMethodDirection =
identical_to<Vector3, ReturnTypeDirection, const T>;
constexpr static bool hasMethodAbsoluteMomentum =
identical_to<TypeScalar<T>, ReturnTypeAbsoluteMomentum, const T>;
constexpr static bool hasMethodCharge =
identical_to<TypeScalar<T>, ReturnTypeCharge, const T>;

// provide meaningful error messages in case of non-compliance
static_assert(hasTypeScalar, "Scalar type is missing");
static_assert(hasTypeParametersVector, "Parameters vector type is missing");
static_assert(hasTypeCovarianceMatrix, "Covariance matrix type is missing");
static_assert(hasMethodParameters, "Missing or invalid 'parameters' method");
static_assert(hasMethodCovariance, "Missing or invalid 'covariance' method");
static_assert(hasMethodFourPosition,
"Missing or invalid 'fourPosition' method");
static_assert(hasMethodPosition, "Missing or invalid 'position' method");
static_assert(hasMethodTime, "Missing or invalid 'time' method");
static_assert(hasMethodDirection, "Missing or invalid 'direction' method");
static_assert(hasMethodAbsoluteMomentum,
"Missing or invalid 'absoluteMomentum' method");
static_assert(hasMethodCharge, "Missing or invalid 'charge' method");

constexpr static bool value =
require<hasTypeScalar, hasTypeParametersVector, hasTypeCovarianceMatrix,
hasMethodParameters, hasMethodCovariance, hasMethodFourPosition,
hasMethodPosition, hasMethodTime, hasMethodDirection,
hasMethodAbsoluteMomentum, hasMethodCharge>;
};

template <typename parameters_t>
constexpr bool BoundTrackParametersConcept =
BoundTrackParametersConceptImpl<parameters_t>::value;

template <typename parameters_t>
constexpr bool FreeTrackParametersConcept =
FreeTrackParametersConceptImpl<parameters_t>::value;

} // namespace Concepts

/// @brief Concept that asserts that a given type meets the requirements to be
/// considered free track parameters in Acts.
template <typename Parameters>
concept FreeTrackParametersConcept =
Concepts::BasicTrackParameters<Parameters> &&
requires(const Parameters &p) {
{ p.parameters() } -> std::convertible_to<FreeVector>;
{
p.covariance()
} -> std::convertible_to<std::optional<FreeSquareMatrix>>;
{ p.fourPosition() } -> std::same_as<Vector4>;
{ p.position() } -> std::same_as<Vector3>;
};

/// @brief Concept that asserts that a given type meets the requirements to be
/// considered bound track parameters in Acts.
template <typename Parameters>
concept BoundTrackParametersConcept =
Concepts::BasicTrackParameters<Parameters> &&
requires(const Parameters &p) {
{ p.parameters() } -> std::convertible_to<BoundVector>;
{
p.covariance()
} -> std::convertible_to<std::optional<BoundSquareMatrix>>;
{ p.referenceSurface() } -> std::same_as<const Surface &>;

requires requires(GeometryContext &c) {
{ p.position(c) } -> std::same_as<Vector3>;
{ p.fourPosition(c) } -> std::same_as<Vector4>;
{ p.position(c) } -> std::same_as<Vector3>;
};
};
} // namespace Acts
3 changes: 1 addition & 2 deletions Core/include/Acts/Propagator/MaterialInteractor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ struct MaterialInteractor {
}

static_assert(
Acts::Concepts::NavigationCompatibilityConcept<propagator_state_t,
navigator_t>,
Acts::NavigationCompatibleConcept<propagator_state_t, navigator_t>,
"Navigation does not fulfill geometry compatibility concept");

// Handle surface material
Expand Down
14 changes: 6 additions & 8 deletions Core/include/Acts/Propagator/Propagator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,16 @@ class Propagator final
/// Re-define bound track parameters dependent on the stepper
using StepperBoundTrackParameters =
detail::stepper_bound_parameters_type_t<stepper_t>;
static_assert(
Concepts::BoundTrackParametersConcept<StepperBoundTrackParameters>,
"Stepper bound track parameters do not fulfill bound "
"parameters concept.");
static_assert(BoundTrackParametersConcept<StepperBoundTrackParameters>,
"Stepper bound track parameters do not fulfill bound "
"parameters concept.");

/// Re-define curvilinear track parameters dependent on the stepper
using StepperCurvilinearTrackParameters =
detail::stepper_curvilinear_parameters_type_t<stepper_t>;
static_assert(
Concepts::BoundTrackParametersConcept<StepperCurvilinearTrackParameters>,
"Stepper bound track parameters do not fulfill bound "
"parameters concept.");
static_assert(BoundTrackParametersConcept<StepperCurvilinearTrackParameters>,
"Stepper bound track parameters do not fulfill bound "
"parameters concept.");

using Jacobian = BoundMatrix;
using BoundState = std::tuple<StepperBoundTrackParameters, Jacobian, double>;
Expand Down
20 changes: 13 additions & 7 deletions Core/include/Acts/Propagator/Propagator.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@

#include <type_traits>

namespace Acts::detail {
template <typename Stepper, typename StateType, typename N>
concept propagator_stepper_compatible_with =
requires(const Stepper& s, StateType& st, const N& n) {
{ s.step(st, n) } -> std::same_as<Acts::Result<double>>;
};
} // namespace Acts::detail

template <typename S, typename N>
template <typename propagator_state_t>
auto Acts::Propagator<S, N>::propagate(propagator_state_t& state) const
Expand Down Expand Up @@ -125,7 +133,7 @@ auto Acts::Propagator<S, N>::propagate(const parameters_t& start,
const -> Result<action_list_t_result_t<
StepperBoundTrackParameters,
typename propagator_options_t::action_list_type>> {
static_assert(Concepts::BoundTrackParametersConcept<parameters_t>,
static_assert(BoundTrackParametersConcept<parameters_t>,
"Parameters do not fulfill bound parameters concept.");

auto state = makeState<parameters_t, propagator_options_t, target_aborter_t,
Expand All @@ -142,7 +150,7 @@ template <typename parameters_t, typename propagator_options_t,
typename path_aborter_t>
auto Acts::Propagator<S, N>::makeState(
const parameters_t& start, const propagator_options_t& options) const {
static_assert(Concepts::BoundTrackParametersConcept<parameters_t>,
static_assert(BoundTrackParametersConcept<parameters_t>,
"Parameters do not fulfill bound parameters concept.");

// Type of track parameters produced by the propagation
Expand Down Expand Up @@ -173,8 +181,7 @@ auto Acts::Propagator<S, N>::makeState(
m_navigator.makeState(eOptions.navigation)};

static_assert(
Concepts::has_method<const S, Result<double>, Concepts::Stepper::step_t,
StateType&, const N&>,
detail::propagator_stepper_compatible_with<S, StateType, N>,
"Step method of the Stepper is not compatible with the propagator "
"state");

Expand All @@ -189,7 +196,7 @@ template <typename parameters_t, typename propagator_options_t,
auto Acts::Propagator<S, N>::makeState(
const parameters_t& start, const Surface& target,
const propagator_options_t& options) const {
static_assert(Concepts::BoundTrackParametersConcept<parameters_t>,
static_assert(BoundTrackParametersConcept<parameters_t>,
"Parameters do not fulfill bound parameters concept.");

// Type of provided options
Expand All @@ -216,8 +223,7 @@ auto Acts::Propagator<S, N>::makeState(
m_navigator.makeState(eOptions.navigation)};

static_assert(
Concepts::has_method<const S, Result<double>, Concepts::Stepper::step_t,
StateType&, const N&>,
detail::propagator_stepper_compatible_with<S, StateType, N>,
"Step method of the Stepper is not compatible with the propagator "
"state");

Expand Down
Loading

0 comments on commit 117e606

Please sign in to comment.