Actual source code: petscdevicetypes.h

  1: #ifndef PETSCDEVICETYPES_H
  2: #define PETSCDEVICETYPES_H

  4: #include <petscsys.h>

  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

 14: /* SUBMANSEC = Sys */

 16: /*E
 17:   PetscMemType - Memory type of a pointer

 19:   Developer Note:
 20:   Encoding of the bitmask in binary: xxxxyyyz

 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

 32:   Other types of memory, e.g., CUDA managed memory, can be added when needed.

 34:   Level: beginner

 36:   Notes:
 37:   `PETSC_MEMTYPE_KOKKOS` depends on the Kokkos backend configuration

 39:   Developer Notes:
 40:   This enum uses a function (`PetscMemTypeToString()`) to convert to string representation so
 41:   cannot be used in `PetscOptionsEnum()`.

 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

 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)

 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), "");

 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), "");

 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

 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)

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: }

119: #define PETSC_OFFLOAD_VECKOKKOS_DEPRECATED PETSC_OFFLOAD_VECKOKKOS PETSC_DEPRECATED_ENUM("Use PETSC_OFFLOAD_KOKKOS (since version 3.17.0)")

121: /*E
122:   PetscOffloadMask - indicates which memory (CPU, GPU, or none) contains valid data

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.

130:   Developer Notes:
131:   This enum uses a function (`PetscOffloadMaskToString()`) to convert to string representation so
132:   cannot be used in `PetscOptionsEnum()`.

134:   Level: developer

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;

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)

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), "");

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), "");

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

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)

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: }

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: }

213: /*E
214:   PetscDeviceInitType - Initialization strategy for `PetscDevice`

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

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.

224:   Level: beginner

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[];

236: /*E
237:   PetscDeviceType - Kind of accelerator device backend

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

245:   Notes:
246:   One can also use the `PETSC_DEVICE_DEFAULT()` routine to get the current default `PetscDeviceType`.

248:   Level: beginner

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[];

261: /*E
262:   PetscDeviceAttribute - Attribute detailing a property or feature of a `PetscDevice`

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

268:   Level: beginner

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[];

278: /*S
279:   PetscDevice - Object to manage an accelerator "device" (usually a GPU)

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.

286:   Level: beginner

288: .seealso: `PetscDeviceType`, `PetscDeviceInitType`, `PetscDeviceCreate()`,
289: `PetscDeviceConfigure()`, `PetscDeviceDestroy()`, `PetscDeviceContext`,
290: `PetscDeviceContextSetDevice()`, `PetscDeviceContextGetDevice()`, `PetscDeviceGetAttribute()`
291: S*/
292: typedef struct _n_PetscDevice *PetscDevice;

294: /*E
295:   PetscStreamType - Stream blocking mode, indicates how a stream implementation will interact
296:   with the default "NULL" stream, which is usually blocking.

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

303:   Level: intermediate

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[];

315: /*E
316:   PetscDeviceContextJoinMode - Describes the type of join operation to perform in
317:   `PetscDeviceContextJoin()`

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.

323:   Level: beginner

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[];

334: /*S
335:   PetscDeviceContext - Container to manage stream dependencies and the various solver handles
336:   for asynchronous device compute.

338:   Level: beginner

340: .seealso: `PetscDevice`, `PetscDeviceContextCreate()`, `PetscDeviceContextSetDevice()`,
341: `PetscDeviceContextDestroy()`, `PetscDeviceContextFork()`, `PetscDeviceContextJoin()`
342: S*/
343: typedef struct _p_PetscDeviceContext *PetscDeviceContext;

345: /*E
346:   PetscDeviceCopyMode - Describes the copy direction of a device-aware memcpy

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

354:   Level: beginner

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[];

367: PETSC_NODISCARD static inline PetscDeviceCopyMode PetscOffloadMaskToDeviceCopyMode(PetscOffloadMask dest, PetscOffloadMask src)
368: {
369:   PetscDeviceCopyMode mode;

371:   PetscAssertAbort(dest != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy to unallocated");
372:   PetscAssertAbort(src != PETSC_OFFLOAD_UNALLOCATED, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot copy from unallocated");

374:   if (PetscOffloadDevice(dest)) {
375:     mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOD : PETSC_DEVICE_COPY_DTOD;
376:   } else {
377:     mode = PetscOffloadHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH;
378:   }
379:   return mode;
380: }

382: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 PetscDeviceCopyMode PetscMemTypeToDeviceCopyMode(PetscMemType dest, PetscMemType src)
383: {
384:   if (PetscMemTypeHost(dest)) {
385:     return PetscMemTypeHost(src) ? PETSC_DEVICE_COPY_HTOH : PETSC_DEVICE_COPY_DTOH;
386:   } else {
387:     return PetscMemTypeDevice(src) ? PETSC_DEVICE_COPY_DTOD : PETSC_DEVICE_COPY_HTOD;
388:   }
389: }

391: /*E
392:   PetscMemoryAccessMode - Describes the intended usage of a memory region

394: + PETSC_MEMORY_ACCESS_READ       - Read only
395: . PETSC_MEMORY_ACCESS_WRITE      - Write only
396: - PETSC_MEMORY_ACCESS_READ_WRITE - Read and write

398:   Notes:
399:   This `enum` is a bitmask with the following encoding (assuming 2 bit)\:

401: .vb
402:   PETSC_MEMORY_ACCESS_READ       = 0b01
403:   PETSC_MEMORY_ACCESS_WRITE      = 0b10
404:   PETSC_MEMORY_ACCESS_READ_WRITE = 0b11

406:   // consequently
407:   PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE = PETSC_MEMORY_ACCESS_READ_WRITE
408: .ve

410:   The following convience macros are also provided\:

412:   - `PetscMemoryAccessRead(mode)`\: `true` if `mode` is any kind of read, `false` otherwise
413:   - `PetscMemoryAccessWrite(mode)`\: `true` if `mode` is any kind of write, `false` otherwise

415:   Developer Notes:
416:   This enum uses a function (`PetscMemoryAccessModeToString()`) to convert values to string
417:   representation, so cannot be used in `PetscOptionsEnum()`.

419:   Level: beginner

421: .seealso: `PetscMemoryAccessModeToString()`, `PetscDevice`, `PetscDeviceContext`
422: E*/
423: typedef enum {
424:   PETSC_MEMORY_ACCESS_READ       = 0x1, // 01
425:   PETSC_MEMORY_ACCESS_WRITE      = 0x2, // 10
426:   PETSC_MEMORY_ACCESS_READ_WRITE = 0x3, // 11
427: } PetscMemoryAccessMode;

429: #define PetscMemoryAccessRead(m)  (((m)&PETSC_MEMORY_ACCESS_READ) == PETSC_MEMORY_ACCESS_READ)
430: #define PetscMemoryAccessWrite(m) (((m)&PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_WRITE)

432: #if defined(__cplusplus)
433:   #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
434:     #pragma GCC diagnostic push
435:     #pragma GCC diagnostic ignored "-Wtautological-compare"
436:   #endif
437: static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ), "");
438: static_assert(PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_READ_WRITE), "");
439: static_assert(!PetscMemoryAccessRead(PETSC_MEMORY_ACCESS_WRITE), "");
440: static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_WRITE), "");
441: static_assert(PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ_WRITE), "");
442: static_assert(!PetscMemoryAccessWrite(PETSC_MEMORY_ACCESS_READ), "");
443: static_assert((PETSC_MEMORY_ACCESS_READ | PETSC_MEMORY_ACCESS_WRITE) == PETSC_MEMORY_ACCESS_READ_WRITE, "");
444:   #if PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING
445:     #pragma GCC diagnostic pop
446:   #endif
447: #endif

449: PETSC_NODISCARD static inline PETSC_CONSTEXPR_14 const char *PetscMemoryAccessModeToString(PetscMemoryAccessMode mode)
450: {
451: #define PETSC_CASE_RETURN(v) \
452: case v: \
453:   return PetscStringize(v)

455:   switch (mode) {
456:     PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ);
457:     PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_WRITE);
458:     PETSC_CASE_RETURN(PETSC_MEMORY_ACCESS_READ_WRITE);
459:   }
460:   PetscUnreachable();
461:   return "invalid";
462: #undef PETSC_CASE_RETURN
463: }

465: #undef PETSC_SHOULD_SILENCE_GCC_TAUTOLOGICAL_COMPARE_WARNING

467: #endif /* PETSCDEVICETYPES_H */