File indexing completed on 2026-05-27 07:24:03
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/pdg_particle.hpp"
0013 #include "detray/propagator/base_actor.hpp"
0014 #include "detray/utils/concepts.hpp"
0015 #include "detray/utils/tuple_helpers.hpp"
0016
0017
0018 #include <concepts>
0019 #include <optional>
0020
0021 namespace detray::concepts {
0022
0023
0024 template <typename A>
0025 concept actor = std::derived_from<A, detray::base_actor> &&
0026 requires(const A a) { typename A::state; };
0027
0028
0029 template <typename A>
0030 concept composite_actor =
0031 actor<A> && A::is_comp_actor::value && requires(const A ca) {
0032 typename A::observer_states;
0033 typename A::observer_state_refs;
0034 };
0035
0036
0037 template <typename A>
0038 concept actor_chain = requires(const A c, typename A::state_tuple s) {
0039 typename A::actor_tuple;
0040 typename A::state_tuple;
0041 typename A::state_ref_tuple;
0042
0043 { c.actors() } -> std::same_as<const typename A::actor_tuple &>;
0044
0045 {
0046 c.make_default_actor_states()
0047 } -> detray::concepts::any_of<typename A::state_tuple, std::nullopt_t>;
0048
0049 { c.setup_actor_states(s) } -> std::same_as<typename A::state_ref_tuple>;
0050 };
0051
0052
0053 template <typename S, typename T>
0054 concept is_state_of =
0055 (actor_chain<T> && (detail::is_permutation_v<std::remove_cvref_t<S>,
0056 typename T::state_ref_tuple> ||
0057 detail::is_permutation_v<std::remove_cvref_t<S>,
0058 typename T::state_tuple>)) ||
0059
0060 (actor<T> && std::same_as<std::remove_cvref_t<S>, typename T::state>);
0061
0062
0063 template <typename S>
0064 concept propagator_state = requires {
0065 typename S::detector_type;
0066 typename S::detector_type::scalar_type;
0067 typename S::stepper_state_type;
0068 typename S::navigator_state_type;
0069 typename S::context_type;
0070 } && requires(S &s) {
0071 requires requires(
0072 const pdg_particle<typename S::detector_type::scalar_type> &ptc) {
0073 { s.set_particle(ptc) };
0074 };
0075
0076 requires requires(bool b) {
0077 { s.heartbeat(b) };
0078 { s.debug(b) };
0079 };
0080
0081 { s.stepping() } -> std::same_as<typename S::stepper_state_type &>;
0082 { s.navigation() } -> std::same_as<typename S::navigator_state_type &>;
0083 { s.context() } -> std::same_as<typename S::context_type &>;
0084 } && requires(const S &s) {
0085 { s.debug() } -> std::same_as<bool>;
0086 { s.is_alive() } -> std::same_as<bool>;
0087 { s.heartbeat() } -> std::same_as<bool>;
0088 { s.stepping() } -> std::same_as<const typename S::stepper_state_type &>;
0089 { s.navigation() } -> std::same_as<const typename S::navigator_state_type &>;
0090 { s.context() } -> std::same_as<const typename S::context_type &>;
0091 };
0092
0093
0094
0095 template <typename S, typename P>
0096 concept is_propagator_state_of = propagator_state<S> && requires {
0097 typename P::detector_type;
0098 typename P::stepper_type;
0099 typename P::navigator_type;
0100
0101 requires std::same_as<typename P::detector_type, typename S::detector_type>;
0102 requires std::same_as<typename P::stepper_type::state,
0103 typename S::stepper_state_type>;
0104 requires std::same_as<typename P::navigator_type::state,
0105 typename S::navigator_state_type>;
0106 };
0107
0108
0109 template <typename S, typename F>
0110 concept is_field_of = requires { typename S::magnetic_field_type; } &&
0111 std::same_as<F, typename S::magnetic_field_type>;
0112
0113 }