File indexing completed on 2025-10-30 08:38:00
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 #pragma once
0014 
0015 #include <stdexcept>
0016 #include <string>
0017 #if defined(__HIP__)
0018 #    include <hip/hip_runtime.h>
0019 #elif defined(__CUDA_ARCH__)
0020 
0021 #else
0022 #    include <ostream>  // IWYU pragma: export
0023 #    include <sstream>  // IWYU pragma: keep
0024 #endif
0025 
0026 #include "corecel/Config.hh"
0027 
0028 #include "Macros.hh"
0029 
0030 
0031 
0032 
0033 
0034 
0035 
0036 
0037 
0038 
0039 
0040 
0041 
0042 
0043 
0044 
0045 
0046 
0047 
0048 
0049 
0050 
0051 
0052 
0053 
0054 
0055 
0056 
0057 
0058 
0059 
0060 
0061 
0062 
0063 
0064 
0065 
0066 
0067 
0068 
0069 
0070 
0071 
0072 
0073 
0074 
0075 
0076 
0077 
0078 
0079 
0080 
0081 
0082 
0083 
0084 
0085 
0086 
0087 
0088 
0089 
0090 
0091 
0092 
0093 
0094 
0095 
0096 
0097 
0098 
0099 
0100 
0101 
0102 
0103 
0104 
0105 
0106 
0107 
0108 
0109 
0110 
0111 
0112 
0113 
0114 
0115 
0116 
0117 
0118 
0119 
0120 
0121 
0122 
0123 
0124 
0125 
0126 
0127 
0128 
0129 
0130 
0131 
0132 
0133 
0134 
0135 
0136 
0137 
0138 
0139 
0140 
0141 
0142 #if !defined(__HIP__) && !defined(__CUDA_ARCH__)
0143 
0144 #    define CELER_DEBUG_THROW_(MSG, WHICH) \
0145         throw ::celeritas::DebugError(     \
0146             {::celeritas::DebugErrorType::WHICH, MSG, __FILE__, __LINE__})
0147 #elif defined(__CUDA_ARCH__) && !defined(NDEBUG)
0148 
0149 #    define CELER_DEBUG_THROW_(MSG, WHICH) \
0150         assert(false && sizeof(#WHICH ": " MSG))
0151 #else
0152 
0153 
0154 
0155 #    define CELER_DEBUG_THROW_(MSG, WHICH) \
0156         ::celeritas::device_debug_error(   \
0157             ::celeritas::DebugErrorType::WHICH, MSG, __FILE__, __LINE__)
0158 #endif
0159 
0160 #define CELER_DEBUG_ASSERT_(COND, WHICH)      \
0161     do                                        \
0162     {                                         \
0163         if (CELER_UNLIKELY(!(COND)))          \
0164         {                                     \
0165             CELER_DEBUG_THROW_(#COND, WHICH); \
0166         }                                     \
0167     } while (0)
0168 #define CELER_NDEBUG_ASSUME_(COND)      \
0169     do                                  \
0170     {                                   \
0171         if (CELER_UNLIKELY(!(COND)))    \
0172         {                               \
0173             ::celeritas::unreachable(); \
0174         }                               \
0175     } while (0)
0176 #define CELER_NOASSERT_(COND)   \
0177     do                          \
0178     {                           \
0179         if (false && (COND)) {} \
0180     } while (0)
0181 
0182 
0183 #define CELER_DEBUG_FAIL(MSG, WHICH)    \
0184     do                                  \
0185     {                                   \
0186         CELER_DEBUG_THROW_(MSG, WHICH); \
0187         ::celeritas::unreachable();     \
0188     } while (0)
0189 
0190 #if !CELER_DEVICE_COMPILE
0191 #    define CELER_RUNTIME_THROW(WHICH, WHAT, COND) \
0192         throw ::celeritas::RuntimeError({          \
0193             WHICH,                                 \
0194             WHAT,                                  \
0195             COND,                                  \
0196             __FILE__,                              \
0197             __LINE__,                              \
0198         })
0199 #elif CELERITAS_DEBUG
0200 #    define CELER_RUNTIME_THROW(WHICH, WHAT, COND)                           \
0201         CELER_DEBUG_FAIL("Runtime errors cannot be thrown from device code", \
0202                          unreachable);
0203 #else
0204 
0205 #    define CELER_RUNTIME_THROW(WHICH, WHAT, COND) ::celeritas::unreachable()
0206 #endif
0207 
0208 #if (CELERITAS_DEBUG && !CELER_DEVICE_COMPILE) \
0209     || (CELERITAS_DEVICE_DEBUG && CELER_DEVICE_COMPILE)
0210 #    define CELER_EXPECT(COND) CELER_DEBUG_ASSERT_(COND, precondition)
0211 #    define CELER_ASSERT(COND) CELER_DEBUG_ASSERT_(COND, internal)
0212 #    define CELER_ENSURE(COND) CELER_DEBUG_ASSERT_(COND, postcondition)
0213 #    define CELER_ASSUME(COND) CELER_DEBUG_ASSERT_(COND, assumption)
0214 #    define CELER_ASSERT_UNREACHABLE() \
0215         CELER_DEBUG_FAIL("unreachable code point encountered", unreachable)
0216 #else
0217 #    define CELER_EXPECT(COND) CELER_NOASSERT_(COND)
0218 #    define CELER_ASSERT(COND) CELER_NOASSERT_(COND)
0219 #    define CELER_ENSURE(COND) CELER_NOASSERT_(COND)
0220 #    define CELER_ASSUME(COND) CELER_NDEBUG_ASSUME_(COND)
0221 #    define CELER_ASSERT_UNREACHABLE() ::celeritas::unreachable()
0222 #endif
0223 
0224 #if !CELER_DEVICE_COMPILE
0225 #    define CELER_VALIDATE(COND, MSG)                            \
0226         do                                                       \
0227         {                                                        \
0228             if (CELER_UNLIKELY(!(COND)))                         \
0229             {                                                    \
0230                 std::ostringstream celer_runtime_msg_;           \
0231                 celer_runtime_msg_ MSG;                          \
0232                 CELER_RUNTIME_THROW(                             \
0233                     ::celeritas::RuntimeError::validate_err_str, \
0234                     celer_runtime_msg_.str(),                    \
0235                     #COND);                                      \
0236             }                                                    \
0237         } while (0)
0238 #else
0239 #    define CELER_VALIDATE(COND, MSG) CELER_RUNTIME_THROW(nullptr, "", #COND)
0240 #endif
0241 
0242 #define CELER_NOT_CONFIGURED(WHAT) \
0243     CELER_RUNTIME_THROW(           \
0244         ::celeritas::RuntimeError::not_config_err_str, WHAT, {})
0245 #define CELER_NOT_IMPLEMENTED(WHAT) \
0246     CELER_RUNTIME_THROW(::celeritas::RuntimeError::not_impl_err_str, WHAT, {})
0247 
0248 
0249 
0250 
0251 
0252 
0253 
0254 
0255 
0256 
0257 
0258 
0259 
0260 
0261 
0262 
0263 
0264 
0265 
0266 
0267 
0268 
0269 
0270 #if CELERITAS_USE_CUDA || CELERITAS_USE_HIP
0271 #    define CELER_DEVICE_API_CALL(STMT)                                      \
0272         do                                                                   \
0273         {                                                                    \
0274             using ErrT_ = CELER_DEVICE_API_SYMBOL(Error_t);                  \
0275             ErrT_ result_ = CELER_DEVICE_API_SYMBOL(STMT);                   \
0276             if (CELER_UNLIKELY(result_ != CELER_DEVICE_API_SYMBOL(Success))) \
0277             {                                                                \
0278                 result_ = CELER_DEVICE_API_SYMBOL(GetLastError)();           \
0279                 CELER_RUNTIME_THROW(                                         \
0280                     CELER_DEVICE_PLATFORM_UPPER_STR,                         \
0281                     CELER_DEVICE_API_SYMBOL(GetErrorString)(result_),        \
0282                     #STMT);                                                  \
0283             }                                                                \
0284         } while (0)
0285 #else
0286 #    define CELER_DEVICE_API_CALL(STMT)              \
0287         do                                           \
0288         {                                            \
0289             CELER_NOT_CONFIGURED("CUDA or HIP");     \
0290             CELER_DISCARD(CorecelDeviceRuntimeApiHh) \
0291         } while (0)
0292 #endif
0293 
0294 
0295 #define CELER_DEVICE_PREFIX(STMT) CELER_DEVICE_API_SYMBOL(STMT)
0296 #define CELER_DEVICE_CALL_PREFIX(STMT) CELER_DEVICE_API_CALL(STMT)
0297 #define CELER_DEVICE_CHECK_ERROR() CELER_DEVICE_API_CALL(PeekAtLastError())
0298 
0299 
0300 
0301 
0302 
0303 
0304 
0305 
0306 
0307 
0308 #if CELERITAS_USE_MPI
0309 #    define CELER_MPI_CALL(STATEMENT)                                     \
0310         do                                                                \
0311         {                                                                 \
0312             int mpi_result_ = (STATEMENT);                                \
0313             if (CELER_UNLIKELY(mpi_result_ != MPI_SUCCESS))               \
0314             {                                                             \
0315                 CELER_RUNTIME_THROW(                                      \
0316                     "MPI", mpi_error_to_string(mpi_result_), #STATEMENT); \
0317             }                                                             \
0318         } while (0)
0319 #else
0320 #    define CELER_MPI_CALL(STATEMENT)    \
0321         do                               \
0322         {                                \
0323             CELER_NOT_CONFIGURED("MPI"); \
0324         } while (0)
0325 #endif
0326 
0327 
0328 
0329 
0330 
0331 namespace celeritas
0332 {
0333 
0334 
0335 
0336 enum class DebugErrorType
0337 {
0338     precondition,  
0339     internal,  
0340     unreachable,  
0341     postcondition,  
0342     assumption,  
0343 };
0344 
0345 
0346 struct DebugErrorDetails
0347 {
0348     DebugErrorType which;
0349     char const* condition;
0350     char const* file;
0351     int line;
0352 };
0353 
0354 
0355 struct RuntimeErrorDetails
0356 {
0357     char const* which{nullptr};  
0358     std::string what{};  
0359     std::string condition{};  
0360     std::string file{};  
0361     int line{0};  
0362 };
0363 
0364 
0365 
0366 
0367 
0368 
0369 [[noreturn]] inline CELER_FUNCTION void unreachable()
0370 {
0371     CELER_UNREACHABLE;
0372 }
0373 
0374 
0375 char const* to_cstring(DebugErrorType which);
0376 
0377 
0378 std::string mpi_error_to_string(int);
0379 
0380 
0381 
0382 
0383 
0384 struct JsonPimpl;
0385 
0386 
0387 
0388 
0389 
0390 class DebugError : public std::logic_error
0391 {
0392   public:
0393     
0394     explicit DebugError(DebugErrorDetails&&);
0395     CELER_DEFAULT_COPY_MOVE(DebugError);
0396 
0397     
0398     ~DebugError() override;
0399 
0400     
0401     DebugErrorDetails const& details() const { return details_; }
0402 
0403   private:
0404     DebugErrorDetails details_;
0405 };
0406 
0407 
0408 
0409 
0410 
0411 class RuntimeError : public std::runtime_error
0412 {
0413   public:
0414     
0415     explicit RuntimeError(RuntimeErrorDetails&&);
0416     CELER_DEFAULT_COPY_MOVE(RuntimeError);
0417 
0418     
0419     ~RuntimeError() override;
0420 
0421     
0422     RuntimeErrorDetails const& details() const { return details_; }
0423 
0424     
0425     
0426     static char const validate_err_str[];
0427     static char const not_config_err_str[];
0428     static char const not_impl_err_str[];
0429     
0430 
0431   private:
0432     RuntimeErrorDetails details_;
0433 };
0434 
0435 
0436 
0437 
0438 
0439 
0440 
0441 
0442 
0443 
0444 class RichContextException : public std::exception
0445 {
0446   public:
0447     
0448     virtual void output(JsonPimpl*) const = 0;
0449 
0450     
0451     virtual char const* type() const = 0;
0452 };
0453 
0454 
0455 
0456 
0457 
0458 #if defined(__CUDA_ARCH__) && defined(NDEBUG)
0459 
0460 inline __attribute__((noinline)) __host__ __device__ void device_debug_error(
0461     DebugErrorType, char const* condition, char const* file, int line)
0462 {
0463     printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0464            file,
0465            line,
0466            condition);
0467     __trap();
0468 }
0469 #elif defined(__HIP__)
0470 
0471 inline __host__ void device_debug_error(DebugErrorType which,
0472                                         char const* condition,
0473                                         char const* file,
0474                                         int line)
0475 {
0476     throw DebugError({which, condition, file, line});
0477 }
0478 
0479 
0480 
0481 inline __attribute__((noinline)) __device__ void device_debug_error(
0482     DebugErrorType, char const* condition, char const* file, int line)
0483 {
0484     printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0485            file,
0486            line,
0487            condition);
0488     abort();
0489 }
0490 #endif
0491 
0492 
0493 }