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