Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:52:27

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 celeritas/track/detail/StatusCheckExecutor.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Macros.hh"
0011 #include "celeritas/global/ActionInterface.hh"
0012 #include "celeritas/global/CoreTrackView.hh"
0013 
0014 #include "../SimTrackView.hh"
0015 
0016 #if !CELER_DEVICE_COMPILE
0017 #    include "corecel/io/Logger.hh"
0018 #    include "celeritas/global/Debug.hh"
0019 #endif
0020 
0021 #include "../StatusCheckData.hh"
0022 
0023 namespace celeritas
0024 {
0025 namespace detail
0026 {
0027 //---------------------------------------------------------------------------//
0028 #if !CELER_DEVICE_COMPILE
0029 // Print a track and why it failed.
0030 #    define CELER_PRINT_TRACK(MSG, TRACK) \
0031         CELER_LOG_LOCAL(error)            \
0032             << MSG << ": " << ::celeritas::StreamableTrack{TRACK};
0033 #else
0034 #    define CELER_PRINT_TRACK(MSG, TRACK)
0035 #endif
0036 
0037 /*!
0038  * Check that the condition is true, otherwise throw an error/assertion.
0039  *
0040  * \note This macro is defined so that the condition is still checked in
0041  * "release" mode, and so that checking will work on GPU.
0042  */
0043 #define CELER_FAIL_IF(COND, MSG)                               \
0044     do                                                         \
0045     {                                                          \
0046         if (CELER_UNLIKELY((COND)))                            \
0047         {                                                      \
0048             CELER_PRINT_TRACK(MSG, track)                      \
0049             CELER_DEBUG_THROW_(MSG ": '" #COND "'", internal); \
0050         }                                                      \
0051     } while (0)
0052 
0053 //---------------------------------------------------------------------------//
0054 /*!
0055  * Assert that a track's status and actions are valid.
0056  *
0057  * When enabled as a debug option, this is called after every action is
0058  * executed. The state's "action" and "order" are for the last executed action.
0059  * The status, post-step, and along-step action are from *before* the last
0060  * executed action.
0061  *
0062  * See \c StepActionOrder, \c TrackStatus .
0063  */
0064 struct StatusCheckExecutor
0065 {
0066     inline CELER_FUNCTION void operator()(CoreTrackView const& track);
0067 
0068     NativeCRef<StatusCheckParamsData> const params;
0069     NativeRef<StatusCheckStateData> const state;
0070 };
0071 
0072 //---------------------------------------------------------------------------//
0073 // INLINE DEFINITIONS
0074 //---------------------------------------------------------------------------//
0075 CELER_FUNCTION void StatusCheckExecutor::operator()(CoreTrackView const& track)
0076 {
0077     CELER_EXPECT(state.order != StepActionOrder::size_);
0078     CELER_EXPECT(state.action);
0079 
0080     auto tsid = track.track_slot_id();
0081     auto sim = track.sim();
0082 
0083     if (state.order > StepActionOrder::start
0084         && state.order < StepActionOrder::end)
0085     {
0086         auto prev_status = state.status[tsid];
0087         CELER_FAIL_IF(sim.status() < prev_status,
0088                       "status was improperly reverted");
0089     }
0090     if (state.order >= StepActionOrder::pre
0091         && state.order < StepActionOrder::end)
0092     {
0093         // Initializing takes place *either* at the very beginning of the
0094         // stepping loop *or* at the very end (in the case where a track is
0095         // initialized in-place from a secondary). It should be cleared in
0096         // pre-step
0097         CELER_FAIL_IF(sim.status() == TrackStatus::initializing,
0098                       "status cannot be 'initializing' after pre-step");
0099     }
0100     if (sim.status() == TrackStatus::inactive)
0101     {
0102         // Remaining tests only apply to active tracks
0103         return;
0104     }
0105     if (state.order < StepActionOrder::pre
0106         || state.order == StepActionOrder::end)
0107     {
0108         // Skip remaining tests since step actions get reset in "pre-step"
0109         return;
0110     }
0111 
0112     if (sim.step_length() != numeric_limits<real_type>::infinity())
0113     {
0114         /*!
0115          * It's allowable to have *no* post step action if there are no physics
0116          * processes for the current particle type.
0117          * \todo Change this behavior to be a *tracking cut* rather than lost
0118          * energy.
0119          */
0120         CELER_FAIL_IF(!sim.post_step_action(), "missing post-step action");
0121     }
0122 
0123     if (sim.status() == TrackStatus::alive)
0124     {
0125         // If the track fails during initialization, it won't get an
0126         // along-step action, so only check this if alive
0127         CELER_FAIL_IF(!sim.along_step_action(), "missing along-step action");
0128 
0129         // All 'alive' tracks should be inside the geometry
0130         CELER_FAIL_IF(track.geometry().is_outside(),
0131                       "track is outside the geometry but still 'alive'");
0132     }
0133 
0134     ActionId const prev_along_step = state.along_step_action[tsid];
0135     ActionId const next_along_step = sim.along_step_action();
0136     if (state.order > StepActionOrder::pre && next_along_step)
0137     {
0138         CELER_FAIL_IF(prev_along_step != next_along_step,
0139                       "along-step action cannot yet change");
0140     }
0141 
0142     ActionId const prev_post_step = state.post_step_action[tsid];
0143     ActionId const next_post_step = sim.post_step_action();
0144     if (state.order > StepActionOrder::pre && prev_post_step
0145         && prev_post_step != next_post_step)
0146     {
0147         // Check that order is increasing if not an "implicit" action
0148         auto prev_order = params.orders[prev_post_step];
0149         auto next_order = params.orders[next_post_step];
0150         CELER_FAIL_IF(!(prev_order == params.implicit_order
0151                         || next_order == params.implicit_order
0152                         || OrderedAction{prev_order, prev_post_step}
0153                                < OrderedAction{next_order, next_post_step}),
0154                       "new post-step action is out of order");
0155     }
0156 }
0157 
0158 //---------------------------------------------------------------------------//
0159 }  // namespace detail
0160 }  // namespace celeritas