File indexing completed on 2026-05-13 08:34:45
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 ::celeritas::throw_debug_error( \
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 ::celeritas::throw_runtime_error({ \
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 [[noreturn]] void throw_debug_error(DebugErrorDetails&&);
0382
0383
0384 [[noreturn]] void throw_runtime_error(RuntimeErrorDetails&&);
0385
0386
0387
0388
0389
0390 struct JsonPimpl;
0391
0392
0393
0394
0395
0396 class DebugError : public std::logic_error
0397 {
0398 public:
0399
0400 explicit DebugError(DebugErrorDetails&&);
0401 CELER_DEFAULT_COPY_MOVE(DebugError);
0402
0403
0404 ~DebugError() override;
0405
0406
0407 DebugErrorDetails const& details() const { return details_; }
0408
0409 private:
0410 DebugErrorDetails details_;
0411 };
0412
0413
0414
0415
0416
0417 class RuntimeError : public std::runtime_error
0418 {
0419 public:
0420
0421 explicit RuntimeError(RuntimeErrorDetails&&);
0422 CELER_DEFAULT_COPY_MOVE(RuntimeError);
0423
0424
0425 ~RuntimeError() override;
0426
0427
0428 RuntimeErrorDetails const& details() const { return details_; }
0429
0430
0431
0432 static char const validate_err_str[];
0433 static char const not_config_err_str[];
0434 static char const not_impl_err_str[];
0435
0436
0437 private:
0438 RuntimeErrorDetails details_;
0439 };
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450 class RichContextException : public std::exception
0451 {
0452 public:
0453
0454 virtual void output(JsonPimpl*) const = 0;
0455
0456
0457 virtual char const* type() const = 0;
0458 };
0459
0460
0461
0462
0463
0464 #if defined(__CUDA_ARCH__) && defined(NDEBUG)
0465
0466 inline __attribute__((noinline)) __host__ __device__ void device_debug_error(
0467 DebugErrorType, char const* condition, char const* file, int line)
0468 {
0469 printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0470 file,
0471 line,
0472 condition);
0473 __trap();
0474 }
0475 #elif defined(__HIP__)
0476
0477 inline __host__ void device_debug_error(DebugErrorType which,
0478 char const* condition,
0479 char const* file,
0480 int line)
0481 {
0482 return ::celeritas::throw_debug_error({which, condition, file, line});
0483 }
0484
0485
0486
0487 inline __attribute__((noinline)) __device__ void device_debug_error(
0488 DebugErrorType, char const* condition, char const* file, int line)
0489 {
0490 printf("%s:%u:\nceleritas: internal assertion failed: %s\n",
0491 file,
0492 line,
0493 condition);
0494 abort();
0495 }
0496 #endif
0497
0498
0499 }