Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:54:09

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/sys/ActionInterface.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <string>
0010 #include <string_view>
0011 
0012 #include "corecel/cont/Span.hh"
0013 
0014 #include "ThreadId.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Within-step ordering of explicit actions.
0021  *
0022  * Each "step iteration", wherein many tracks undergo a single step in
0023  * parallel, consists of an ordered series of actions. An action with an
0024  * earlier order always precedes an action with a later order.
0025  *
0026  * \sa StepActionInterface
0027  */
0028 enum class StepActionOrder
0029 {
0030     generate,  //!< Fill new track initializers
0031     start,  //!< Initialize tracks
0032     user_start,  //!< User initialization of new tracks
0033     sort_start,  //!< Sort track slots after initialization
0034     pre,  //!< Pre-step physics and setup
0035     user_pre,  //!< User actions for querying pre-step data
0036     sort_pre,  //!< Sort track slots after setting pre-step
0037     along,  //!< Along-step
0038     sort_along,  //!< Sort track slots after determining first step action
0039     pre_post,  //!< Discrete selection kernel
0040     sort_pre_post,  //! Sort track slots after selecting discrete interaction
0041     post,  //!< After step
0042     user_post,  //!< User actions after boundary crossing, collision
0043     end,  //!< Processing secondaries, including replacing primaries
0044     size_
0045 };
0046 
0047 //---------------------------------------------------------------------------//
0048 /*!
0049  * Pure abstract interface for an action that could happen to a track.
0050  *
0051  * An action represents a possible state point or state change for a track.
0052  * Explicit actions (see \c StepActionInterface ) call kernels that change
0053  * the state (discrete processes, geometry boundary), and *implicit* actions
0054  * (which do not inherit from the explicit interface) are placeholders for
0055  * different reasons to pause the state or mark it for future modification
0056  * (range limitation, propagation loop limit).
0057  *
0058  * The \c ActionInterface provides a clean virtual interface for
0059  * gathering metadata. The \c StepActionInterface provides additional
0060  * interfaces for launching kernels. The \c BeginRunActionInterface allows
0061  * actions to modify the state (or the class instance itself) at the beginning
0062  * of a stepping loop, and \c EndRunActionInterface allows actions to
0063  * gather and merge multiple state information at the end.
0064  *
0065  * Using multiple inheritance, you can create an action that inherits from
0066  * multiple of these classes. Note also that the function signatures are
0067  * similar to other high-level interfaces classes in Celeritas (e.g., \c
0068  * AuxParamsInterface, \c OutputInterface), so one "label" can be used to
0069  * satisfy multiple interfaces.
0070  *
0071  * The \c label should be a brief lowercase hyphen-separated string, usually a
0072  * noun, with perhaps some sort of category being the first token.
0073  *
0074  * The \c description should be a verb phrase (and not have a title-cased
0075  * start).
0076  */
0077 class ActionInterface
0078 {
0079   public:
0080     // Default virtual destructor allows deletion by pointer-to-interface
0081     virtual ~ActionInterface() noexcept = 0;
0082 
0083     //! ID of this action for verification and ordering
0084     virtual ActionId action_id() const = 0;
0085 
0086     //! Short unique label of the action
0087     virtual std::string_view label() const = 0;
0088 
0089     //! Description of the action
0090     virtual std::string_view description() const = 0;
0091 
0092   protected:
0093     //!@{
0094     //! Allow construction and assignment only through daughter classes
0095     ActionInterface() = default;
0096     CELER_DEFAULT_COPY_MOVE(ActionInterface);
0097     //!@}
0098 };
0099 
0100 //---------------------------------------------------------------------------//
0101 /*!
0102  * Interface that can modify the action's state.
0103  *
0104  * Most actions can modify \em only the local "state" being passed as an
0105  * argument. This one allows data to be allocated or initialized at the
0106  * beginning of the run.
0107  *
0108  * \todo Delete this to allow only stateless actions, since now
0109  * we have aux data? This will reduce overhead for virtual inheritance classes
0110  * too.
0111  */
0112 class MutableActionInterface : public virtual ActionInterface
0113 {
0114 };
0115 
0116 //---------------------------------------------------------------------------//
0117 /*!
0118  * Traits class for actions that modify or access params/state.
0119  *
0120  * Using a single base class's typedefs is necessary for some compilers to
0121  * avoid an "ambiguous type alias" failure: "member 'CoreParams' found in
0122  * multiple base classes of different types". Note that adding this class to
0123  * the inheritance hierarchy (even multiple times) has no additional storage or
0124  * access cost.
0125  */
0126 template<class P, template<MemSpace M> class S>
0127 struct ActionTypeTraits
0128 {
0129     //@{
0130     //! \name Type aliases
0131     using CoreParams = P;
0132     using CoreStateHost = S<MemSpace::host>;
0133     using CoreStateDevice = S<MemSpace::device>;
0134     using SpanCoreStateHost = Span<S<MemSpace::host>* const>;
0135     using SpanCoreStateDevice = Span<S<MemSpace::device>* const>;
0136     //@}
0137 };
0138 
0139 //---------------------------------------------------------------------------//
0140 /*!
0141  * Interface for updating states at the beginning of the simulation.
0142  *
0143  * This is necessary for some classes that require deferred initialization
0144  * (either to the class itself or the state), for example because it needs the
0145  * number of total actions being run.
0146  *
0147  * If the class itself--rather than the state--needs initialization, try to
0148  * initialize in the constructor and avoid using this interface if possible.
0149  *
0150  * \todo This is currently called once per each state on each CPU thread, and
0151  * it would be more sensible to call a single with all cooperative states.
0152  *
0153  * \warning Because this is called once per thread, the inheriting class is
0154  * responsible for thread safety (e.g. adding mutexes).
0155  */
0156 template<class P, template<MemSpace M> class S>
0157 class BeginRunActionInterface : public ActionTypeTraits<P, S>,
0158                                 public MutableActionInterface
0159 {
0160   public:
0161     //! Set host data at the beginning of a run
0162     virtual void begin_run(P const&, S<MemSpace::host>&) = 0;
0163     //! Set device data at the beginning of a run
0164     virtual void begin_run(P const&, S<MemSpace::device>&) = 0;
0165 };
0166 
0167 //---------------------------------------------------------------------------//
0168 /*!
0169  * Interface for kernel actions in a stepping loop.
0170  *
0171  * \tparam P Core param class
0172  * \tparam S Core state class
0173  */
0174 template<class P, template<MemSpace M> class S>
0175 class StepActionInterface : public ActionTypeTraits<P, S>,
0176                             virtual public ActionInterface
0177 {
0178   public:
0179     //! Dependency ordering of the action inside the step
0180     virtual StepActionOrder order() const = 0;
0181     //! Execute the action with host data
0182     virtual void step(P const&, S<MemSpace::host>&) const = 0;
0183     //! Execute the action with device data
0184     virtual void step(P const&, S<MemSpace::device>&) const = 0;
0185 };
0186 
0187 //---------------------------------------------------------------------------//
0188 /*!
0189  * Concrete mixin utility class for managing an action.
0190  *
0191  * Example:
0192  * \code
0193   class KernellyPhysicsAction final : public CoreStepActionInterface,
0194                                       public ConcreteAction
0195   {
0196     public:
0197       // Construct with ID and label
0198       using ConcreteAction::ConcreteAction;
0199 
0200       void step(CoreParams const&, CoreStateHost&) const final;
0201       void step(CoreParams const&, CoreStateDevice&) const final;
0202 
0203       StepActionOrder order() const final { return StepActionOrder::post; }
0204   };
0205 
0206   class PlaceholderPhysicsAction final : public ConcreteAction
0207   {
0208     public:
0209       // Construct with ID and label
0210       using ConcreteAction::ConcreteAction;
0211   };
0212  * \endcode
0213  *
0214  * The \c noexcept declarations improve code generation for the
0215  * common use case of multiple inheritance.
0216  *
0217  * \note Use this class when multiple instances of the class may coexist in the
0218  * same stepping loop.
0219  */
0220 class ConcreteAction : virtual public ActionInterface
0221 {
0222   public:
0223     // Construct from ID, unique label
0224     ConcreteAction(ActionId id, std::string label) noexcept(!CELERITAS_DEBUG);
0225 
0226     // Construct from ID, unique label, and description
0227     ConcreteAction(ActionId id,
0228                    std::string label,
0229                    std::string description) noexcept(!CELERITAS_DEBUG);
0230 
0231     // Default destructor
0232     ~ConcreteAction() noexcept override;
0233     CELER_DELETE_COPY_MOVE(ConcreteAction);
0234 
0235     //! ID of this action for verification
0236     ActionId action_id() const final { return id_; }
0237 
0238     //! Short label
0239     std::string_view label() const final { return label_; }
0240 
0241     //! Descriptive label
0242     std::string_view description() const final { return description_; }
0243 
0244   private:
0245     ActionId id_;
0246     std::string label_;
0247     std::string description_;
0248 };
0249 
0250 //---------------------------------------------------------------------------//
0251 /*!
0252  * Concrete utility class for managing an action with static strings.
0253  *
0254  * This is an implementation detail of \c StaticConcreteAction, but it can be
0255  * used manually for classes that inherit from multiple \c label methods (e.g.,
0256  * something that's both an action and has aux data) for which the mixin method
0257  * does not work.
0258  */
0259 class StaticActionData
0260 {
0261   public:
0262     // Construct from ID, unique label
0263     StaticActionData(ActionId id,
0264                      std::string_view label) noexcept(!CELERITAS_DEBUG);
0265 
0266     // Construct from ID, unique label, and description
0267     StaticActionData(ActionId id,
0268                      std::string_view label,
0269                      std::string_view description) noexcept(!CELERITAS_DEBUG);
0270 
0271     //! ID of this action for verification
0272     ActionId action_id() const { return id_; }
0273 
0274     //! Short label
0275     std::string_view label() const { return label_; }
0276 
0277     //! Descriptive label
0278     std::string_view description() const { return description_; }
0279 
0280   private:
0281     ActionId id_;
0282     std::string_view label_;
0283     std::string_view description_;
0284 };
0285 
0286 //---------------------------------------------------------------------------//
0287 /*!
0288  * Concrete mixin utility class for managing an action with static strings.
0289  *
0290  * This is a typical use case for "singleton" actions where a maximum of one
0291  * can exist per stepping loop. The action ID still must be supplied at
0292  * runtime.
0293  *
0294  * \note Use this class when the label and description are compile-time
0295  * constants.
0296  */
0297 class StaticConcreteAction : virtual public ActionInterface
0298 {
0299   public:
0300     // Construct from ID, unique label
0301     StaticConcreteAction(ActionId id,
0302                          std::string_view label) noexcept(!CELERITAS_DEBUG);
0303 
0304     // Construct from ID, unique label, and description
0305     StaticConcreteAction(ActionId id,
0306                          std::string_view label,
0307                          std::string_view description) noexcept(!CELERITAS_DEBUG);
0308 
0309     // Default destructor
0310     ~StaticConcreteAction() override = default;
0311     CELER_DELETE_COPY_MOVE(StaticConcreteAction);
0312 
0313     //! ID of this action for verification
0314     ActionId action_id() const final { return sad_.action_id(); }
0315 
0316     //! Short label
0317     std::string_view label() const final { return sad_.label(); }
0318 
0319     //! Descriptive label
0320     std::string_view description() const final { return sad_.description(); }
0321 
0322   private:
0323     StaticActionData sad_;
0324 };
0325 
0326 //---------------------------------------------------------------------------//
0327 
0328 //! Action order/ID tuple for comparison in sorting
0329 struct OrderedAction
0330 {
0331     StepActionOrder order;
0332     ActionId id;
0333 
0334     //! Ordering comparison for an action/ID
0335     CELER_CONSTEXPR_FUNCTION bool operator<(OrderedAction const& other) const
0336     {
0337         if (this->order < other.order)
0338             return true;
0339         if (this->order > other.order)
0340             return false;
0341         return this->id < other.id;
0342     }
0343 };
0344 
0345 //---------------------------------------------------------------------------//
0346 
0347 // Get a string corresponding to a surface type
0348 char const* to_cstring(StepActionOrder);
0349 
0350 //---------------------------------------------------------------------------//
0351 }  // namespace celeritas