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