1 #ifndef PETSCDEVICETYPES_H 2 #define PETSCDEVICETYPES_H 3 4 #include <petscsys.h> /*I <petscdevicetypes.h> I*/ 5 6 // Some overzealous older gcc versions warn that the comparisons below are always true. Neat 7 // that it can detect this, but the tautology *is* the point of the static_assert()! 8 #if defined(__GNUC__) && __GNUC__ >= 6 && !PetscDefined(HAVE_WINDOWS_COMPILERS) 9 #define PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 1 10 #else 11 #define PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 0 12 #endif 13 14 /* SUBMANSEC = Sys */ 15 16 /*E 17 PetscMemType - Memory type of a pointer 18 19 Developer Note: 20 Encoding of the bitmask in binary: xxxxyyyz 21 22 $ z = 0 - Host memory 23 $ z = 1 - Device memory 24 $ yyy = 000 - CUDA-related memory 25 $ yyy = 001 - HIP-related memory 26 $ yyy = 010 - SYCL-related memory 27 $ xxxxyyy1 = 0000,0001 - CUDA memory 28 $ xxxxyyy1 = 0001,0001 - CUDA NVSHMEM memory 29 $ xxxxyyy1 = 0000,0011 - HIP memory 30 $ xxxxyyy1 = 0000,0101 - SYCL memory 31 32 Other types of memory, e.g., CUDA managed memory, can be added when needed. 33 34 Level: beginner 35 36 Notes: 37 `PETSC_MEMTYPE_KOKKOS` depends on the Kokkos backend configuration 38 39 Developer Notes: 40 This enum uses a function (`PetscMemTypeToString()`) to convert to string representation so 41 cannot be used in `PetscOptionsEnum()`. 42 43 .seealso: `PetscMemTypeToString()`, `VecGetArrayAndMemType()`, 44 `PetscSFBcastWithMemTypeBegin()`, `PetscSFReduceWithMemTypeBegin()` 45 E*/ 46 typedef enum { 47 PETSC_MEMTYPE_HOST = 0, 48 PETSC_MEMTYPE_DEVICE = 0x01, 49 PETSC_MEMTYPE_CUDA = 0x01, 50 PETSC_MEMTYPE_NVSHMEM = 0x11, 51 PETSC_MEMTYPE_HIP = 0x03, 52 PETSC_MEMTYPE_SYCL = 0x05, 53 } PetscMemType; 54 #if PetscDefined(HAVE_CUDA) 55 #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_CUDA 56 #elif PetscDefined(HAVE_HIP) 57 #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_HIP 58 #elif PetscDefined(HAVE_SYCL) 59 #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_SYCL 60 #else 61 #define PETSC_MEMTYPE_KOKKOS PETSC_MEMTYPE_HOST 62 #endif 63 64 #define PetscMemTypeHost(m) (((m)&0x1) == PETSC_MEMTYPE_HOST) 65 #define PetscMemTypeDevice(m) (((m)&0x1) == PETSC_MEMTYPE_DEVICE) 66 #define PetscMemTypeCUDA(m) (((m)&0xF) == PETSC_MEMTYPE_CUDA) 67 #define PetscMemTypeHIP(m) (((m)&0xF) == PETSC_MEMTYPE_HIP) 68 #define PetscMemTypeSYCL(m) (((m)&0xF) == PETSC_MEMTYPE_SYCL) 69 #define PetscMemTypeNVSHMEM(m) ((m) == PETSC_MEMTYPE_NVSHMEM) 70 71 #if defined(__cplusplus) 72 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 73 #pragma GCC diagnostic push 74 #pragma GCC diagnostic ignored "-Wtautological-compare" 75 #endif 76 static_assert(PetscMemTypeHost(PETSC_MEMTYPE_HOST), ""); 77 static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_DEVICE), ""); 78 static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_CUDA), ""); 79 static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_HIP), ""); 80 static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_SYCL), ""); 81 static_assert(!PetscMemTypeHost(PETSC_MEMTYPE_NVSHMEM), ""); 82 83 static_assert(!PetscMemTypeDevice(PETSC_MEMTYPE_HOST), ""); 84 static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_DEVICE), ""); 85 static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_CUDA), ""); 86 static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_HIP), ""); 87 static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_SYCL), ""); 88 static_assert(PetscMemTypeDevice(PETSC_MEMTYPE_NVSHMEM), ""); 89 90 static_assert(PetscMemTypeCUDA(PETSC_MEMTYPE_CUDA), ""); 91 static_assert(PetscMemTypeCUDA(PETSC_MEMTYPE_NVSHMEM), ""); 92 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 93 #pragma GCC diagnostic pop 94 #endif 95 #endif // __cplusplus 96 97 PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscMemTypeToString(PetscMemType mtype) 98 { 99 #ifdef __cplusplus 100 static_assert(PETSC_MEMTYPE_CUDA == PETSC_MEMTYPE_DEVICE, ""); 101 #endif 102 #define PETSC_CASE_NAME(v) \ 103 case v: \ 104 return PetscStringize(v) 105 106 switch (mtype) { 107 PETSC_CASE_NAME(PETSC_MEMTYPE_HOST); 108 /* PETSC_CASE_NAME(PETSC_MEMTYPE_DEVICE); same as PETSC_MEMTYPE_CUDA */ 109 PETSC_CASE_NAME(PETSC_MEMTYPE_CUDA); 110 PETSC_CASE_NAME(PETSC_MEMTYPE_NVSHMEM); 111 PETSC_CASE_NAME(PETSC_MEMTYPE_HIP); 112 PETSC_CASE_NAME(PETSC_MEMTYPE_SYCL); 113 } 114 PetscUnreachable(); 115 return "invalid"; 116 #undef PETSC_CASE_NAME 117 } 118 119 #define PETSC_OFFLOAD_VECKOKKOS_DEPRECATED PETSC_OFFLOAD_VECKOKKOS PETSC_DEPRECATED_ENUM("Use PETSC_OFFLOAD_KOKKOS (since version 3.17.0)") 120 121 /*E 122 PetscOffloadMask - indicates which memory (CPU, GPU, or none) contains valid data 123 124 $ PETSC_OFFLOAD_UNALLOCATED - no memory contains valid matrix entries; NEVER used for vectors 125 $ PETSC_OFFLOAD_GPU - GPU has valid vector/matrix entries 126 $ PETSC_OFFLOAD_CPU - CPU has valid vector/matrix entries 127 $ PETSC_OFFLOAD_BOTH - Both GPU and CPU have valid vector/matrix entries and they match 128 $ PETSC_OFFLOAD_KOKKOS - Reserved for Kokkos matrix and vector. It means the offload is managed by Kokkos, thus this flag itself cannot tell you where the valid data is. 129 130 Developer Notes: 131 This enum uses a function (`PetscOffloadMaskToString()`) to convert to string representation so 132 cannot be used in `PetscOptionsEnum()`. 133 134 Level: developer 135 136 .seealso: `PetscOffloadMaskToString()`, `PetscOffloadMaskToMemType()`, `PetscOffloadMaskToDeviceCopyMode()` 137 E*/ 138 typedef enum { 139 PETSC_OFFLOAD_UNALLOCATED = 0x0, 140 PETSC_OFFLOAD_CPU = 0x1, 141 PETSC_OFFLOAD_GPU = 0x2, 142 PETSC_OFFLOAD_BOTH = 0x3, 143 PETSC_OFFLOAD_VECKOKKOS_DEPRECATED = 0x100, 144 PETSC_OFFLOAD_KOKKOS = 0x100 145 } PetscOffloadMask; 146 147 #define PetscOffloadUnallocated(m) ((m) == PETSC_OFFLOAD_UNALLOCATED) 148 #define PetscOffloadHost(m) (((m)&PETSC_OFFLOAD_CPU) == PETSC_OFFLOAD_CPU) 149 #define PetscOffloadDevice(m) (((m)&PETSC_OFFLOAD_GPU) == PETSC_OFFLOAD_GPU) 150 #define PetscOffloadBoth(m) ((m) == PETSC_OFFLOAD_BOTH) 151 152 #if defined(__cplusplus) 153 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 154 #pragma GCC diagnostic push 155 #pragma GCC diagnostic ignored "-Wtautological-compare" 156 #endif 157 static_assert(!PetscOffloadHost(PETSC_OFFLOAD_UNALLOCATED), ""); 158 static_assert(PetscOffloadHost(PETSC_OFFLOAD_BOTH), ""); 159 static_assert(!PetscOffloadHost(PETSC_OFFLOAD_GPU), ""); 160 static_assert(PetscOffloadHost(PETSC_OFFLOAD_BOTH), ""); 161 static_assert(!PetscOffloadHost(PETSC_OFFLOAD_KOKKOS), ""); 162 163 static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_UNALLOCATED), ""); 164 static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_CPU), ""); 165 static_assert(PetscOffloadDevice(PETSC_OFFLOAD_GPU), ""); 166 static_assert(PetscOffloadDevice(PETSC_OFFLOAD_BOTH), ""); 167 static_assert(!PetscOffloadDevice(PETSC_OFFLOAD_KOKKOS), ""); 168 169 static_assert(PetscOffloadBoth(PETSC_OFFLOAD_BOTH), ""); 170 static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_CPU), ""); 171 static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_GPU), ""); 172 static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_GPU), ""); 173 static_assert(!PetscOffloadBoth(PETSC_OFFLOAD_KOKKOS), ""); 174 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 175 #pragma GCC diagnostic pop 176 #endif 177 #endif // __cplusplus 178 179 PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscOffloadMaskToString(PetscOffloadMask mask) 180 { 181 #define PETSC_CASE_RETURN(v) \ 182 case v: \ 183 return PetscStringize(v) 184 185 switch (mask) { 186 PETSC_CASE_RETURN(PETSC_OFFLOAD_UNALLOCATED); 187 PETSC_CASE_RETURN(PETSC_OFFLOAD_CPU); 188 PETSC_CASE_RETURN(PETSC_OFFLOAD_GPU); 189 PETSC_CASE_RETURN(PETSC_OFFLOAD_BOTH); 190 PETSC_CASE_RETURN(PETSC_OFFLOAD_KOKKOS); 191 } 192 PetscUnreachable(); 193 return "invalid"; 194 #undef PETSC_CASE_RETURN 195 } 196 197 PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 PetscMemType PetscOffloadMaskToMemType(PetscOffloadMask mask) 198 { 199 switch (mask) { 200 case PETSC_OFFLOAD_UNALLOCATED: 201 case PETSC_OFFLOAD_CPU: 202 return PETSC_MEMTYPE_HOST; 203 case PETSC_OFFLOAD_GPU: 204 case PETSC_OFFLOAD_BOTH: 205 return PETSC_MEMTYPE_DEVICE; 206 case PETSC_OFFLOAD_KOKKOS: 207 return PETSC_MEMTYPE_KOKKOS; 208 } 209 PetscUnreachable(); 210 return PETSC_MEMTYPE_HOST; 211 } 212 213 /*E 214 PetscDeviceInitType - Initialization strategy for `PetscDevice` 215 216 $ PETSC_DEVICE_INIT_NONE - PetscDevice is never initialized 217 $ PETSC_DEVICE_INIT_LAZY - PetscDevice is initialized on demand 218 $ PETSC_DEVICE_INIT_EAGER - PetscDevice is initialized as soon as possible 219 220 Notes: 221 `PETSC_DEVICE_INIT_NONE` implies that any initialization of `PetscDevice` is disallowed and 222 doing so results in an error. Useful to ensure that no accelerator is used in a program. 223 224 Level: beginner 225 226 .seealso: `PetscDevice`, `PetscDeviceType`, `PetscDeviceInitialize()`, 227 `PetscDeviceInitialized()`, `PetscDeviceCreate()` 228 E*/ 229 typedef enum { 230 PETSC_DEVICE_INIT_NONE, 231 PETSC_DEVICE_INIT_LAZY, 232 PETSC_DEVICE_INIT_EAGER 233 } PetscDeviceInitType; 234 PETSC_EXTERN const char *const PetscDeviceInitTypes[]; 235 236 /*E 237 PetscDeviceType - Kind of accelerator device backend 238 239 $ PETSC_DEVICE_HOST - Host, no accelerator backend found 240 $ PETSC_DEVICE_CUDA - CUDA enabled GPU 241 $ PETSC_DEVICE_HIP - ROCM/HIP enabled GPU 242 $ PETSC_DEVICE_SYCL - SYCL enabled device 243 $ PETSC_DEVICE_MAX - Always 1 greater than the largest valid PetscDeviceType, invalid type, do not use 244 245 Notes: 246 One can also use the `PETSC_DEVICE_DEFAULT()` routine to get the current default `PetscDeviceType`. 247 248 Level: beginner 249 250 .seealso: `PetscDevice`, `PetscDeviceInitType`, `PetscDeviceCreate()`, `PETSC_DEVICE_DEFAULT()` 251 E*/ 252 typedef enum { 253 PETSC_DEVICE_HOST, 254 PETSC_DEVICE_CUDA, 255 PETSC_DEVICE_HIP, 256 PETSC_DEVICE_SYCL, 257 PETSC_DEVICE_MAX 258 } PetscDeviceType; 259 PETSC_EXTERN const char *const PetscDeviceTypes[]; 260 261 /*E 262 PetscDeviceAttribute - Attribute detailing a property or feature of a `PetscDevice` 263 264 $ PETSC_DEVICE_ATTR_SIZE_T_SHARED_MEM_PER_BLOCK - The maximum amount of shared memory per block in a 265 device kernel 266 $ PETSC_DEVICE_ATTR_MAX - Invalid attribute, do not use 267 268 Level: beginner 269 270 .seealso: `PetscDevice`, `PetscDeviceGetAttribute()` 271 E*/ 272 typedef enum { 273 PETSC_DEVICE_ATTR_SIZE_T_SHARED_MEM_PER_BLOCK, 274 PETSC_DEVICE_ATTR_MAX 275 } PetscDeviceAttribute; 276 PETSC_EXTERN const char *const PetscDeviceAttributes[]; 277 278 /*S 279 PetscDevice - Object to manage an accelerator "device" (usually a GPU) 280 281 Notes: 282 This object is used to house configuration and state of a device, but does not offer any 283 ability to interact with or drive device computation. This functionality is facilitated 284 instead by the `PetscDeviceContext` object. 285 286 Level: beginner 287 288 .seealso: `PetscDeviceType`, `PetscDeviceInitType`, `PetscDeviceCreate()`, 289 `PetscDeviceConfigure()`, `PetscDeviceDestroy()`, `PetscDeviceContext`, 290 `PetscDeviceContextSetDevice()`, `PetscDeviceContextGetDevice()`, `PetscDeviceGetAttribute()` 291 S*/ 292 typedef struct _n_PetscDevice *PetscDevice; 293 294 /*E 295 PetscStreamType - Stream blocking mode, indicates how a stream implementation will interact 296 with the default "NULL" stream, which is usually blocking. 297 298 $ PETSC_STREAM_GLOBAL_BLOCKING - Alias for NULL stream. Any stream of this type will block the host for all other streams to finish work before starting its operations. 299 $ PETSC_STREAM_DEFAULT_BLOCKING - Stream will act independent of other streams, but will still be blocked by actions on the NULL stream. 300 $ PETSC_STREAM_GLOBAL_NONBLOCKING - Stream is truly asynchronous, and is blocked by nothing, not even the NULL stream. 301 $ PETSC_STREAM_MAX - Always 1 greater than the largest PetscStreamType, do not use 302 303 Level: intermediate 304 305 .seealso: `PetscDeviceContextSetStreamType()`, `PetscDeviceContextGetStreamType()` 306 E*/ 307 typedef enum { 308 PETSC_STREAM_GLOBAL_BLOCKING, 309 PETSC_STREAM_DEFAULT_BLOCKING, 310 PETSC_STREAM_GLOBAL_NONBLOCKING, 311 PETSC_STREAM_MAX 312 } PetscStreamType; 313 PETSC_EXTERN const char *const PetscStreamTypes[]; 314 315 /*E 316 PetscDeviceContextJoinMode - Describes the type of join operation to perform in 317 `PetscDeviceContextJoin()` 318 319 $ PETSC_DEVICE_CONTEXT_JOIN_DESTROY - Destroy all incoming sub-contexts after join. 320 $ PETSC_DEVICE_CONTEXT_JOIN_SYNC - Synchronize incoming sub-contexts after join. 321 $ PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC - Do not synchronize incoming sub-contexts after join. 322 323 Level: beginner 324 325 .seealso: `PetscDeviceContext`, `PetscDeviceContextFork()`, `PetscDeviceContextJoin()` 326 E*/ 327 typedef enum { 328 PETSC_DEVICE_CONTEXT_JOIN_DESTROY, 329 PETSC_DEVICE_CONTEXT_JOIN_SYNC, 330 PETSC_DEVICE_CONTEXT_JOIN_NO_SYNC 331 } PetscDeviceContextJoinMode; 332 PETSC_EXTERN const char *const PetscDeviceContextJoinModes[]; 333 334 /*S 335 PetscDeviceContext - Container to manage stream dependencies and the various solver handles 336 for asynchronous device compute. 337 338 Level: beginner 339 340 .seealso: `PetscDevice`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`, 341 `PetscDeviceContextDestroy()`, `PetscDeviceContextFork()`, `PetscDeviceContextJoin()` 342 S*/ 343 typedef struct _p_PetscDeviceContext *PetscDeviceContext; 344 345 /*E 346 PetscDeviceCopyMode - Describes the copy direction of a device-aware memcpy 347 348 $ PETSC_DEVICE_COPY_HTOH - Copy from host memory to host memory 349 $ PETSC_DEVICE_COPY_DTOH - Copy from device memory to host memory 350 $ PETSC_DEVICE_COPY_HTOD - Copy from host memory to device memory 351 $ PETSC_DEVICE_COPY_DTOD - Copy from device memory to device memory 352 $ PETSC_DEVICE_COPY_AUTO - Infer the copy direction from the pointers 353 354 Level: beginner 355 356 .seealso: `PetscDeviceArrayCopy()`, `PetscDeviceMemcpy()` 357 E*/ 358 typedef enum { 359 PETSC_DEVICE_COPY_HTOH, 360 PETSC_DEVICE_COPY_DTOH, 361 PETSC_DEVICE_COPY_HTOD, 362 PETSC_DEVICE_COPY_DTOD, 363 PETSC_DEVICE_COPY_AUTO, 364 } PetscDeviceCopyMode; 365 PETSC_EXTERN const char *const PetscDeviceCopyModes[]; 366 367 PETSC_NODISCARD static inline PetscDeviceCopyMode PetscOffloadMaskToDeviceCopyMode(PetscOffloadMask dest, PetscOffloadMask src) 368 { 369 PetscDeviceCopyMode mode; 370 371 PetscFunctionBegin; 372 PetscAssertAbort(dest != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy to unallocated"); 373 PetscAssertAbort(src != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy from unallocated"); 374 375 if (PetscOffloadDevice(dest)) { 376 mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOD : PETSC_DEVICE_COPY_DTOD; 377 } else { 378 mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH; 379 } 380 PetscFunctionReturn(mode); 381 } 382 383 PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 PetscDeviceCopyMode PetscMemTypeToDeviceCopyMode(PetscMemType dest, PetscMemType src) 384 { 385 if (PetscMemTypeHost(dest)) { 386 return PetscMemTypeHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH; 387 } else { 388 return PetscMemTypeDevice(src) ? PETSC_DEVICE_COPY_DTOD : PETSC_DEVICE_COPY_HTOD; 389 } 390 } 391 392 /*E 393 PetscMemoryAccessMode - Describes the intended usage of a memory region 394 395 + PETSC_MEMORY_ACCESS_READ - Read only 396 . PETSC_MEMORY_ACCESS_WRITE - Write only 397 - PETSC_MEMORY_ACCESS_READ_WRITE - Read and write 398 399 Notes: 400 This `enum` is a bitmask with the following encoding (assuming 2 bit)\: 401 402 .vb 403 PETSC_MEMORY_ACCESS_READ = 0b01 404 PETSC_MEMORY_ACCESS_WRITE = 0b10 405 PETSC_MEMORY_ACCESS_READ_WRITE = 0b11 406 407 // consequently 408 PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE = PETSC_MEMORY_ACCESS_READ_WRITE 409 .ve 410 411 The following convience macros are also provided\: 412 413 - `PetscMemoryAccessRead(mode)`\: `true` if `mode` is any kind of read, `false` otherwise 414 - `PetscMemoryAccessWrite(mode)`\: `true` if `mode` is any kind of write, `false` otherwise 415 416 Developer Notes: 417 This enum uses a function (`PetscMemoryAccessModeToString()`) to convert values to string 418 representation, so cannot be used in `PetscOptionsEnum()`. 419 420 Level: beginner 421 422 .seealso: `PetscMemoryAccessModeToString()`, `PetscDevice`, `PetscDeviceContext` 423 E*/ 424 typedef enum { 425 PETSC_MEMORY_ACCESS_READ = 0x1, // 01 426 PETSC_MEMORY_ACCESS_WRITE = 0x2, // 10 427 PETSC_MEMORY_ACCESS_READ_WRITE = 0x3, // 11 428 } PetscMemoryAccessMode; 429 430 #define PetscMemoryAccessRead(m) (((m)&PETSC_MEMORY_ACCESS_READ) == PETSC_MEMORY_ACCESS_READ) 431 #define PetscMemoryAccessWrite(m) (((m)&PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_WRITE) 432 433 #if defined(__cplusplus) 434 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 435 #pragma GCC diagnostic push 436 #pragma GCC diagnostic ignored "-Wtautological-compare" 437 #endif 438 static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ), ""); 439 static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ_WRITE), ""); 440 static_assert(!PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_WRITE), ""); 441 static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_WRITE), ""); 442 static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ_WRITE), ""); 443 static_assert(!PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ), ""); 444 static_assert((PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_READ_WRITE, ""); 445 #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 446 #pragma GCC diagnostic pop 447 #endif 448 #endif 449 450 PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscMemoryAccessModeToString(PetscMemoryAccessMode mode) 451 { 452 #define PETSC_CASE_RETURN(v) \ 453 case v: \ 454 return PetscStringize(v) 455 456 switch (mode) { 457 PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ); 458 PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_WRITE); 459 PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ_WRITE); 460 } 461 PetscUnreachable(); 462 return "invalid"; 463 #undef PETSC_CASE_RETURN 464 } 465 466 #undef PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING 467 468 #endif /* PETSCDEVICETYPES_H */ 469