Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:49

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